diff --git a/ci.hocon b/ci.hocon
index 5c04f82cf99d06dc864f4b1ae2ae87a4c3721224..f50713f267251d23654d97f5da0c96142a88a9f7 100644
--- a/ci.hocon
+++ b/ci.hocon
@@ -36,6 +36,7 @@ logfiles : [
     "com.oracle.truffle.r.native/gnur/R-*/Makeconf"
     "com.oracle.truffle.r.native/gnur/libiconv-*/iconv_configure.log"
     "com.oracle.truffle.r.native/gnur/libiconv-*/iconv_make.log"
+    "*-tests/*.Rout"
   ]
 
 # This is needed by all (Linux) builds but is specific to the module system employed
@@ -127,7 +128,7 @@ gateTestLinuxNFI : ${gateTestCommon} {
 
 gateTestManagedLinux: ${common} {
   environment :  {
-      FASTR_MANAGED : "true"
+      FASTR_RFFI : "managed"
   }
   run : [
     ${gateCmd} ["Versions,JDKReleaseInfo,BuildJavaWithJavac"]
@@ -155,7 +156,7 @@ gateStyle : ${common} {
     ECLIPSE_EXE : "$ECLIPSE/eclipse"
   }
   run : [
-    ${gateCmd} ["Versions,JDKReleaseInfo,Pylint,Canonicalization Check,BuildJavaWithJavac,IDEConfigCheck,CodeFormatCheck,Checkstyle,Copyright check, UnitTests: ExpectedTestOutput file check"]
+    ${gateCmd} ["Versions,JDKReleaseInfo,Pylint,Canonicalization Check,BuildJavaWithJavac,IDEConfigCheck,CodeFormatCheck,Checkstyle,Copyright check,UnitTests: ExpectedTestOutput file check"]
   ]
 }
 
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 eaa5cfbb487b3a1e1c357e329afb3189b833253d..f8d34c719561803502b83654cad520a4bd6ca95c 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
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.engine;
 
-import java.io.File;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -34,28 +33,27 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.TruffleLanguage.ContextReference;
 import com.oracle.truffle.api.dsl.UnsupportedSpecializationException;
 import com.oracle.truffle.api.frame.Frame;
-import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.launcher.StartupTiming;
 import com.oracle.truffle.r.library.graphics.RGraphics;
 import com.oracle.truffle.r.nodes.RASTBuilder;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinPackages;
-import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNode;
 import com.oracle.truffle.r.nodes.control.BreakException;
 import com.oracle.truffle.r.nodes.control.NextException;
 import com.oracle.truffle.r.nodes.function.CallMatcherNode.CallMatcherGenericNode;
@@ -78,7 +76,6 @@ import com.oracle.truffle.r.runtime.RParserFactory;
 import com.oracle.truffle.r.runtime.RProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.RootWithBody;
 import com.oracle.truffle.r.runtime.SubstituteVirtualFrame;
@@ -101,6 +98,8 @@ import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
@@ -159,9 +158,10 @@ final class REngine implements Engine, Engine.Timings {
         suppressWarnings = true;
         MaterializedFrame baseFrame = RRuntime.createNonFunctionFrame("base");
         REnvironment.baseInitialize(baseFrame, globalFrame);
-        RBuiltinPackages.loadBase(baseFrame);
+        RBuiltinPackages.loadBase(context.getLanguage(), baseFrame);
         RGraphics.initialize();
         if (FastROptions.LoadProfiles.getBooleanValue()) {
+            StartupTiming.timestamp("Before Profiles Loaded");
             /*
              * eval the system/site/user profiles. Experimentally GnuR does not report warnings
              * during system profile evaluation, but does for the site/user profiles.
@@ -190,13 +190,14 @@ final class REngine implements Engine, Engine.Timings {
                     throw new RInternalError(e, "error while parsing user profile from %s", userProfile.getName());
                 }
             }
-            if (!(context.getStartParams().getRestoreAction() == SA_TYPE.NORESTORE)) {
+            if (context.getStartParams().restore()) {
                 // call sys.load.image(".RData", RCmdOption.QUIET
-                checkAndRunStartupShutdownFunction("sys.load.image", new String[]{"\".RData\"", context.getStartParams().getQuiet() ? "TRUE" : "FALSE"});
-                context.getConsoleHandler().setHistoryFrom(new File("./.Rhistory"));
+                checkAndRunStartupShutdownFunction("sys.load.image", new String[]{"\".RData\"", context.getStartParams().isQuiet() ? "TRUE" : "FALSE"});
             }
             checkAndRunStartupShutdownFunction(".First");
             checkAndRunStartupShutdownFunction(".First.sys");
+
+            StartupTiming.timestamp("After Profiles Loaded");
         }
     }
 
@@ -233,6 +234,11 @@ final class REngine implements Engine, Engine.Timings {
         return this;
     }
 
+    @Override
+    public MaterializedFrame getGlobalFrame() {
+        return globalFrame;
+    }
+
     @Override
     public long elapsedTimeInNanos() {
         return System.nanoTime() - startTime;
@@ -264,24 +270,23 @@ final class REngine implements Engine, Engine.Timings {
             throw e;
         } catch (RError e) {
             // RError prints the correct result on the console during construction
-            RInternalError.reportError(e);
             return null;
         } catch (UnsupportedSpecializationException use) {
             String message = "FastR internal error: Unsupported specialization in node " + use.getNode().getClass().getSimpleName() + " - supplied values: " +
                             Arrays.asList(use.getSuppliedValues()).stream().map(v -> v == null ? "null" : v.getClass().getSimpleName()).collect(Collectors.toList());
-            context.getConsoleHandler().printErrorln(message);
+            context.getConsole().printErrorln(message);
             RInternalError.reportError(use);
             return null;
         } catch (Throwable t) {
-            context.getConsoleHandler().printErrorln("FastR internal error: " + t.getMessage());
+            context.getConsole().printErrorln("FastR internal error: " + t.getMessage());
             RInternalError.reportError(t);
             return null;
         }
     }
 
-    private static List<RSyntaxNode> parseImpl(Source source) throws ParseException {
+    private List<RSyntaxNode> parseImpl(Source source) throws ParseException {
         RParserFactory.Parser<RSyntaxNode> parser = RParserFactory.getParser();
-        return parser.script(source, new RASTBuilder());
+        return parser.script(source, new RASTBuilder(), context.getLanguage());
     }
 
     @Override
@@ -292,14 +297,18 @@ final class REngine implements Engine, Engine.Timings {
     }
 
     @Override
-    @SuppressWarnings("deprecation")
     public CallTarget parseToCallTarget(Source source, MaterializedFrame executionFrame) throws ParseException {
         if (source == Engine.GET_CONTEXT) {
             /*
              * The "get context" operations should be executed with as little influence on the
              * actual engine as possible, therefore this special case takes care of it explicitly.
              */
-            return Truffle.getRuntime().createCallTarget(new RootNode(TruffleRLanguage.class, source.createUnavailableSection(), new FrameDescriptor()) {
+            return Truffle.getRuntime().createCallTarget(new RootNode(context.getLanguage()) {
+                @Override
+                public SourceSection getSourceSection() {
+                    return source.createUnavailableSection();
+                }
+
                 @Override
                 public Object execute(VirtualFrame frame) {
                     return JavaInterop.asTruffleValue(context);
@@ -329,12 +338,15 @@ final class REngine implements Engine, Engine.Timings {
         private final MaterializedFrame executionFrame;
         @Children private final DirectCallNode[] calls;
         private final boolean printResult;
+        private final SourceSection sourceSection;
+        private final ContextReference<RContext> contextReference;
 
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+        @Child private R2Foreign r2Foreign = R2ForeignNodeGen.create();
 
-        @SuppressWarnings("deprecation")
         PolyglotEngineRootNode(List<RSyntaxNode> statements, SourceSection sourceSection, MaterializedFrame executionFrame) {
-            super(TruffleRLanguage.class, sourceSection, new FrameDescriptor());
+            super(context.getLanguage());
+            this.sourceSection = sourceSection;
+            this.contextReference = context.getLanguage().getContextReference();
             // can't print if initializing the system in embedded mode (no builtins yet)
             this.printResult = !sourceSection.getSource().getName().equals(RSource.Internal.INIT_EMBEDDED.string) && sourceSection.getSource().isInteractive();
             this.statements = statements;
@@ -342,6 +354,11 @@ final class REngine implements Engine, Engine.Timings {
             this.calls = new DirectCallNode[statements.size()];
         }
 
+        @Override
+        public SourceSection getSourceSection() {
+            return sourceSection;
+        }
+
         /**
          * The normal {@link #doMakeCallTarget} happens first, then we actually run the call using
          * the standard FastR machinery, saving and restoring the {@link RContext}, since we have no
@@ -350,31 +367,31 @@ final class REngine implements Engine, Engine.Timings {
         @Override
         @ExplodeLoop
         public Object execute(VirtualFrame frame) {
-            RContext oldContext = RContext.getThreadLocalInstance();
-            RContext newContext = TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext);
-            RContext.setThreadLocalInstance(newContext);
+            Object actualFrame = executionFrame != null ? executionFrame : contextReference.get().stateREnvironment.getGlobalFrame();
             try {
                 Object lastValue = RNull.instance;
-                for (int i = 0; i < statements.size(); i++) {
-                    RSyntaxNode node = statements.get(i);
+                for (int i = 0; i < calls.length; i++) {
                     if (calls[i] == null) {
                         CompilerDirectives.transferToInterpreterAndInvalidate();
+                        RSyntaxNode node = statements.get(i);
                         calls[i] = insert(Truffle.getRuntime().createDirectCallNode(doMakeCallTarget(node.asRNode(), RSource.Internal.REPL_WRAPPER.string, printResult, true)));
                     }
-                    lastValue = calls[i].call(new Object[]{executionFrame != null ? executionFrame : newContext.stateREnvironment.getGlobalFrame()});
+                    lastValue = calls[i].call(new Object[]{actualFrame});
                 }
-                return RRuntime.r2Java(lastValue);
+                return r2Foreign.execute(lastValue);
             } catch (ReturnException ex) {
                 return ex.getResult();
             } catch (DebugExitException | JumpToTopLevelException | ExitException | ThreadDeath e) {
+                CompilerDirectives.transferToInterpreter();
                 throw e;
             } catch (RError e) {
                 CompilerDirectives.transferToInterpreter();
                 throw e;
             } catch (Throwable t) {
+                CompilerDirectives.transferToInterpreter();
+                // other errors didn't produce an output yet
+                RInternalError.reportError(t);
                 throw t;
-            } finally {
-                RContext.setThreadLocalInstance(oldContext);
             }
         }
     }
@@ -522,15 +539,24 @@ final class REngine implements Engine, Engine.Timings {
         @Child private GetVisibilityNode visibility = GetVisibilityNode.create();
         @Child private SetVisibilityNode setVisibility = SetVisibilityNode.create();
 
-        @SuppressWarnings("deprecation")
         protected AnonymousRootNode(RNode body, String description, boolean printResult, boolean topLevel) {
-            super(TruffleRLanguage.class, null, new FrameDescriptor());
+            super(context.getLanguage());
             this.body = body;
             this.description = description;
             this.printResult = printResult;
             this.topLevel = topLevel;
         }
 
+        @Override
+        public SourceSection getSourceSection() {
+            return body.getSourceSection();
+        }
+
+        @Override
+        public boolean isInternal() {
+            return RSyntaxNode.isInternal(body.asRSyntaxNode().getLazySourceSection());
+        }
+
         private VirtualFrame prepareFrame(VirtualFrame frame) {
             VirtualFrame vf;
             MaterializedFrame originalFrame = (MaterializedFrame) frameTypeProfile.profile(frame.getArguments()[0]);
@@ -640,7 +666,15 @@ final class REngine implements Engine, Engine.Timings {
             ShareObjectNode.unshare(resultValue);
         } else {
             // this supports printing of non-R values (via toString for now)
-            RContext.getInstance().getConsoleHandler().println(toString(result));
+            String str;
+            if (result == null) {
+                str = "[external object (null)]";
+            } else if (result instanceof CharSequence) {
+                str = "[1] \"" + String.valueOf(result) + "\"";
+            } else {
+                str = String.valueOf(result);
+            }
+            RContext.getInstance().getConsole().println(str);
         }
     }
 
@@ -665,21 +699,6 @@ final class REngine implements Engine, Engine.Timings {
         doMakeCallTarget(call.asRNode(), RSource.Internal.EVAL_WRAPPER.string, false, false).call(callingFrame);
     }
 
-    private static String toString(Object originalResult) {
-        Object result = evaluatePromise(originalResult);
-        result = RRuntime.asAbstractVector(result);
-        // this supports printing of non-R values (via toString for now)
-        if (result instanceof RTypedValue || result instanceof TruffleObject) {
-            return ValuePrinterNode.prettyPrint(result);
-        } else if (result == null) {
-            return "[external object (null)]";
-        } else if (result instanceof CharSequence) {
-            return "[1] \"" + String.valueOf(result) + "\"";
-        } else {
-            return String.valueOf(result);
-        }
-    }
-
     private static Object evaluatePromise(Object value) {
         return value instanceof RPromise ? PromiseHelperNode.evaluateSlowPath((RPromise) value) : value;
     }
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 454eafb417159396083e0e72333299f393f513ff..f20257ce3144f3e3fbd1d52c0d878da62d8dc4fb 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
@@ -33,15 +33,13 @@ import java.util.List;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.r.engine.shell.RCommand;
-import com.oracle.truffle.r.engine.shell.RscriptCommand;
-import com.oracle.truffle.r.nodes.RASTBuilder;
+import com.oracle.truffle.r.launcher.RCommand;
+import com.oracle.truffle.r.launcher.RscriptCommand;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
@@ -54,7 +52,6 @@ import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling;
 import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling;
 import com.oracle.truffle.r.nodes.control.AbstractLoopNode;
 import com.oracle.truffle.r.nodes.control.BlockNode;
-import com.oracle.truffle.r.nodes.control.ForNode;
 import com.oracle.truffle.r.nodes.control.IfNode;
 import com.oracle.truffle.r.nodes.control.ReplacementDispatchNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
@@ -71,11 +68,11 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RSrcref;
-import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.RootWithBody;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -255,7 +252,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
                 Argument<RSyntaxNode> arg = RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, argName, argVal == RSymbol.MISSING ? null : (RSyntaxNode) unwrapToRNode(argVal));
                 resArgs.add(arg);
             }
-            RootCallTarget rootCallTarget = new RASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, resArgs, body, null);
+            RootCallTarget rootCallTarget = RContext.getASTBuilder().rootFunction(RContext.getInstance().getLanguage(), RSyntaxNode.LAZY_DEPARSE, resArgs, body, null);
             FunctionExpressionNode fnExprNode = FunctionExpressionNode.create(RSyntaxNode.LAZY_DEPARSE, rootCallTarget);
             RLanguage result = RDataFactory.createLanguage(fnExprNode);
             return addAttributes(result, list);
@@ -272,14 +269,17 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         return result;
     }
 
-    private static RNode unwrapToRNode(Object objArg) {
+    private RNode unwrapToRNode(Object objArg) {
         Object obj = objArg;
         // obj is RSymbol or a primitive value.
         // A symbol needs to be converted back to a ReadVariableNode
         if (obj instanceof RLanguage) {
             return (RNode) RASTUtils.unwrap(((RLanguage) obj).getRep());
         } else if (obj instanceof RSymbol) {
-            return ReadVariableNode.create(((RSymbol) obj).getName());
+            return RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) obj).getName(), false).asRNode();
+        } else if (obj instanceof RPromise) {
+            // Evaluate promise and return the result as constant.
+            return ConstantNode.create(forcePromise("unwrapToRNode", objArg));
         } else {
             return ConstantNode.create(obj);
         }
@@ -368,9 +368,6 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         boolean gd = RContext.getInstance().stateInstrumentation.setDebugGloballyDisabled(true);
         try {
             return RContext.getEngine().evalFunction(f, null, null, true, null, args);
-        } catch (ReturnException ex) {
-            // cannot throw return exceptions further up.
-            return ex.getResult();
         } finally {
             RContext.getInstance().stateInstrumentation.setDebugGloballyDisabled(gd);
         }
@@ -536,7 +533,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
                     // single statement block, variable parent
                     // note: RepeatingNode is not a RSyntaxElement but the body of a loop is
                     // under the repeating node !
-                    return parent instanceof FunctionDefinitionNode || parent instanceof RootWithBody || parent instanceof IfNode || parent instanceof AbstractLoopNode || ForNode.isLoopBody(node);
+                    return parent instanceof FunctionDefinitionNode || parent instanceof RootWithBody || parent instanceof IfNode || AbstractLoopNode.isLoopBody(node);
                 }
             }
 
@@ -585,7 +582,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     @Override
     public Object rcommandMain(String[] args, String[] env, boolean intern) {
         IORedirect redirect = handleIORedirect(args, intern);
-        Object result = RCommand.doMain(redirect.args, env, false, redirect.in, redirect.out);
+        Object result = RCommand.doMain(redirect.args, env, redirect.in, redirect.out, redirect.err);
         return redirect.getInternResult(result);
     }
 
@@ -594,19 +591,21 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         IORedirect redirect = handleIORedirect(args, intern);
         // TODO argument parsing can fail with ExitException, which needs to be handled correctly in
         // nested context
-        Object result = RscriptCommand.doMain(redirect.args, env, false, redirect.in, redirect.out);
+        Object result = RscriptCommand.doMain(redirect.args, env, redirect.in, redirect.out, redirect.err);
         return redirect.getInternResult(result);
     }
 
     private static final class IORedirect {
         private final InputStream in;
+        private final OutputStream err;
         private final OutputStream out;
         private final String[] args;
         private final boolean intern;
 
-        private IORedirect(InputStream in, OutputStream out, String[] args, boolean intern) {
+        private IORedirect(InputStream in, OutputStream out, OutputStream err, String[] args, boolean intern) {
             this.in = in;
             this.out = out;
+            this.err = err;
             this.args = args;
             this.intern = intern;
         }
@@ -646,6 +645,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
          */
         InputStream in = System.in;
         OutputStream out = System.out;
+        OutputStream err = System.err;
         ArrayList<String> newArgsList = new ArrayList<>();
         int i = 0;
         while (i < args.length) {
@@ -693,7 +693,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
         if (intern) {
             out = new ByteArrayOutputStream();
         }
-        return new IORedirect(in, out, newArgs, intern);
+        return new IORedirect(in, out, err, newArgs, intern);
     }
 
     @Override
@@ -722,12 +722,17 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     }
 
     @Override
-    public Class<? extends TruffleLanguage<?>> getTruffleRLanguage() {
-        return TruffleRLanguage.class;
+    public Class<? extends TruffleRLanguage> getTruffleRLanguage() {
+        return TruffleRLanguageImpl.class;
     }
 
     @Override
     public RAbstractStringVector getClassHierarchy(RAttributable value) {
         return ClassHierarchyNode.getClassHierarchy(value);
     }
+
+    @Override
+    public RContext getCurrentContext() {
+        return TruffleRLanguageImpl.getCurrentContext();
+    }
 }
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/TruffleRLanguageImpl.java
similarity index 78%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
rename to com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
index 58b7dc98bc69f2e56d0a84ba3717e7fe652ef5cf..99f5912b13cc68eff11fa16fe6399d319c9d8882 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/TruffleRLanguageImpl.java
@@ -28,23 +28,17 @@ import java.io.Serializable;
 import java.io.StringWriter;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.Locale;
 import java.util.Map;
 import java.util.stream.Collectors;
-
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.Frame;
-import com.oracle.truffle.api.frame.FrameDescriptor;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
 import com.oracle.truffle.api.instrumentation.ProvidedTags;
 import com.oracle.truffle.api.instrumentation.StandardTags;
 import com.oracle.truffle.api.metadata.ScopeProvider;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.api.vm.PolyglotEngine;
@@ -52,34 +46,39 @@ import com.oracle.truffle.api.vm.PolyglotEngine.Value;
 import com.oracle.truffle.r.engine.interop.RForeignAccessFactoryImpl;
 import com.oracle.truffle.r.nodes.RASTBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinPackages;
+import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.nodes.instrumentation.RSyntaxTags;
 import com.oracle.truffle.r.nodes.qirinterface.QIRInterface;
 import com.oracle.truffle.r.runtime.ExitException;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RAccuracyInfo;
 import com.oracle.truffle.r.runtime.RDeparse;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RValue;
 import com.oracle.truffle.r.runtime.Utils;
 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.RCloseable;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.RScope;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-/**
- * Only does the minimum for running under the debugger. It is not completely clear how to correctly
- * integrate the R startup in {@code RCommand} with this API.
- */
-@TruffleLanguage.Registration(name = "R", version = "0.1", mimeType = {RRuntime.R_APP_MIME, RRuntime.R_TEXT_MIME}, interactive = true)
+@TruffleLanguage.Registration(name = "R", id = "R", version = "3.3.2", mimeType = {RRuntime.R_APP_MIME, RRuntime.R_TEXT_MIME}, interactive = true)
 @ProvidedTags({StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, RSyntaxTags.LoopTag.class})
-public final class TruffleRLanguage extends TruffleLanguage<RContext> implements ScopeProvider<RContext> {
+public final class TruffleRLanguageImpl extends TruffleRLanguage implements ScopeProvider<RContext> {
+
+    private final HashMap<String, RFunction> builtinFunctionCache = new HashMap<>();
+
+    @Override
+    public HashMap<String, RFunction> getBuiltinFunctionCache() {
+        return builtinFunctionCache;
+    }
 
     /**
      * The choice of {@link RFFIFactory} is made statically so that it is bound into an AOT-compiled
@@ -88,7 +87,6 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> implements
      */
     private static void initialize() {
         try {
-            Locale.setDefault(Locale.ROOT);
             RAccuracyInfo.initialize();
         } catch (Throwable t) {
             t.printStackTrace();
@@ -107,17 +105,11 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> implements
 
     private static boolean systemInitialized;
 
-    public static TruffleRLanguage INSTANCE;
-
     public static final String MIME = RRuntime.R_APP_MIME;
 
-    public TruffleRLanguage() {
-        INSTANCE = this;
-    }
-
     @Override
     protected boolean isObjectOfLanguage(Object object) {
-        return false;
+        return object instanceof RTypedValue;
     }
 
     @Override
@@ -136,7 +128,7 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> implements
         if (initialContext) {
             RContext.initializeGlobalState(new RASTBuilder(), new RRuntimeASTAccessImpl(), RBuiltinPackages.getInstance(), new RForeignAccessFactoryImpl());
         }
-        RContext result = RContext.create(env, env.lookup(Instrumenter.class), initialContext);
+        RContext result = RContext.create(this, env, env.lookup(Instrumenter.class), initialContext);
         return result;
     }
 
@@ -183,8 +175,8 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> implements
                 unwrappedValue = promise.getValue();
             }
         }
-        unwrappedValue = RRuntime.asAbstractVector(unwrappedValue); // Wrap scalars "Integer",
-                                                                    // "Double" etc.
+        // Wrap scalars Integer, Double, etc.
+        unwrappedValue = RRuntime.convertScalarVectors(unwrappedValue);
         if (unwrappedValue instanceof RTypedValue) {
             return ((RTypedValue) unwrappedValue).getRType().getName();
         } else {
@@ -208,39 +200,26 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> implements
     }
 
     @Override
-    @SuppressWarnings({"try", "deprecation"})
     protected CallTarget parse(ParsingRequest request) throws Exception {
         CompilerAsserts.neverPartOfCompilation();
-        try (RCloseable c = RContext.withinContext(findContext(createFindContextNode()))) {
-            try {
-                return RContext.getEngine().parseToCallTarget(request.getSource(), request.getFrame());
-            } catch (IncompleteSourceException e) {
-                throw new com.oracle.truffle.api.vm.IncompleteSourceException(e);
-            } catch (ParseException e) {
-                return Truffle.getRuntime().createCallTarget(new RootNode(TruffleRLanguage.class, null, new FrameDescriptor()) {
-                    @Override
-                    public Object execute(VirtualFrame frame) {
-                        try {
-                            throw e.throwAsRError();
-                        } catch (RError e2) {
-                            return null;
-                        }
-                    }
-                });
-            } catch (RError e) {
-                return Truffle.getRuntime().createCallTarget(new RootNode(TruffleRLanguage.class, null, new FrameDescriptor()) {
-                    @Override
-                    public Object execute(VirtualFrame frame) {
-                        return null;
-                    }
-                });
-            }
+        try {
+            return RContext.getEngine().parseToCallTarget(request.getSource(), request.getFrame());
+        } catch (IncompleteSourceException e) {
+            throw e;
+        } catch (ParseException e) {
+            throw e.throwAsRError();
         }
     }
 
+    private static final R2Foreign r2foreign = R2ForeignNodeGen.create();
+
     @Override
-    protected Object findExportedSymbol(RContext context, String globalName, boolean onlyExplicit) {
-        return context.getExportedSymbols().get(globalName);
+    protected Object lookupSymbol(RContext context, String symbolName) {
+        Object value = context.stateREnvironment.getGlobalEnv().get(symbolName);
+        if (value instanceof RPromise) {
+            value = PromiseHelperNode.evaluateSlowPath((RPromise) value);
+        }
+        return value != null ? r2foreign.execute(value) : null;
     }
 
     @Override
@@ -249,15 +228,12 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> implements
         return null;
     }
 
-    // TODO: why isn't the original method public?
-    @SuppressWarnings("deprecation")
-    public Node actuallyCreateFindContextNode() {
-        return createFindContextNode();
+    public static RContext getCurrentContext() {
+        return TruffleLanguage.getCurrentContext(TruffleRLanguage.class);
     }
 
-    @SuppressWarnings("deprecation")
-    public RContext actuallyFindContext0(Node contextNode) {
-        return findContext(contextNode);
+    public static TruffleRLanguage getCurrentLanguage() {
+        return TruffleLanguage.getCurrentLanguage(TruffleRLanguage.class);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
index b028bd676da709688dd0328c54b998517824e21b..94532825ba6d359254f320a8ad0c778b62d1da8c 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
@@ -27,12 +27,9 @@ 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.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 
-@MessageResolution(receiverType = ActiveBinding.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = ActiveBinding.class)
 public class ActiveBindingMR {
     @Resolve(message = "IS_BOXED")
     public abstract static class ActiveBindingIsBoxedNode extends Node {
@@ -41,29 +38,18 @@ public class ActiveBindingMR {
         }
     }
 
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class ActiveBindingHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") ActiveBinding receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "IS_NULL")
-    public abstract static class ActiveBindingIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") ActiveBinding receiver) {
-            return false;
-        }
-    }
-
     @Resolve(message = "UNBOX")
     public abstract static class ActiveBindingUnboxNode extends Node {
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
-        @SuppressWarnings("try")
         protected Object access(ActiveBinding receiver) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                return receiver.readValue();
-            }
+            return receiver.readValue();
+        }
+    }
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class ActiveBindingKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object idx) {
+            return 0;
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..92276371262cf8d572b35f2feb6458d10590b8c8
--- /dev/null
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ListMR.java
@@ -0,0 +1,407 @@
+/*
+ * 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.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.KeyInfo;
+import com.oracle.truffle.api.interop.KeyInfo.Builder;
+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.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.engine.interop.ListMRFactory.ListKeyInfoImplNodeGen;
+import com.oracle.truffle.r.engine.interop.ListMRFactory.ListReadImplNodeGen;
+import com.oracle.truffle.r.engine.interop.ListMRFactory.ListWriteImplNodeGen;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
+import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
+import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
+import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.control.RLengthNode;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RLogical;
+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.RStringVector;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.Foreign2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
+
+public class ListMR {
+
+    @MessageResolution(receiverType = RList.class)
+    public static class RListMR extends ListMR {
+
+        @Resolve(message = "HAS_SIZE")
+        public abstract static class RListHasSizeNode extends Node {
+            protected Object access(RList receiver) {
+                return hasSize(receiver);
+            }
+        }
+
+        @Resolve(message = "GET_SIZE")
+        public abstract static class RListGetSizeNode extends Node {
+            @Child private RLengthNode lengthNode = RLengthNode.create();
+
+            protected Object access(RList receiver) {
+                return getSize(receiver, lengthNode);
+            }
+        }
+
+        @Resolve(message = "READ")
+        public abstract static class RListReadNode extends Node {
+            @Child private ListReadImplNode read = ListReadImplNodeGen.create();
+
+            protected Object access(VirtualFrame frame, RList receiver, Object identifier) {
+                return read.execute(frame, receiver, identifier);
+            }
+        }
+
+        @Resolve(message = "WRITE")
+        public abstract static class RListWriteNode extends Node {
+            @Child private ListWriteImplNode writeNode = ListWriteImplNodeGen.create();
+
+            protected Object access(RList receiver, Object identifier, Object valueObj) {
+                return writeNode.execute(receiver, identifier, valueObj);
+            }
+        }
+
+        @Resolve(message = "KEYS")
+        public abstract static class RListKeysNode extends Node {
+            @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
+
+            protected Object access(RList receiver) {
+                return listKeys(receiver, getNamesNode);
+            }
+        }
+
+        @Resolve(message = "KEY_INFO")
+        public abstract static class RListKeyInfoNode extends Node {
+            @Child private ListKeyInfoImplNode keyInfoNode = ListKeyInfoImplNodeGen.create();
+
+            protected Object access(TruffleObject receiver, Object idx) {
+                return keyInfoNode.execute(receiver, idx);
+            }
+        }
+
+        @Resolve(message = "TO_NATIVE")
+        public abstract static class RListToNativeNode extends Node {
+            protected Object access(RTruffleObject receiver) {
+                return toNativePointer(receiver);
+            }
+        }
+
+        @CanResolve
+        public abstract static class RListCheck extends Node {
+
+            protected static boolean test(TruffleObject receiver) {
+                return receiver instanceof RList;
+            }
+        }
+    }
+
+    @MessageResolution(receiverType = RPairList.class)
+    public static class RPairListMR {
+
+        @Resolve(message = "HAS_SIZE")
+        public abstract static class RPairListHasSizeNode extends Node {
+            protected Object access(RPairList receiver) {
+                return hasSize(receiver);
+            }
+        }
+
+        @Resolve(message = "GET_SIZE")
+        public abstract static class RPairListGetSizeNode extends Node {
+            @Child private RLengthNode lengthNode = RLengthNode.create();
+
+            protected Object access(RPairList receiver) {
+                return getSize(receiver, lengthNode);
+            }
+        }
+
+        @Resolve(message = "IS_EXECUTABLE")
+        public abstract static class RPairListIsExecutableNode extends Node {
+            protected Object access(@SuppressWarnings("unused") RPairList receiver) {
+                return false;
+            }
+        }
+
+        @Resolve(message = "READ")
+        public abstract static class RPairListReadNode extends Node {
+            @Child private ListReadImplNode read = ListReadImplNodeGen.create();
+
+            protected Object access(VirtualFrame frame, RPairList receiver, Object identifier) {
+                return read.execute(frame, receiver, identifier);
+            }
+        }
+
+        @Resolve(message = "WRITE")
+        public abstract static class RPairListWriteNode extends Node {
+            @Child private ListWriteImplNode writeNode = ListWriteImplNodeGen.create();
+
+            protected Object access(RPairList receiver, Object identifier, Object valueObj) {
+                return writeNode.execute(receiver, identifier, valueObj);
+            }
+        }
+
+        @Resolve(message = "KEYS")
+        public abstract static class RPairListKeysNode extends Node {
+            @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
+
+            protected Object access(RPairList receiver) {
+                return listKeys(receiver, getNamesNode);
+            }
+        }
+
+        @Resolve(message = "KEY_INFO")
+        public abstract static class RPairListKeyInfoNode extends Node {
+            @Child private ListKeyInfoImplNode keyInfoNode = ListKeyInfoImplNodeGen.create();
+
+            protected Object access(TruffleObject receiver, Object idx) {
+                return keyInfoNode.execute(receiver, idx);
+            }
+        }
+
+        @Resolve(message = "TO_NATIVE")
+        public abstract static class RPairListToNativeNode extends Node {
+            protected Object access(RPairList receiver) {
+                return toNativePointer(receiver);
+            }
+        }
+
+        @CanResolve
+        public abstract static class RPairListCheck extends Node {
+            protected static boolean test(TruffleObject receiver) {
+                return receiver instanceof RPairList;
+            }
+        }
+    }
+
+    abstract static class ListReadImplNode extends Node {
+        @Child private ExtractVectorNode extract;
+        @Child private R2Foreign r2Foreign;
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        protected abstract Object execute(VirtualFrame frame, TruffleObject receiver, Object idx);
+
+        @Specialization
+        protected Object read(TruffleObject receiver, double idx,
+                        @Cached("createKeyInfoNode()") ListKeyInfoImplNode keyInfo) {
+            return read(receiver, (int) idx, keyInfo);
+        }
+
+        @Specialization
+        protected Object read(TruffleObject receiver, long idx,
+                        @Cached("createKeyInfoNode()") ListKeyInfoImplNode keyInfo) {
+            return read(receiver, (int) idx, keyInfo);
+        }
+
+        @Specialization
+        protected Object read(TruffleObject receiver, int idx,
+                        @Cached("createKeyInfoNode()") ListKeyInfoImplNode keyInfo) {
+            int info = keyInfo.execute(receiver, idx);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + idx);
+            }
+            initExtractNode();
+            // idx + 1 R is indexing from 1
+            Object value = extract.apply(receiver, new Object[]{idx + 1}, RLogical.valueOf(false), RMissing.instance);
+            initR2ForeignNode();
+            return r2Foreign.execute(value);
+        }
+
+        @Specialization
+        protected Object read(TruffleObject receiver, String field,
+                        @Cached("createKeyInfoNode()") ListKeyInfoImplNode keyInfo) {
+            // reading by an unknown name returns null,
+            // reading by an unknown index returns subscript out of bounds;
+            // let's be consistent at this place, the name should be known to the caller anyway
+            int info = keyInfo.execute(receiver, field);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + field);
+            }
+            initExtractNode();
+            Object value = extract.applyAccessField(receiver, field);
+            initR2ForeignNode();
+            return r2Foreign.execute(value);
+        }
+
+        @Fallback
+        protected Object read(@SuppressWarnings("unused") TruffleObject receiver, Object field) {
+            throw UnknownIdentifierException.raise("" + field);
+        }
+
+        protected ListKeyInfoImplNode createKeyInfoNode() {
+            return ListKeyInfoImplNodeGen.create();
+        }
+
+        private void initR2ForeignNode() {
+            if (r2Foreign == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                r2Foreign = insert(R2ForeignNodeGen.create());
+            }
+        }
+
+        private void initExtractNode() {
+            if (extract == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                extract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+            }
+        }
+    }
+
+    abstract static class ListWriteImplNode extends Node {
+        @Child private ReplaceVectorNode replace;
+        @Child private Foreign2R foreign2R;
+
+        protected abstract Object execute(TruffleObject receiver, Object identifier, Object valueObj);
+
+        @Specialization
+        protected Object write(TruffleObject receiver, int idx, Object valueObj) {
+            // idx + 1 R is indexing from 1
+            return write(receiver, new Object[]{idx + 1}, valueObj);
+        }
+
+        @Specialization
+        protected Object write(TruffleObject receiver, String field, Object valueObj) {
+            return write(receiver, new Object[]{field}, valueObj);
+        }
+
+        private Object write(TruffleObject receiver, Object[] positions, Object valueObj) {
+            if (foreign2R == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                foreign2R = insert(Foreign2RNodeGen.create());
+            }
+            Object value = foreign2R.execute(valueObj);
+            if (replace == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                replace = insert(ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+            }
+            return replace.apply(receiver, positions, value);
+        }
+
+        @Fallback
+        protected Object write(@SuppressWarnings("unused") TruffleObject receiver, Object field, @SuppressWarnings("unused") Object object) {
+            throw UnknownIdentifierException.raise("" + field);
+        }
+    }
+
+    abstract static class ListKeyInfoImplNode extends Node {
+        @Child private ExtractVectorNode extractNode;
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        abstract int execute(TruffleObject receiver, Object idx);
+
+        @Specialization
+        protected int keyInfo(TruffleObject receiver, int idx,
+                        @Cached("createLengthNode()") RLengthNode lenghtNode) {
+            return keyInfo(receiver, (double) idx, lenghtNode);
+        }
+
+        @Specialization
+        protected int keyInfo(TruffleObject receiver, double idx,
+                        @Cached("createLengthNode()") RLengthNode lengthNode) {
+
+            int length = lengthNode.executeInteger(receiver);
+            if (unknownIdentifier.profile(idx < 0 || idx >= length)) {
+                return 0;
+            }
+            initExtractNode();
+            return buildKeys(extractNode.apply(receiver, new Object[]{idx + 1}, RLogical.valueOf(false), RMissing.instance));
+        }
+
+        @Specialization
+        protected int keyInfo(TruffleObject receiver, String identifier,
+                        @Cached("createNamesNode()") GetNamesAttributeNode namesNode) {
+            RStringVector names = namesNode.getNames(receiver);
+            boolean exists = false;
+            for (int i = 0; i < names.getLength(); i++) {
+                if (identifier.equals(names.getDataAt(i))) {
+                    exists = true;
+                    break;
+                }
+            }
+            if (unknownIdentifier.profile(!exists)) {
+                return 0;
+            }
+            initExtractNode();
+            return buildKeys(extractNode.applyAccessField(receiver, identifier));
+        }
+
+        protected RLengthNode createLengthNode() {
+            return RLengthNode.create();
+        }
+
+        protected GetNamesAttributeNode createNamesNode() {
+            return GetNamesAttributeNode.create();
+        }
+
+        private static int buildKeys(Object value) {
+            Builder builder = KeyInfo.newBuilder();
+            builder.setReadable(true).setWritable(true).setInvocable(value instanceof RFunction);
+            return builder.build();
+        }
+
+        private void initExtractNode() {
+            if (extractNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+            }
+        }
+
+        @Fallback
+        protected int access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object field) {
+            return 0;
+        }
+    }
+
+    private static boolean hasSize(@SuppressWarnings("unused") TruffleObject receiver) {
+        return true;
+    }
+
+    private static Object getSize(TruffleObject receiver, RLengthNode lengthNode) {
+        return lengthNode.executeInteger(receiver);
+    }
+
+    private static Object listKeys(TruffleObject receiver, GetNamesAttributeNode getNamesNode) {
+        RStringVector names = getNamesNode.getNames(receiver);
+        return names != null ? names : RNull.instance;
+    }
+
+    private static Object toNativePointer(RTruffleObject receiver) {
+        return new NativePointer(receiver);
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
index c5ee552ba380672fe4fe7156fee47151cf430807..3b9d9624bc827d2f6ab7300fb7f586d7337c76c0 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
@@ -22,83 +22,201 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
+import java.util.List;
+
 import com.oracle.truffle.api.CallTarget;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.ForeignAccess.Factory26;
+import com.oracle.truffle.api.interop.KeyInfo;
 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.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
-import com.oracle.truffle.r.engine.TruffleRLanguage;
-import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorReadNodeGen;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
+import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorKeyInfoImplNodeGen;
+import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorKeyInfoRootNodeGen;
+import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorReadImplNodeGen;
+import com.oracle.truffle.r.engine.interop.RAbstractVectorAccessFactoryFactory.VectorWriteImplNodeGen;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
+import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.Foreign2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+
+abstract class InteropRootNode extends RootNode {
+    InteropRootNode() {
+        super(TruffleRLanguageImpl.getCurrentLanguage());
+    }
+
+    @Override
+    public final SourceSection getSourceSection() {
+        return RSyntaxNode.INTERNAL;
+    }
+}
 
 public final class RAbstractVectorAccessFactory implements Factory26 {
 
-    static class VectorSizeNode extends RootNode {
+    abstract static class VectorReadImplNode extends InteropRootNode {
 
-        @Child private RLengthNode lengthNode = RLengthNode.create();
+        @Child private ExtractVectorNode extract;
+        @Child private R2Foreign r2Foreign;
 
-        @SuppressWarnings("deprecation")
-        VectorSizeNode() {
-            super(TruffleRLanguage.class, null, null);
-        }
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
 
         @Override
-        public Object execute(VirtualFrame frame) {
-            return lengthNode.executeInteger(frame, ForeignAccess.getReceiver(frame));
+        public final Object execute(VirtualFrame frame) {
+            Object indentifier = ForeignAccess.getArguments(frame).get(0);
+            Object receiver = ForeignAccess.getReceiver(frame);
+            return execute(frame, receiver, indentifier);
         }
-    }
 
-    abstract static class VectorReadNode extends RootNode {
+        protected abstract Object execute(VirtualFrame frame, Object reciever, Object indentifier);
 
-        @CompilationFinal private boolean lengthAccess;
-        @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
-        @Child private RLengthNode lengthNode = RLengthNode.create();
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+        @Specialization
+        protected Object readIndexed(VirtualFrame frame, Object receiver, int idx,
+                        @Cached("createKeyInfoNode()") VectorKeyInfoImplNode keyInfo) {
+            int info = keyInfo.execute(frame, receiver, idx);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + idx);
+            }
+            return read(receiver, new Object[]{idx + 1});
+        }
+
+        @Specialization
+        protected Object readIndexed(VirtualFrame frame, Object receiver, long idx,
+                        @Cached("createKeyInfoNode()") VectorKeyInfoImplNode keyInfo) {
+            int info = keyInfo.execute(frame, receiver, idx);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + idx);
+            }
+            return read(receiver, new Object[]{idx + 1});
+        }
+
+        private Object read(Object receiver, Object[] positions) {
+            if (extract == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                extract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+            }
+            Object value = extract.apply(receiver, positions, RLogical.TRUE, RLogical.TRUE);
+            if (r2Foreign == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                r2Foreign = insert(R2ForeignNodeGen.create());
+            }
+            return r2Foreign.execute(value);
+        }
 
-        @SuppressWarnings("deprecation")
-        VectorReadNode() {
-            super(TruffleRLanguage.class, null, null);
-            this.lengthAccess = false;
+        @Fallback
+        protected Object read(@SuppressWarnings("unused") Object receiver, Object indentifier) {
+            throw UnknownIdentifierException.raise("" + indentifier);
         }
 
+        protected VectorKeyInfoImplNode createKeyInfoNode() {
+            return VectorKeyInfoImplNodeGen.create();
+        }
+    }
+
+    abstract static class VectorWriteImplNode extends InteropRootNode {
+        @Child private ReplaceVectorNode replace;
+        @Child private Foreign2R foreign2R;
+
         @Override
-        @SuppressWarnings("try")
         public final Object execute(VirtualFrame frame) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                Object label = ForeignAccess.getArguments(frame).get(0);
-                Object receiver = ForeignAccess.getReceiver(frame);
-                return execute(frame, receiver, label);
-            }
+            List<Object> arguments = ForeignAccess.getArguments(frame);
+            Object receiver = ForeignAccess.getReceiver(frame);
+            return execute(frame, receiver, arguments.get(0), arguments.get(1));
         }
 
-        protected abstract Object execute(VirtualFrame frame, Object reciever, Object label);
+        protected abstract Object execute(VirtualFrame frame, Object receiver, Object identifier, Object valueObj);
 
         @Specialization
-        protected Object readIndexed(VirtualFrame frame, Object receiver, int label) {
-            return extract.apply(frame, receiver, new Object[]{label + 1}, RLogical.TRUE, RLogical.TRUE);
+        protected Object write(TruffleObject receiver, int idx, Object valueObj) {
+            // idx + 1 R is indexing from 1
+            return write(receiver, new Object[]{idx + 1}, valueObj);
+        }
+
+        @Specialization
+        protected Object write(TruffleObject receiver, long idx, Object valueObj) {
+            // idx + 1 R is indexing from 1
+            return write(receiver, new Object[]{idx + 1}, valueObj);
+        }
+
+        private Object write(TruffleObject receiver, Object[] positions, Object valueObj) {
+            if (foreign2R == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                foreign2R = insert(Foreign2RNodeGen.create());
+            }
+            Object value = foreign2R.execute(valueObj);
+            if (replace == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                replace = insert(ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+            }
+            return replace.apply(receiver, positions, value);
+        }
+
+        @Fallback
+        protected Object write(@SuppressWarnings("unused") Object receiver, Object field, @SuppressWarnings("unused") Object object) {
+            throw UnknownIdentifierException.raise("" + field);
         }
+    }
+
+    abstract static class VectorKeyInfoRootNode extends InteropRootNode {
+        @Child VectorKeyInfoImplNode keyInfoNode = VectorKeyInfoImplNodeGen.create();
+
+        @Override
+        public final Object execute(VirtualFrame frame) {
+            Object indentifier = ForeignAccess.getArguments(frame).get(0);
+            Object receiver = ForeignAccess.getReceiver(frame);
+            return execute(frame, receiver, indentifier);
+        }
+
+        protected abstract int execute(VirtualFrame frame, Object reciever, Object indentifier);
 
         @Specialization
-        protected Object readProperty(VirtualFrame frame, Object receiver, String label) {
-            return extract.applyAccessField(frame, receiver, label);
+        protected int keyInfo(VirtualFrame frame, Object receiver, Object indentifier) {
+            return keyInfoNode.execute(frame, receiver, indentifier);
         }
     }
 
-    private abstract class InteropRootNode extends RootNode {
-        @SuppressWarnings("deprecation")
-        InteropRootNode() {
-            super(TruffleRLanguage.class, null, null);
+    abstract static class VectorKeyInfoImplNode extends Node {
+        @Child private RLengthNode lengthNode = RLengthNode.create();
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        protected abstract int execute(VirtualFrame frame, Object reciever, Object indentifier);
+
+        @Specialization
+        protected int keyInfo(Object receiver, int idx) {
+            return keyInfo(receiver, (long) idx);
+        }
+
+        @Specialization
+        protected int keyInfo(Object receiver, long idx) {
+            if (unknownIdentifier.profile(idx < 0 || idx >= lengthNode.executeInteger(receiver))) {
+                return 0;
+            }
+            KeyInfo.Builder builder = KeyInfo.newBuilder();
+            builder.setReadable(true).setWritable(true);
+            return builder.build();
+        }
+
+        @Fallback
+        protected int keyInfo(@SuppressWarnings("unused") Object receiver, @SuppressWarnings("unused") Object label) {
+            return 0;
         }
     }
 
@@ -114,7 +232,12 @@ public final class RAbstractVectorAccessFactory implements Factory26 {
 
     @Override
     public CallTarget accessIsExecutable() {
-        return null;
+        return Truffle.getRuntime().createCallTarget(new InteropRootNode() {
+            @Override
+            public Object execute(VirtualFrame frame) {
+                return false;
+            }
+        });
     }
 
     @Override
@@ -140,7 +263,15 @@ public final class RAbstractVectorAccessFactory implements Factory26 {
 
     @Override
     public CallTarget accessGetSize() {
-        return Truffle.getRuntime().createCallTarget(new VectorSizeNode());
+        return Truffle.getRuntime().createCallTarget(new InteropRootNode() {
+
+            @Child private RLengthNode lengthNode = RLengthNode.create();
+
+            @Override
+            public Object execute(VirtualFrame frame) {
+                return lengthNode.executeInteger(ForeignAccess.getReceiver(frame));
+            }
+        });
     }
 
     @Override
@@ -156,12 +287,12 @@ public final class RAbstractVectorAccessFactory implements Factory26 {
 
     @Override
     public CallTarget accessRead() {
-        return Truffle.getRuntime().createCallTarget(VectorReadNodeGen.create());
+        return Truffle.getRuntime().createCallTarget(VectorReadImplNodeGen.create());
     }
 
     @Override
     public CallTarget accessWrite() {
-        return null;
+        return Truffle.getRuntime().createCallTarget(VectorWriteImplNodeGen.create());
     }
 
     @Override
@@ -191,6 +322,32 @@ public final class RAbstractVectorAccessFactory implements Factory26 {
 
     @Override
     public CallTarget accessKeyInfo() {
+        return Truffle.getRuntime().createCallTarget(VectorKeyInfoRootNodeGen.create());
+    }
+
+    @Override
+    public CallTarget accessIsPointer() {
+        return Truffle.getRuntime().createCallTarget(new InteropRootNode() {
+            @Override
+            public Object execute(VirtualFrame frame) {
+                return false;
+            }
+        });
+    }
+
+    @Override
+    public CallTarget accessAsPointer() {
         return null;
     }
+
+    @Override
+    public CallTarget accessToNative() {
+        return Truffle.getRuntime().createCallTarget(new InteropRootNode() {
+            @Override
+            public Object execute(VirtualFrame frame) {
+                RAbstractVector arg = (RAbstractVector) ForeignAccess.getReceiver(frame);
+                return new NativePointer(arg);
+            }
+        });
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
index 5eafbc04ce58622d9989777137668b3345bc8047..9e60cc21fd4caeab36ffe79306617ecc27d1c8ea 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RArgsValuesAndNamesMR.java
@@ -22,22 +22,28 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.KeyInfo;
 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.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.engine.interop.RArgsValuesAndNamesMRFactory.RArgsValuesAndNamesKeyInfoImplNodeGen;
+import com.oracle.truffle.r.engine.interop.RArgsValuesAndNamesMRFactory.RArgsValuesAndNamesReadImplNodeGen;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
 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.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 
-@MessageResolution(receiverType = RArgsValuesAndNames.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RArgsValuesAndNames.class)
 public class RArgsValuesAndNamesMR {
-    @Resolve(message = "IS_BOXED")
-    public abstract static class RArgsValuesAndNamesIsBoxedNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver) {
-            return false;
-        }
-    }
 
     @Resolve(message = "HAS_SIZE")
     public abstract static class RArgsValuesAndNamesHasSizeNode extends Node {
@@ -46,10 +52,35 @@ public class RArgsValuesAndNamesMR {
         }
     }
 
-    @Resolve(message = "IS_NULL")
-    public abstract static class RArgsValuesAndNamesIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver) {
-            return false;
+    @Resolve(message = "GET_SIZE")
+    public abstract static class RArgsValuesAndNamesGetSizeNode extends Node {
+        protected Object access(RArgsValuesAndNames receiver) {
+            return receiver.getLength();
+        }
+    }
+
+    @Resolve(message = "READ")
+    public abstract static class RArgsValuesAndNamesReadNode extends Node {
+        @Child RArgsValuesAndNamesReadImplNode readNode = RArgsValuesAndNamesReadImplNodeGen.create();
+
+        protected Object access(RArgsValuesAndNames receiver, Object identifier) {
+            return readNode.execute(receiver, identifier);
+        }
+    }
+
+    @Resolve(message = "KEYS")
+    public abstract static class RArgsValuesAndNamesKeysNode extends Node {
+        protected Object access(RArgsValuesAndNames receiver) {
+            return RDataFactory.createStringVector(receiver.getSignature().getNames(), RDataFactory.COMPLETE_VECTOR);
+        }
+    }
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RArgsValuesAndNamesKeyInfoNode extends Node {
+        @Child private RArgsValuesAndNamesKeyInfoImplNode keyInfoNode = RArgsValuesAndNamesKeyInfoImplNodeGen.create();
+
+        protected Object access(VirtualFrame frame, RArgsValuesAndNames receiver, Object obj) {
+            return keyInfoNode.execute(frame, receiver, obj);
         }
     }
 
@@ -60,4 +91,88 @@ public class RArgsValuesAndNamesMR {
             return receiver instanceof RArgsValuesAndNames;
         }
     }
+
+    abstract static class RArgsValuesAndNamesReadImplNode extends Node {
+        @Child private R2Foreign r2Foreign = R2ForeignNodeGen.create();
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        abstract Object execute(RArgsValuesAndNames receiver, Object identifier);
+
+        @Specialization
+        protected Object access(RArgsValuesAndNames receiver, int index) {
+            if (unknownIdentifier.profile(index < 0 || index >= receiver.getLength())) {
+                throw UnknownIdentifierException.raise("" + index);
+            }
+            Object value = receiver.getArgument(index);
+            return r2Foreign.execute(value);
+        }
+
+        @Specialization
+        protected Object access(RArgsValuesAndNames receiver, String identifier) {
+            ArgumentsSignature sig = receiver.getSignature();
+            String[] names = sig.getNames();
+            int idx = -1;
+            for (int i = 0; i < names.length; i++) {
+                if (names[i].equals(identifier)) {
+                    idx = i;
+                    break;
+                }
+            }
+            if (unknownIdentifier.profile(idx < 0)) {
+                throw UnknownIdentifierException.raise("" + identifier);
+            }
+
+            Object value = receiver.getArgument(idx);
+            return r2Foreign.execute(value);
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver, Object identifier) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+    }
+
+    abstract static class RArgsValuesAndNamesKeyInfoImplNode extends Node {
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        abstract Object execute(VirtualFrame frame, RArgsValuesAndNames receiver, Object idx);
+
+        @Specialization
+        protected Object access(RArgsValuesAndNames receiver, int idx) {
+            if (unknownIdentifier.profile(idx < 0 || idx >= receiver.getLength())) {
+                return 0;
+            }
+            return createKeyInfo(receiver, idx);
+        }
+
+        @Specialization
+        protected Object access(RArgsValuesAndNames receiver, String identifier) {
+            ArgumentsSignature sig = receiver.getSignature();
+            String[] names = sig.getNames();
+            int idx = -1;
+            for (int i = 0; i < names.length; i++) {
+                if (names[i].equals(identifier)) {
+                    idx = i;
+                    break;
+                }
+            }
+            if (unknownIdentifier.profile(idx < 0)) {
+                return 0;
+            }
+
+            return createKeyInfo(receiver, idx);
+        }
+
+        private static Object createKeyInfo(RArgsValuesAndNames receiver, int idx) {
+            KeyInfo.Builder builder = KeyInfo.newBuilder();
+            builder.setReadable(true).setInvocable(receiver.getArgument(idx) instanceof RFunction);
+            return builder.build();
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") RArgsValuesAndNames receiver, @SuppressWarnings("unused") Object field) {
+            return 0;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java
index 45df6f9f1920f0b49d8069efb5df6fb6bed57ed2..273c19ac19309adaafef5501531d4199f0426aeb 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RConnectionMR.java
@@ -24,13 +24,21 @@ 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.conn.RConnection;
 
-@MessageResolution(receiverType = RConnection.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RConnection.class)
 public class RConnectionMR {
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RConnectionKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
+        }
+    }
+
     @CanResolve
     public abstract static class RConnection extends Node {
 
@@ -38,5 +46,4 @@ public class RConnectionMR {
             return receiver instanceof RConnection;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java
index 19ed14c1253f992a27cb3bff458f80a54ece9229..e1d5c3497e607570a63187226591acfd0753c2a2 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RContextMR.java
@@ -24,13 +24,21 @@ 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.context.RContext;
 
-@MessageResolution(receiverType = RContext.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RContext.class)
 public class RContextMR {
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RContextKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
+        }
+    }
+
     @CanResolve
     public abstract static class RContext extends Node {
 
@@ -38,5 +46,4 @@ public class RContextMR {
             return receiver instanceof RContext;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RDoubleMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RDoubleMR.java
index 518f0d36b11211a655a83641bdc1d89c3c034f33..06c424cc1f2b1fb4badd4c012be9d491fd8dbe01 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RDoubleMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RDoubleMR.java
@@ -27,10 +27,9 @@ 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.RDouble;
 
-@MessageResolution(receiverType = RDouble.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RDouble.class)
 public class RDoubleMR {
     @Resolve(message = "IS_BOXED")
     public abstract static class RDoubleIsBoxedNode extends Node {
@@ -39,20 +38,6 @@ public class RDoubleMR {
         }
     }
 
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RDoubleHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RDouble receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "IS_NULL")
-    public abstract static class RDoubleIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RDouble receiver) {
-            return false;
-        }
-    }
-
     @Resolve(message = "UNBOX")
     public abstract static class RDoubleUnboxNode extends Node {
         protected double access(RDouble receiver) {
@@ -60,6 +45,13 @@ public class RDoubleMR {
         }
     }
 
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RDoubleKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
+        }
+    }
+
     @CanResolve
     public abstract static class RDoubleCheck extends Node {
 
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
index 99277bbbcfbee60a210c5d0eacf8c530faa4dae0..462d98e4c6aaccd9d4393568435d0766219e8ef4 100644
--- 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
@@ -27,30 +27,15 @@ 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)
+@MessageResolution(receiverType = REmpty.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;
+    @Resolve(message = "KEY_INFO")
+    public abstract static class REmptyKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
index c3e7e288f8dc10217a4444067a0a0c2290d0a271..b18d134b3bffc9232b05c213cac2fdd11f600141 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
@@ -22,71 +22,78 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
-import static com.oracle.truffle.r.engine.interop.Utils.javaToRPrimitive;
-
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.KeyInfo;
+import com.oracle.truffle.api.interop.KeyInfo.Builder;
+import com.oracle.truffle.api.interop.Message;
 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.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentKeyInfoImplNodeGen;
+import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentReadImplNodeGen;
+import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentWriteImplNodeGen;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
-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.env.REnvironment;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.Foreign2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 
-@MessageResolution(receiverType = REnvironment.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = REnvironment.class)
 public class REnvironmentMR {
 
-    @Resolve(message = "IS_BOXED")
-    public abstract static class REnvironmentIsBoxedNode extends Node {
-        protected Object access(@SuppressWarnings("unused") REnvironment receiver) {
-            return false;
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class REnvironmentToNativeNode extends Node {
+        protected Object access(REnvironment receiver) {
+            return new NativePointer(receiver);
         }
     }
 
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class REnvironmentHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") REnvironment receiver) {
-            return true;
+    @Resolve(message = "READ")
+    public abstract static class REnvironmentReadNode extends Node {
+        @Child private REnvironmentReadImplNode readNode = REnvironmentReadImplNodeGen.create();
+
+        protected Object access(VirtualFrame frame, REnvironment receiver, Object identifier) {
+            return readNode.execute(frame, receiver, identifier);
         }
     }
 
-    @Resolve(message = "IS_NULL")
-    public abstract static class REnvironmentIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") REnvironment receiver) {
-            return false;
+    @Resolve(message = "WRITE")
+    public abstract static class REnvironmentWriteNode extends Node {
+        @Child private REnvironmentWriteImplNode writeNode = REnvironmentWriteImplNodeGen.create();
+
+        protected Object access(VirtualFrame frame, REnvironment receiver, Object field, Object valueObj) {
+            return writeNode.execute(frame, receiver, field, valueObj);
         }
     }
 
-    @Resolve(message = "READ")
-    public abstract static class REnvironmentReadNode extends Node {
-        @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+    @Resolve(message = "KEYS")
+    public abstract static class REnvironmentKeysNode extends Node {
 
-        @SuppressWarnings("try")
-        protected Object access(VirtualFrame frame, REnvironment receiver, String field) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                return extract.applyAccessField(frame, receiver, field);
-            }
+        protected Object access(REnvironment receiver) {
+            return receiver.ls(true, null, true);
         }
     }
 
-    @Resolve(message = "WRITE")
-    public abstract static class REnvironmentWriteNode extends Node {
-        @Child private ReplaceVectorNode extract = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
-
-        @SuppressWarnings("try")
-        protected Object access(VirtualFrame frame, REnvironment receiver, String field, Object valueObj) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                Object value = javaToRPrimitive(valueObj);
-                Object x = extract.apply(frame, receiver, new Object[]{field}, value);
-                return x;
-            }
+    @Resolve(message = "KEY_INFO")
+    public abstract static class REnvironmentKeyInfoNode extends Node {
+        @Child private REnvironmentKeyInfoImplNode keyInfoNode = REnvironmentKeyInfoImplNodeGen.create();
+
+        protected Object access(REnvironment receiver, Object obj) {
+            return keyInfoNode.execute(receiver, obj);
         }
     }
 
@@ -97,4 +104,118 @@ public class REnvironmentMR {
             return receiver instanceof REnvironment;
         }
     }
+
+    abstract static class REnvironmentReadImplNode extends Node {
+        @Child private ExtractVectorNode extract;
+        @Child private R2Foreign r2Foreign;
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        protected abstract Object execute(VirtualFrame frame, TruffleObject receiver, Object identifier);
+
+        @Specialization
+        protected Object access(REnvironment receiver, String identifier,
+                        @Cached("createKeyInfoNode()") REnvironmentKeyInfoImplNode keyInfo) {
+            int info = keyInfo.execute(receiver, identifier);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + identifier);
+            }
+
+            initExtractNode();
+            Object value = extract.applyAccessField(receiver, identifier);
+            initR2ForeignNode();
+            return r2Foreign.execute(value);
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, Object identifier) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+
+        protected REnvironmentKeyInfoImplNode createKeyInfoNode() {
+            return REnvironmentKeyInfoImplNodeGen.create();
+        }
+
+        private void initR2ForeignNode() {
+            if (r2Foreign == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                r2Foreign = insert(R2ForeignNodeGen.create());
+            }
+        }
+
+        private void initExtractNode() {
+            if (extract == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                extract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+            }
+        }
+    }
+
+    abstract static class REnvironmentWriteImplNode extends Node {
+        @Child private Foreign2R foreign2R;
+        @Child private ReplaceVectorNode replace;
+
+        private final ConditionProfile roIdentifier = ConditionProfile.createBinaryProfile();
+
+        protected abstract Object execute(VirtualFrame frame, TruffleObject receiver, Object identifier, Object valueObj);
+
+        @Specialization
+        protected Object access(REnvironment receiver, String identifier, Object valueObj,
+                        @Cached("createKeyInfoNode()") REnvironmentKeyInfoImplNode keyInfo) {
+
+            int info = keyInfo.execute(receiver, identifier);
+            if (KeyInfo.isExisting(info)) {
+                if (roIdentifier.profile(!KeyInfo.isWritable(info))) {
+                    // TODO - this is a bit weird - should be Message.WRITE and identifier
+                    throw UnsupportedMessageException.raise(Message.WRITE);
+                }
+            } else if (receiver.isLocked()) {
+                throw UnsupportedMessageException.raise(Message.WRITE);
+            }
+            if (foreign2R == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                foreign2R = insert(Foreign2RNodeGen.create());
+            }
+            Object value = foreign2R.execute(valueObj);
+            if (replace == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                replace = insert(ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+            }
+            return replace.apply(receiver, new Object[]{identifier}, value);
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, Object identifier, @SuppressWarnings("unused") Object valueObj) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+
+        protected REnvironmentKeyInfoImplNode createKeyInfoNode() {
+            return REnvironmentKeyInfoImplNodeGen.create();
+        }
+    }
+
+    abstract static class REnvironmentKeyInfoImplNode extends Node {
+
+        protected abstract int execute(REnvironment receiver, Object identifier);
+
+        @Specialization
+        protected int access(REnvironment receiver, String identifier) {
+            Object val = receiver.get(identifier);
+            if (val == null) {
+                return 0;
+            }
+            Builder builder = KeyInfo.newBuilder();
+            builder.setReadable(true);
+            if (!receiver.isLocked() && !receiver.bindingIsLocked(identifier)) {
+                builder.setWritable(true);
+            }
+            builder.setInvocable(val instanceof RFunction);
+            return builder.build();
+        }
+
+        @Fallback
+        protected int access(@SuppressWarnings("unused") REnvironment receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RExternalPtrMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RExternalPtrMR.java
index 9df56f2454ca8b1565c93c52b3eb8a10cd8ea703..bb333c5502fd6dbec9b5522babfcd46fc94257f5 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RExternalPtrMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RExternalPtrMR.java
@@ -24,13 +24,21 @@ 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.RExternalPtr;
 
-@MessageResolution(receiverType = RExternalPtr.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RExternalPtr.class)
 public class RExternalPtrMR {
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RExternalPtrKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
+        }
+    }
+
     @CanResolve
     public abstract static class RExternalPtrCheck extends Node {
 
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 fa203c367ab06940717e8f66f02b92fb8910150b..3fd10f6ef50db12c670ffa5c10e750ecd2d7ffd8 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
@@ -23,12 +23,9 @@
 package com.oracle.truffle.r.engine.interop;
 
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.interop.ForeignAccess;
 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.ffi.impl.interop.FFI_RForeignAccessFactoryImpl;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -50,17 +47,22 @@ 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;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
-import com.oracle.truffle.r.runtime.ffi.DLL;
 
 /**
  * For most types we use the {@link MessageResolution} facility to automatically generate the
  * factory for creating the {@link ForeignAccess} instance. The exceptions are the (many) subclasses
  * of {@link RAbstractVector} as these have the same handling but the generator cannot handle
  * abstract classes.
+ *
+ * The types that must flow across the interop boundary fall into (at least) two categories. Those
+ * listed in this class are those that other peer languages might expect to receive and make sense
+ * of. There are also a large number that are involved in implementing the R Foreign Function
+ * Interface, which are essentially private to the implementation. These are enumerated in
+ * {@link FFI_RForeignAccessFactoryImpl}.
  */
 public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
 
@@ -77,46 +79,20 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return RPairListMRForeign.ACCESS;
         } else if (obj instanceof RFunction) {
             return RFunctionMRForeign.ACCESS;
-        } else if (obj instanceof DLL.DLLInfo) {
-            return DLLInfoMRForeign.ACCESS;
-        } else if (obj instanceof DLL.DotSymbol) {
-            return DLLDotSymbolMRForeign.ACCESS;
         } else if (obj instanceof RSymbol) {
             return RSymbolMRForeign.ACCESS;
         } else if (obj instanceof RExternalPtr) {
             return RExternalPtrMRForeign.ACCESS;
         } else if (obj instanceof RUnboundValue) {
             return RUnboundValueMRForeign.ACCESS;
-        } else if (obj instanceof NativeRawArray) {
-            return NativeRawArrayMRForeign.ACCESS;
-        } else if (obj instanceof NativeLogicalArray) {
-            return NativeLogicalArrayMRForeign.ACCESS;
-        } else if (obj instanceof NativeCharArray) {
-            return NativeCharArrayMRForeign.ACCESS;
-        } else if (obj instanceof NativeDoubleArray) {
-            return NativeDoubleArrayMRForeign.ACCESS;
-        } else if (obj instanceof NativeIntegerArray) {
-            return NativeIntegerArrayMRForeign.ACCESS;
         } else if (obj instanceof RInteger) {
             return RIntegerMRForeign.ACCESS;
         } else if (obj instanceof RDouble) {
             return RDoubleMRForeign.ACCESS;
-        } else if (obj instanceof CharSXPWrapper) {
-            return CharSXPWrapperMRForeign.ACCESS;
         } else if (obj instanceof RConnection) {
             return RConnectionMRForeign.ACCESS;
         } else if (obj instanceof RContext) {
             return RContextMRForeign.ACCESS;
-        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl) {
-            return UnameUpCallImplMRForeign.ACCESS;
-        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl) {
-            return SetResultImplMRForeign.ACCESS;
-        } else if (obj instanceof TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl) {
-            return GlobUpCallImplMRForeign.ACCESS;
-        } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl) {
-            return MakeResultImplMRForeign.ACCESS;
-        } else if (obj instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl) {
-            return CaptureNamesImplMRForeign.ACCESS;
         } else if (obj instanceof RS4Object) {
             return RS4ObjectMRForeign.ACCESS;
         } else if (obj instanceof RPromise) {
@@ -133,19 +109,20 @@ public final class RForeignAccessFactoryImpl implements RForeignAccessFactory {
             return RMissingMRForeign.ACCESS;
         } else if (obj instanceof REmpty) {
             return REmptyMRForeign.ACCESS;
-
+        } else if (obj instanceof RAbstractAtomicVector) {
+            return ForeignAccess.create(RAbstractAtomicVector.class, new RAbstractVectorAccessFactory());
         } else {
-            if (obj instanceof RAbstractVector) {
-                return ForeignAccess.create(RAbstractVector.class, new RAbstractVectorAccessFactory());
+            ForeignAccess access = FFI_RForeignAccessFactoryImpl.getForeignAccess(obj);
+            if (access != null) {
+                return access;
             } else {
                 throw RInternalError.unimplemented("missing foreign access factory for " + obj.getClass().getSimpleName());
             }
         }
-
     }
 
     @Override
-    public Class<? extends TruffleLanguage<RContext>> getTruffleLanguage() {
-        return TruffleRLanguage.class;
+    public boolean setIsNull(boolean value) {
+        return RNullMR.setIsNull(value);
     }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
index c0e648cc3a7eab50e1c93e2f4f8584c45976d514..19af21fca055a0f36aa5c97327ce9a224614827b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
@@ -32,20 +32,30 @@ 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.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.RFrameSlot;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.Foreign2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 
-@MessageResolution(receiverType = RFunction.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RFunction.class)
 public class RFunctionMR {
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RFunctionKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
+        }
+    }
+
     @Resolve(message = "IS_EXECUTABLE")
     public abstract static class RFunctionIsExecutabledNode extends Node {
         protected Object access(@SuppressWarnings("unused") RFunction receiver) {
@@ -53,8 +63,18 @@ public class RFunctionMR {
         }
     }
 
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class RFunctionToNativeNode extends Node {
+        protected Object access(RFunction receiver) {
+            return new NativePointer(receiver);
+        }
+    }
+
     @Resolve(message = "EXECUTE")
     public abstract static class RFunctionExecuteNode extends Node {
+        @Child private Foreign2R foreign2R = Foreign2RNodeGen.create();
+        @Child private R2Foreign r2Foreign = R2ForeignNodeGen.create();
+
         private static final FrameDescriptor emptyFrameDescriptor = FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<interop>", new FrameDescriptor("R interop frame"));
         private static final RFrameSlot argsIdentifier = RFrameSlot.createTemp(false);
         private static final FrameSlot slot = FrameSlotChangeMonitor.findOrAddFrameSlot(emptyFrameDescriptor, argsIdentifier, FrameSlotKind.Object);
@@ -64,17 +84,20 @@ public class RFunctionMR {
         }
 
         @Child private RCallBaseNode call = RCallNode.createExplicitCall(argsIdentifier);
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
 
-        @SuppressWarnings("try")
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, RFunction receiver, Object[] arguments) {
+        protected Object access(RFunction receiver, Object[] arguments) {
             Object[] dummyFrameArgs = RArguments.createUnitialized();
             VirtualFrame dummyFrame = Truffle.getRuntime().createVirtualFrame(dummyFrameArgs, emptyFrameDescriptor);
 
-            RArgsValuesAndNames actualArgs = new RArgsValuesAndNames(arguments, ArgumentsSignature.empty(arguments.length));
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
+            Object[] convertedArguments = new Object[arguments.length];
+            for (int i = 0; i < arguments.length; i++) {
+                convertedArguments[i] = foreign2R.execute(arguments[i]);
+            }
+            RArgsValuesAndNames actualArgs = new RArgsValuesAndNames(convertedArguments, ArgumentsSignature.empty(arguments.length));
+            try {
                 FrameSlotChangeMonitor.setObject(dummyFrame, slot, actualArgs);
-                return call.execute(dummyFrame, receiver);
+                Object value = call.execute(dummyFrame, receiver);
+                return r2Foreign.execute(value);
             } finally {
                 FrameSlotChangeMonitor.setObject(dummyFrame, slot, null);
             }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RIntegerMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RIntegerMR.java
index 2519b3736c17b4dd0ac85fc8883351afc3008289..923a8cd7b3954a100b060bb421f1138d038c230f 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RIntegerMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RIntegerMR.java
@@ -27,10 +27,9 @@ 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.RInteger;
 
-@MessageResolution(receiverType = RInteger.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RInteger.class)
 public class RIntegerMR {
     @Resolve(message = "IS_BOXED")
     public abstract static class RIntegerIsBoxedNode extends Node {
@@ -39,23 +38,16 @@ public class RIntegerMR {
         }
     }
 
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RIntegerHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RInteger receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "IS_NULL")
-    public abstract static class RIntegerIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RInteger receiver) {
-            return false;
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RIntegerKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
         }
     }
 
     @Resolve(message = "UNBOX")
     public abstract static class RIntegerUnboxNode extends Node {
-        protected double access(RInteger receiver) {
+        protected int access(RInteger receiver) {
             return receiver.getValue();
         }
     }
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
index 0ae18bbe9de7a97cf20fc6b8b4e97198d3c8b119..2d4ff14a9ef7dd35d3801918b793fa9566ed59e6 100644
--- 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
@@ -62,17 +62,10 @@ public class RInteropScalarMR {
         }
     }
 
-    @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;
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RInteropScalarKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
index df173b4679df75f8006d1aa34359ebe164b3b40a..699bf254017fcbe4830059d21a9651109cfde27f 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
@@ -22,33 +22,31 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
-import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.KeyInfo;
 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.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 
-@MessageResolution(receiverType = RLanguage.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RLanguage.class)
 public class RLanguageMR {
 
-    @Resolve(message = "IS_BOXED")
-    public abstract static class RLanguageIsBoxedNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
-            return false;
-        }
-    }
-
     @Resolve(message = "HAS_SIZE")
     public abstract static class RLanguageHasSizeNode extends Node {
         protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
@@ -56,57 +54,109 @@ public class RLanguageMR {
         }
     }
 
-    @Resolve(message = "IS_NULL")
-    public abstract static class RLanguageIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
-            return false;
+    @Resolve(message = "GET_SIZE")
+    public abstract static class RLanguageGetSizeNode extends Node {
+        protected Object access(RLanguage receiver) {
+            return receiver.getLength();
+        }
+    }
+
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class RLanguageToNativeNode extends Node {
+        protected Object access(RLanguage receiver) {
+            return new NativePointer(receiver);
         }
     }
 
     @Resolve(message = "READ")
     public abstract static class RLanguageReadNode extends Node {
-        @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+        @Child private ReadNode readNode = RLanguageMRFactory.ReadNodeGen.create();
 
-        @SuppressWarnings("try")
-        protected Object access(VirtualFrame frame, RLanguage receiver, int label) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                return extract.apply(frame, receiver, new Object[]{label + 1}, RLogical.TRUE, RLogical.TRUE);
-            }
+        protected Object access(VirtualFrame frame, RLanguage receiver, Object identifier) {
+            return readNode.execute(frame, receiver, identifier);
         }
     }
 
-    @Resolve(message = "WRITE")
-    public abstract static class RLanguageWriteNode extends Node {
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RLanguageNode extends Node {
+        @Node.Child private KeyInfoNode keyInfoNode = RLanguageMRFactory.KeyInfoNodeGen.create();
 
-        @SuppressWarnings("unused")
-        protected Object access(VirtualFrame frame, RLanguage receiver, int label, Object valueObj) {
-            throw UnsupportedMessageException.raise(Message.WRITE);
+        protected Object access(RLanguage receiver, Object obj) {
+            return keyInfoNode.execute(receiver, obj);
         }
     }
 
-    @Resolve(message = "KEYS")
-    public abstract static class RLanguageKeysNode extends Node {
+    @CanResolve
+    public abstract static class RLanguageCheck extends Node {
 
-        protected Object access(@SuppressWarnings("unused") RLanguage receiver) {
-            return RNull.instance;
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof RLanguage;
         }
     }
 
-    @Resolve(message = "KEY_INFO")
-    public abstract static class RLanguageKeyInfoNode extends Node {
+    abstract static class ReadNode extends Node {
+        @Child private ExtractVectorNode extract;
+        @Child private R2Foreign r2Foreign;
 
-        @SuppressWarnings("unused")
-        protected Object access(VirtualFrame frame, RLanguage receiver, String identifier) {
-            return 0;
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        abstract Object execute(VirtualFrame frame, RLanguage receiver, Object identifier);
+
+        @Specialization
+        protected Object access(RLanguage receiver, int idx,
+                        @Cached("createKeyInfoNode()") KeyInfoNode keyInfo) {
+
+            int info = keyInfo.execute(receiver, idx);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + idx);
+            }
+
+            if (extract == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                extract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
+            }
+            Object value = extract.apply(receiver, new Object[]{idx + 1}, RLogical.TRUE, RLogical.TRUE);
+            if (value == null) {
+                return RNull.instance;
+            }
+
+            if (r2Foreign == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                r2Foreign = insert(R2ForeignNodeGen.create());
+            }
+            return r2Foreign.execute(value);
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") RLanguage receiver, Object identifier) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+
+        protected static KeyInfoNode createKeyInfoNode() {
+            return RLanguageMRFactory.KeyInfoNodeGen.create();
         }
     }
 
-    @CanResolve
-    public abstract static class RLanguageCheck extends Node {
+    abstract static class KeyInfoNode extends Node {
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
 
-        protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof RLanguage;
+        abstract int execute(RLanguage receiver, Object identifier);
+
+        @Specialization
+        protected int access(RLanguage receiver, int idx) {
+            if (unknownIdentifier.profile(idx < 0 || idx >= receiver.getLength())) {
+                return 0;
+            }
+
+            KeyInfo.Builder builder = KeyInfo.newBuilder();
+            builder.setReadable(true);
+            // TODO what about writeble/invocable/...
+            return builder.build();
+        }
+
+        @Fallback
+        protected int access(@SuppressWarnings("unused") RLanguage receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
         }
     }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
deleted file mode 100644
index c202c4896041792a89c35d2c7ed62b7e7f20e7da..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * 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 static com.oracle.truffle.r.engine.interop.Utils.javaToRPrimitive;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.frame.VirtualFrame;
-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.ConditionProfile;
-import com.oracle.truffle.r.engine.TruffleRLanguage;
-import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
-import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
-import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-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.RNull;
-import com.oracle.truffle.r.runtime.data.RStringVector;
-
-@MessageResolution(receiverType = RList.class, language = TruffleRLanguage.class)
-public class RListMR {
-
-    @Resolve(message = "IS_BOXED")
-    public abstract static class RListIsBoxedNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RList receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RListHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RList receiver) {
-            return true;
-        }
-    }
-
-    @Resolve(message = "IS_NULL")
-    public abstract static class RListIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RList receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "READ")
-    public abstract static class RListReadNode extends Node {
-        @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
-
-        @SuppressWarnings("try")
-        protected Object access(VirtualFrame frame, RList receiver, String field) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                return extract.applyAccessField(frame, receiver, field);
-            }
-        }
-    }
-
-    @Resolve(message = "WRITE")
-    public abstract static class RListWriteNode extends Node {
-        @Child private ReplaceVectorNode replace = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
-
-        @SuppressWarnings("try")
-        protected Object access(VirtualFrame frame, RList receiver, String field, Object valueObj) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                Object value = javaToRPrimitive(valueObj);
-                return replace.apply(frame, receiver, new Object[]{field}, value);
-            }
-        }
-    }
-
-    @Resolve(message = "KEYS")
-    public abstract static class RListKeysNode extends Node {
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
-        @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
-
-        @SuppressWarnings("try")
-        protected Object access(RList receiver) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                RStringVector names = getNamesNode.getNames(receiver);
-                return names != null ? names : RNull.instance;
-            }
-        }
-    }
-
-    @Resolve(message = "KEY_INFO")
-    public abstract static class RListKeyInfoNode extends Node {
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
-        @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
-        @Child private ExtractVectorNode extractNode;
-
-        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
-
-        private static final int READABLE = 1 << 1;
-        private static final int WRITABLE = 1 << 2;
-        private static final int INVOCABLE = 1 << 3;
-        private static final int INTERNAL = 1 << 4;
-
-        @SuppressWarnings("try")
-        protected Object access(VirtualFrame frame, RList receiver, String identifier) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                int info = 0;
-                RStringVector names = getNamesNode.getNames(receiver);
-                for (int i = 0; i < names.getLength(); i++) {
-                    if (identifier.equals(names.getDataAt(i))) {
-                        info = 1;
-                        break;
-                    }
-                }
-                if (unknownIdentifier.profile(info == 0)) {
-                    return info;
-                }
-
-                info = info + READABLE + WRITABLE;
-                if (extractNode == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
-                }
-                Object value = extractNode.applyAccessField(frame, receiver, identifier);
-                if (value instanceof RFunction) {
-                    info = info + INVOCABLE;
-                }
-                return info;
-            }
-        }
-    }
-
-    @CanResolve
-    public abstract static class RListCheck extends Node {
-
-        protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof RList;
-        }
-    }
-}
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
index 656843ed0c421fa4281d00467a90ca850a28203d..9c6abcf27b4b49c284248918ac15327e5a8bfe38 100644
--- 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
@@ -27,30 +27,15 @@ 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)
+@MessageResolution(receiverType = RMissing.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;
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RMissingKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
index 4fa755eacc68df01dd1bf4a5989e5431245c27d8..270f160dde7635edebde476f2cffbc82ffb51141 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RNullMR.java
@@ -27,34 +27,34 @@ 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.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.runtime.data.RNull;
 
-@MessageResolution(receiverType = RNull.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RNull.class)
 public class RNullMR {
     /**
      * Workaround to avoid NFI converting {@link RNull} to {@code null}.
      */
     private static boolean isNull = true;
 
-    @Resolve(message = "IS_BOXED")
-    public abstract static class RNullIsBoxedNode extends Node {
+    @Resolve(message = "IS_NULL")
+    public abstract static class RNullIsNullNode extends Node {
         protected Object access(@SuppressWarnings("unused") RNull receiver) {
-            return false;
+            return isNull;
         }
     }
 
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RNullHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RNull receiver) {
-            return false;
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RNullKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
         }
     }
 
-    @Resolve(message = "IS_NULL")
-    public abstract static class RNullIsNullNode extends Node {
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class RNullToNativeNode extends Node {
         protected Object access(@SuppressWarnings("unused") RNull receiver) {
-            return isNull;
+            return NativePointer.NULL_NATIVEPOINTER;
         }
     }
 
@@ -66,7 +66,7 @@ public class RNullMR {
         }
     }
 
-    public static boolean setIsNull(boolean value) {
+    static boolean setIsNull(boolean value) {
         boolean prev = isNull;
         isNull = value;
         return prev;
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPairListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPairListMR.java
deleted file mode 100644
index 8aab5a3e3b0d9320309034089022709d4750b9cc..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPairListMR.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.frame.VirtualFrame;
-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.nodes.access.vector.ElementAccessMode;
-import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
-import com.oracle.truffle.r.nodes.control.RLengthNode;
-import com.oracle.truffle.r.runtime.data.RLogical;
-import com.oracle.truffle.r.runtime.data.RMissing;
-import com.oracle.truffle.r.runtime.data.RPairList;
-
-@MessageResolution(receiverType = RPairList.class, language = TruffleRLanguage.class)
-public class RPairListMR {
-    @Resolve(message = "IS_BOXED")
-    public abstract static class RPairListIsBoxedNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RPairList receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RPairListHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RPairList receiver) {
-            return true;
-        }
-    }
-
-    @Resolve(message = "IS_NULL")
-    public abstract static class RPairListIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RPairList receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "GET_SIZE")
-    public abstract static class RVectorGetSizeNode extends Node {
-        @Child private RLengthNode lengthNode = RLengthNode.create();
-
-        protected Object access(VirtualFrame frame, RPairList receiver) {
-            return lengthNode.executeInteger(frame, receiver);
-        }
-    }
-
-    @Resolve(message = "READ")
-    public abstract static class RPairListReadNode extends Node {
-        @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
-
-        protected Object access(VirtualFrame frame, RPairList receiver, Integer index) {
-            return extract.apply(frame, receiver, new Object[]{index}, RLogical.valueOf(false), RMissing.instance);
-        }
-    }
-
-    @CanResolve
-    public abstract static class RPairListCheck extends Node {
-
-        protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof RPairList;
-        }
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
index 257848ba0269263f98cacc9a04064c19f48d519a..f531beac95dcddda545333c19445b074ea67fc50 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
@@ -22,41 +22,74 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.KeyInfo;
 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.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.interop.RPromiseMRFactory.RPromiseKeyInfoImplNodeGen;
+import com.oracle.truffle.r.engine.interop.RPromiseMRFactory.RPromiseReadImplNodeGen;
+import com.oracle.truffle.r.engine.interop.RPromiseMRFactory.RPromiseWriteImplNodeGen;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
+import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 
-@MessageResolution(receiverType = RPromise.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RPromise.class)
 public class RPromiseMR {
-    @Resolve(message = "IS_BOXED")
-    public abstract static class RPromiseIsBoxedNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RPromise receiver) {
-            return true;
+
+    private static final String PROP_VALUE = "value";
+    private static final String PROP_IS_EVALUATED = "isEvaluated";
+    private static final String PROP_EXPR = "expression";
+
+    @Resolve(message = "READ")
+    public abstract static class RPromiseReadNode extends Node {
+        @Child RPromiseReadImplNode readNode = RPromiseReadImplNodeGen.create();
+
+        @TruffleBoundary
+        protected Object access(RPromise receiver, String field) {
+            return readNode.execute(receiver, field);
         }
     }
 
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RPromiseHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RPromise receiver) {
-            return false;
+    @Resolve(message = "WRITE")
+    public abstract static class RPromiseWriteNode extends Node {
+        @Child RPromiseWriteImplNode writeNode = RPromiseWriteImplNodeGen.create();
+
+        protected Object access(RPromise receiver, String field, Object valueObj) {
+            return writeNode.execute(receiver, field, valueObj);
         }
     }
 
-    @Resolve(message = "IS_NULL")
-    public abstract static class RPromiseIsNullNode extends Node {
+    @Resolve(message = "KEYS")
+    public abstract static class RPromiseKeysNode extends Node {
+
         protected Object access(@SuppressWarnings("unused") RPromise receiver) {
-            return false;
+            return RDataFactory.createStringVector(new String[]{PROP_VALUE, PROP_IS_EVALUATED, PROP_EXPR}, true);
         }
     }
 
-    @Resolve(message = "UNBOX")
-    public abstract static class RPromiseUnboxNode extends Node {
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RPromiseKeyInfoNode extends Node {
+        @Child RPromiseKeyInfoImplNode keyInfoNode = RPromiseKeyInfoImplNodeGen.create();
+
+        protected Object access(RPromise receiver, String identifier) {
+            return keyInfoNode.execute(receiver, identifier);
+        }
+    }
+
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class RPromiseToNativeNode extends Node {
         protected Object access(RPromise receiver) {
-            return receiver.getValue();
+            return new NativePointer(receiver);
         }
     }
 
@@ -67,4 +100,81 @@ public class RPromiseMR {
             return receiver instanceof RPromise;
         }
     }
+
+    abstract static class RPromiseWriteImplNode extends Node {
+
+        protected abstract Object execute(RPromise receiver, Object identifier, Object valueObj);
+
+        @Specialization
+        protected Object access(RPromise receiver, String identifier, Object valueObj) {
+            if (PROP_IS_EVALUATED.equals(identifier)) {
+                if (!(valueObj instanceof Boolean)) {
+                    throw UnsupportedTypeException.raise(new Object[]{valueObj});
+                }
+
+                boolean newVal = (boolean) valueObj;
+                if (!receiver.isEvaluated() && newVal) {
+                    PromiseHelperNode.evaluateSlowPath(receiver);
+                } else if (receiver.isEvaluated() && !newVal) {
+                    receiver.resetValue();
+                }
+                return RRuntime.asLogical(receiver.isEvaluated());
+            }
+            throw UnknownIdentifierException.raise(identifier);
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") RPromise receiver, Object identifier, @SuppressWarnings("unused") Object valueObj) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+    }
+
+    abstract static class RPromiseReadImplNode extends Node {
+
+        protected abstract Object execute(RPromise receiver, Object identifier);
+
+        @Specialization
+        protected Object access(RPromise receiver, String identifier) {
+            if (PROP_EXPR.equals(identifier)) {
+                return RDataFactory.createLanguage(receiver.getRep());
+            }
+            if (PROP_IS_EVALUATED.equals(identifier)) {
+                return RRuntime.asLogical(receiver.isEvaluated());
+            }
+            if (PROP_VALUE.equals(identifier)) {
+                // only read value if evaluated
+                if (receiver.isEvaluated()) {
+                    return receiver.getValue();
+                }
+                return RNull.instance;
+            }
+            throw UnknownIdentifierException.raise(identifier);
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") RPromise receiver, Object identifier) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+    }
+
+    abstract static class RPromiseKeyInfoImplNode extends Node {
+
+        protected abstract Object execute(RPromise receiver, Object identifier);
+
+        @Specialization
+        protected Object access(@SuppressWarnings("unused") RPromise receiver, String identifier) {
+            if (PROP_EXPR.equals(identifier) || PROP_VALUE.equals(identifier)) {
+                return KeyInfo.newBuilder().setReadable(true).build();
+            } else if (PROP_IS_EVALUATED.equals(identifier)) {
+                return KeyInfo.newBuilder().setReadable(true).setWritable(true).build();
+            } else {
+                return 0;
+            }
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") RPromise receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
index 0c62ef582b8ca097738e8e1e891a13128d91b947..65a9cd84ba36ed4a52c624bcadfd77a9e1574081 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
@@ -22,90 +22,84 @@
  */
 package com.oracle.truffle.r.engine.interop;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.KeyInfo;
+import com.oracle.truffle.api.interop.KeyInfo.Builder;
+import com.oracle.truffle.api.interop.Message;
 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.interop.UnknownIdentifierException;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.engine.interop.RS4ObjectMRFactory.RS4ObjectKeyInfoImplNodeGen;
+import com.oracle.truffle.r.engine.interop.RS4ObjectMRFactory.RS4ObjectReadImplNodeGen;
+import com.oracle.truffle.r.engine.interop.RS4ObjectMRFactory.RS4ObjectWriteImplNodeGen;
 import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout.RAttribute;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RS4Object;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.Foreign2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 
-@MessageResolution(receiverType = RS4Object.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RS4Object.class)
 public class RS4ObjectMR {
 
-    @Resolve(message = "IS_BOXED")
-    public abstract static class RS4ObjectIsBoxedNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RS4Object receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RS4ObjectHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RS4Object receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "IS_NULL")
-    public abstract static class RS4ObjectIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RS4Object receiver) {
-            return false;
-        }
-    }
-
     @Resolve(message = "READ")
     public abstract static class RS4ObjectReadNode extends Node {
-        @Child private GetAttributeNode getAttributeNode = GetAttributeNode.create();
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
+        @Child private RS4ObjectReadImplNode readNode = RS4ObjectReadImplNodeGen.create();
 
-        @SuppressWarnings("try")
-        protected Object access(VirtualFrame frame, RS4Object receiver, String field) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                return getAttributeNode.execute(receiver, field);
-            }
+        protected Object access(RS4Object receiver, Object identifier) {
+            return readNode.execute(receiver, identifier);
         }
     }
 
     @Resolve(message = "WRITE")
     public abstract static class RS4ObjectWriteNode extends Node {
-        @Child private SetAttributeNode setAttributeNode = SetAttributeNode.create();
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
-
-        @SuppressWarnings("try")
-        protected Object access(VirtualFrame frame, RS4Object receiver, String field, Object valueObj) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                Object value = Utils.javaToRPrimitive(valueObj);
-                setAttributeNode.execute(receiver, field, value);
-                return value;
-            }
+        @Child private RS4ObjectWriteImplNode writeNode = RS4ObjectWriteImplNodeGen.create();
+
+        protected Object access(RS4Object receiver, Object identifier, Object valueObj) {
+            return writeNode.execute(receiver, identifier, valueObj);
         }
     }
 
     @Resolve(message = "KEYS")
     public abstract static class RS4ObjectKeysNode extends Node {
-        @Child private Node findContext = TruffleRLanguage.INSTANCE.actuallyCreateFindContextNode();
         @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
 
-        @SuppressWarnings("try")
         protected Object access(RS4Object receiver) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguage.INSTANCE.actuallyFindContext0(findContext))) {
-                RAttribute[] attributes = arrayAttrAccess.execute(receiver.getAttributes());
-                String[] data = new String[attributes.length];
-                for (int i = 0; i < data.length; i++) {
-                    data[i] = attributes[i].getName();
-                }
-                return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
-            }
+            return getKeys(receiver, arrayAttrAccess);
+        }
+    }
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RS4ObjectNode extends Node {
+        @Node.Child private RS4ObjectKeyInfoImplNode keyInfoNode = RS4ObjectKeyInfoImplNodeGen.create();
+
+        protected Object access(RS4Object receiver, Object obj) {
+            return keyInfoNode.execute(receiver, obj);
+        }
+    }
+
+    private static RAbstractStringVector getKeys(RS4Object s4, ArrayAttributeNode arrayAttrAccess) {
+        RAttribute[] attributes = arrayAttrAccess.execute(s4.getAttributes());
+        String[] data = new String[attributes.length];
+        for (int i = 0; i < data.length; i++) {
+            data[i] = attributes[i].getName();
         }
+        return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
     }
 
     @CanResolve
@@ -114,4 +108,138 @@ public class RS4ObjectMR {
             return receiver instanceof RS4Object;
         }
     }
+
+    abstract static class RS4ObjectReadImplNode extends Node {
+        @Child private GetAttributeNode getAttributeNode;
+        @Child private R2Foreign r2Foreign;
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        abstract Object execute(RS4Object receiver, Object identifier);
+
+        @Specialization
+        protected Object access(RS4Object receiver, String identifier,
+                        @Cached("createKeyInfoNode()") RS4ObjectKeyInfoImplNode keyInfo) {
+            int info = keyInfo.execute(receiver, identifier);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + identifier);
+            }
+
+            if (getAttributeNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                getAttributeNode = insert(GetAttributeNode.create());
+            }
+            Object value = getAttributeNode.execute(receiver, identifier);
+            if (value == null) {
+                return RNull.instance;
+            }
+
+            if (r2Foreign == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                r2Foreign = insert(R2ForeignNodeGen.create());
+            }
+            return r2Foreign.execute(value);
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") RS4Object receiver, Object identifier) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+
+        protected static ArrayAttributeNode createArrayAttributeNode() {
+            return ArrayAttributeNode.create();
+        }
+
+        protected static RS4ObjectKeyInfoImplNode createKeyInfoNode() {
+            return RS4ObjectKeyInfoImplNodeGen.create();
+        }
+    }
+
+    abstract static class RS4ObjectWriteImplNode extends Node {
+        @Child private SetAttributeNode setAttributeNode;
+        @Child private Foreign2R foreign2R;
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        abstract Object execute(RS4Object receiver, Object identifier, Object valueObj);
+
+        @Specialization
+        protected Object access(RS4Object receiver, String identifier, Object valueObj,
+                        @Cached("createKeyInfoNode()") RS4ObjectKeyInfoImplNode keyInfo) {
+            int info = keyInfo.execute(receiver, identifier);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + identifier);
+            }
+
+            if (!KeyInfo.isWritable(info)) {
+                throw UnsupportedMessageException.raise(Message.WRITE);
+            }
+
+            if (foreign2R == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                foreign2R = insert(Foreign2RNodeGen.create());
+            }
+            Object value = foreign2R.execute(valueObj);
+            if (setAttributeNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                setAttributeNode = insert(SetAttributeNode.create());
+            }
+            setAttributeNode.execute(receiver, identifier, value);
+            return valueObj;
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") RS4Object receiver, Object identifier, @SuppressWarnings("unused") Object valueObj) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+
+        protected static RS4ObjectKeyInfoImplNode createKeyInfoNode() {
+            return RS4ObjectKeyInfoImplNodeGen.create();
+        }
+    }
+
+    abstract static class RS4ObjectKeyInfoImplNode extends Node {
+        @Child private GetAttributeNode getAttributeNode;
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        abstract int execute(RS4Object receiver, Object idx);
+
+        @Specialization
+        protected int access(RS4Object receiver, String identifier,
+                        @Cached("createArrayAttributeNode()") ArrayAttributeNode arrayAttrAccess) {
+            int idx = getAttrIndex(receiver, identifier, arrayAttrAccess);
+            if (unknownIdentifier.profile(idx < 0)) {
+                return 0;
+            }
+
+            if (getAttributeNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                getAttributeNode = insert(GetAttributeNode.create());
+            }
+            Builder builder = KeyInfo.newBuilder();
+            builder.setReadable(true).setWritable(!identifier.equals("class"));
+            builder.setInvocable(getAttributeNode.execute(receiver, identifier) instanceof RFunction);
+            return builder.build();
+        }
+
+        protected static ArrayAttributeNode createArrayAttributeNode() {
+            return ArrayAttributeNode.create();
+        }
+
+        @Fallback
+        protected int access(@SuppressWarnings("unused") RS4Object receiver, @SuppressWarnings("unused") Object field) {
+            return 0;
+        }
+    }
+
+    private static int getAttrIndex(RS4Object receiver, String identifier, ArrayAttributeNode arrayAttrAccess) {
+        RAttribute[] attributes = arrayAttrAccess.execute(receiver.getAttributes());
+        for (int i = 0; i < attributes.length; i++) {
+            if (attributes[i].getName().equals(identifier)) {
+                return i;
+            }
+        }
+        return -1;
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
index b7cff8ea42faf4cb92065c348e1f560d237780a3..d506157e6f72ff6ec0d09e76e792b5217b7b4396 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RSymbolMR.java
@@ -24,13 +24,29 @@ 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.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 
-@MessageResolution(receiverType = RSymbol.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RSymbol.class)
 public class RSymbolMR {
+
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RSymbolKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
+        }
+    }
+
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class RSymbolToNativeNode extends Node {
+        protected Object access(RSymbol receiver) {
+            return new NativePointer(receiver);
+        }
+    }
+
     @CanResolve
     public abstract static class RSymbolCheck extends Node {
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RUnboundValueMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RUnboundValueMR.java
index 2f6ad858cbcbfc8bc82d85e418d37c3e8436bb73..6810239ab9eda9b452af44aa14f75b0045e13aad 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RUnboundValueMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RUnboundValueMR.java
@@ -27,29 +27,15 @@ 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.RUnboundValue;
 
-@MessageResolution(receiverType = RUnboundValue.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = RUnboundValue.class)
 public class RUnboundValueMR {
-    @Resolve(message = "IS_BOXED")
-    public abstract static class RUnboundValueIsBoxedNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RUnboundValue receiver) {
-            return false;
-        }
-    }
-
-    @Resolve(message = "HAS_SIZE")
-    public abstract static class RUnboundValueHasSizeNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RUnboundValue receiver) {
-            return false;
-        }
-    }
 
-    @Resolve(message = "IS_NULL")
-    public abstract static class RUnboundValueIsNullNode extends Node {
-        protected Object access(@SuppressWarnings("unused") RUnboundValue receiver) {
-            return false;
+    @Resolve(message = "KEY_INFO")
+    public abstract static class RUnboundValueKeyInfoNode extends Node {
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, @SuppressWarnings("unused") Object identifier) {
+            return 0;
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_Call.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_Call.java
deleted file mode 100644
index 9b76276804be7dacb87f9e4d2d16712eea905654..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_Call.java
+++ /dev/null
@@ -1,254 +0,0 @@
-/*
- * 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
- * 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.ffi.llvm;
-
-import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.ImportStatic;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_CallFactory.InvokeTruffleNodeGen;
-import com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_CallFactory.SplitTruffleCallRFFINodeGen;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.ContextState;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.ffi.CallRFFI;
-import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
-import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
-import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
-import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
-import com.oracle.truffle.r.runtime.ffi.jni.JNI_Call;
-
-class TruffleLLVM_Call implements CallRFFI {
-    private static TruffleLLVM_Call truffleCall;
-    private static TruffleObject truffleCallTruffleObject;
-    private static TruffleObject truffleCallHelper;
-
-    @SuppressWarnings("unused")
-    TruffleLLVM_Call() {
-        new JNI_Call();
-        truffleCall = this;
-        truffleCallTruffleObject = JavaInterop.asTruffleObject(truffleCall);
-        truffleCallHelper = TruffleLLVM_UpCallsRFFIImpl.initialize();
-    }
-
-    static class ContextStateImpl implements RContext.ContextState {
-        private RContext context;
-        private boolean initVariablesDone;
-
-        @Override
-        public ContextState initialize(RContext contextA) {
-            this.context = contextA;
-            RFFIFactory.getRFFI().getCallRFFI();
-            context.addExportedSymbol("_fastr_rffi_call", truffleCallTruffleObject);
-            context.addExportedSymbol("_fastr_rffi_callhelper", truffleCallHelper);
-            return this;
-        }
-
-        @Override
-        public void beforeDestroy(RContext contextA) {
-        }
-    }
-
-    static ContextStateImpl newContextState() {
-        return new ContextStateImpl();
-    }
-
-    private enum INIT_VAR_FUN {
-        DOUBLE,
-        INT;
-
-        private final String funName;
-        private SymbolHandle symbolHandle;
-
-        INIT_VAR_FUN() {
-            funName = "Call_initvar_" + name().toLowerCase();
-        }
-    }
-
-    private static void initVariables(RContext context) {
-        // must have parsed the variables module in libR
-        for (INIT_VAR_FUN initVarFun : INIT_VAR_FUN.values()) {
-            TruffleLLVM_DLL.ensureParsed("libR", initVarFun.funName, true);
-            initVarFun.symbolHandle = new SymbolHandle(context.getEnv().importSymbol("@" + initVarFun.funName));
-        }
-        Node executeNode = Message.createExecute(2).createNode();
-        RFFIVariables[] variables = RFFIVariables.initialize();
-        for (int i = 0; i < variables.length; i++) {
-            // The TruffleObject instances are not passed down as
-            // they cannot be stored in memory at the moment
-            RFFIVariables var = variables[i];
-            Object value = var.getValue();
-            if (value == null) {
-                continue;
-            }
-            try {
-                if (value instanceof Double) {
-                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.DOUBLE.symbolHandle.asTruffleObject(), i, value);
-                } else if (value instanceof Integer) {
-                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.INT.symbolHandle.asTruffleObject(), i, value);
-                }
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere(t);
-            }
-        }
-    }
-
-    public static class InvokeJNICall extends Node {
-        @Child CallRFFI.InvokeCallNode jniCall = new JNI_Call.JNI_InvokeCallNode();
-
-        public Object execute(NativeCallInfo nativeCallInfo, Object[] args) {
-            return jniCall.execute(nativeCallInfo, args);
-        }
-    }
-
-    public static class InvokeJNIVoidCall extends Node {
-        @Child CallRFFI.InvokeVoidCallNode jniCall = new JNI_Call.JNI_InvokeVoidCallNode();
-
-        public Object execute(NativeCallInfo nativeCallInfo, Object[] args) {
-            jniCall.execute(nativeCallInfo, args);
-            return RNull.instance;
-        }
-    }
-
-    /**
-     * Experimentally the node created for the message send contains cached information regarding
-     * the target, which is {@link RContext} specific, leading to invalid data being accessed in
-     * SHARED_PARENT_RW contexts (specifically the cached exported symbols used for package
-     * initialization). So we guard the node with a check that the context has not changed.
-     *
-     */
-    @ImportStatic({Message.class, RContext.class})
-    public abstract static class InvokeTruffle extends Node {
-        public abstract Object execute(NativeCallInfo nativeCallInfo, Object[] args, RContext context);
-
-        @Specialization(guards = {"context == cachedContext"})
-        protected Object invokeCallCached(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") RContext context,
-                        @SuppressWarnings("unused") @Cached("getInstance()") RContext cachedContext,
-                        @Cached("createExecute(0).createNode()") Node messageNode,
-                        @SuppressWarnings("unused") @Cached("ensureReady(nativeCallInfo)") boolean ready) {
-            return doInvoke(messageNode, nativeCallInfo, args);
-        }
-
-        @Specialization(replaces = "invokeCallCached")
-        protected Object invokeCallNormal(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") RContext context) {
-            return doInvoke(Message.createExecute(0).createNode(), nativeCallInfo, args);
-        }
-
-        private static Object doInvoke(Node messageNode, NativeCallInfo nativeCallInfo, Object[] args) {
-            try {
-                return ForeignAccess.sendExecute(messageNode, nativeCallInfo.address.asTruffleObject(), args);
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere(t);
-            }
-        }
-
-        public static boolean ensureReady(NativeCallInfo nativeCallInfo) {
-            TruffleLLVM_DLL.ensureParsed(nativeCallInfo);
-            ContextStateImpl contextState = TruffleLLVM_RFFIContextState.getContextState().callState;
-            if (!contextState.initVariablesDone) {
-                initVariables(contextState.context);
-                contextState.initVariablesDone = true;
-            }
-            return true;
-        }
-
-        public static InvokeTruffle create() {
-            return InvokeTruffleNodeGen.create();
-        }
-    }
-
-    /**
-     * This class exists to separate out the delegated JNI calls from the Truffle calls.
-     */
-    public abstract static class SplitTruffleCallRFFINode extends Node {
-        public abstract Object execute(NativeCallInfo nativeCallInfo, Object[] args, boolean voidCall);
-
-        @Specialization(guards = {"isJNICall(nativeCallInfo)", "!voidCall"})
-        protected Object invokeCall(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean voidCall,
-                        @Cached("new()") InvokeJNICall invokeJNI) {
-            return invokeJNI.execute(nativeCallInfo, args);
-
-        }
-
-        @Specialization(guards = {"isJNICall(nativeCallInfo)", "voidCall"})
-        protected Object invokeVoidCall(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean voidCall,
-                        @Cached("new()") InvokeJNICall invokeJNI) {
-            return invokeJNI.execute(nativeCallInfo, args);
-
-        }
-
-        @Specialization(guards = "!isJNICall(nativeCallInfo)")
-        protected Object invokeCall(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean voidCall,
-                        @Cached("create()") InvokeTruffle invokeTruffle) {
-            return invokeTruffle.execute(nativeCallInfo, args, RContext.getInstance());
-        }
-
-        public static boolean isJNICall(NativeCallInfo nativeCallInfo) {
-            return nativeCallInfo.address.value instanceof Long;
-        }
-    }
-
-    private static class TruffleLLVM_InvokeCallNode extends InvokeCallNode {
-        @Child SplitTruffleCallRFFINode splitTruffleCallRFFINode = SplitTruffleCallRFFINodeGen.create();
-
-        @Override
-        public synchronized Object execute(NativeCallInfo nativeCallInfo, Object[] args) {
-            return splitTruffleCallRFFINode.execute(nativeCallInfo, args, false);
-
-        }
-    }
-
-    private static class TruffleLLVM_InvokeVoidCallNode extends InvokeVoidCallNode {
-        @Child SplitTruffleCallRFFINode splitTruffleCallRFFINode = SplitTruffleCallRFFINodeGen.create();
-
-        @Override
-        public synchronized void execute(NativeCallInfo nativeCallInfo, Object[] args) {
-            splitTruffleCallRFFINode.execute(nativeCallInfo, args, true);
-        }
-
-    }
-
-    /**
-     * Upcalled from Rinternal et al.
-     *
-     * @param function
-     */
-    public void unimplemented(String function) {
-        throw RInternalError.unimplemented("RFFI function: '" + function + "' not implemented");
-    }
-
-    @Override
-    public InvokeCallNode createInvokeCallNode() {
-        return new TruffleLLVM_InvokeCallNode();
-    }
-
-    @Override
-    public InvokeVoidCallNode createInvokeVoidCallNode() {
-        return new TruffleLLVM_InvokeVoidCallNode();
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_DLL.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_DLL.java
deleted file mode 100644
index 13eeb36eb0f4fcbb7ef9a53834e35b2d4e477ae8..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_DLL.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * 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.ffi.llvm;
-
-import java.nio.file.FileSystems;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Map;
-
-import com.oracle.truffle.api.CallTarget;
-import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.ContextState;
-import com.oracle.truffle.r.runtime.ffi.DLL;
-import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
-import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
-import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
-import com.oracle.truffle.r.runtime.ffi.jni.JNI_DLL;
-import com.oracle.truffle.r.runtime.ffi.truffle.LLVM_IR;
-
-/**
- * The Truffle version of {@link DLLRFFI}. {@code dlopen} expects to find the LLVM IR embedded in
- * the shared library. If it exists it is used, unless the library is blacklisted. Otherwise we fall
- * back to the standard JNI implementation.
- *
- * The LLVM bitcode is stored (opaquely) in the shared library file, and access through the
- * {@link LLVM_IR} class. The {@link LLVM_IR#getLLVMIR(String)} method will return an array of
- * {@link LLVM_IR} instances for all the modules in the library. These have to be parsed by the
- * Truffle LLVM system (into ASTs) before they can be interpreted/compiled. Note that there is no
- * support in Truffle LLVM itself for resolving references to functions in other LLVM modules. If
- * the function as an LLVM AST cannot be found it is assumed to be a native function. The upshot of
- * this is that, naively, every module in a library has to be parsed before any modules can be
- * executed, and inter-library dependencies also have to be handled explicitly. Most of the
- * inter-library references are to "libR", which is handled specially. If parsing was fast eager
- * parsing of all modules would not be an issue but, currently, is it not fast and some modules
- * exhibit pathologies that can take as long as a minute to parse, so some effort to support lazy
- * parsing has been implemented. Unfortunately this requires additional metadata. Note also that
- * only functions that are invoked explicitly through on of the RFFI interfaces can be handled
- * lazily; any internal calls must already be resolved (this would change if LLVM had the callback
- * facility alluded to above).
- *
- * This code can operate with lazy or eager parsing, but additional metadata has to be provided on
- * the defined/undefined symbols in a module.
- *
- * There is one major difference between native and LLVM libraries. There is a single global
- * instance of a native library and the symbols are, therefore, accessible from any {@link RContext}
- * instance . However, the (Truffle) function descriptors for an LLVM library are specific to the
- * {@link RContext} they are created (parsed) in. This has two important consequences:
- * <ol>
- * <li>It is theoretically possible to have different versions of libraries in different contexts.
- * </li>
- * <li>The {@code libR} library function descriptors must be made available in every context. At the
- * present time this can only be done by re-parsing the library contents.</li>
- * </ol>
- *
- * Note also that {@code libR} is the only library that is opened in native and LLVM mode, as the
- * native code is used by non-LLVM packages (libraries) and the LLVM code is used by the LLVM
- * packages (libraries).
- */
-class TruffleLLVM_DLL extends JNI_DLL implements DLLRFFI {
-    /**
-     * Supports lazy parsing of LLVM modules.
-     */
-    static class ParseStatus {
-        /**
-         * Name of associated library.
-         */
-        final String libName;
-        /**
-         * The LLVM IR (bitcode).
-         */
-        final LLVM_IR ir;
-        /**
-         * {@code true} iff the bitcode has been parsed into a Truffle AST.
-         */
-        boolean parsed;
-
-        ParseStatus(String libName, LLVM_IR ir, boolean parsed) {
-            this.libName = libName;
-            this.ir = ir;
-            this.parsed = parsed;
-        }
-
-        @Override
-        public String toString() {
-            CompilerAsserts.neverPartOfCompilation();
-            return String.format("lib %s, module %s, parsed %b%n", libName, ir.name, parsed);
-        }
-    }
-
-    static class ContextStateImpl implements RContext.ContextState {
-        /**
-         * A map from function name to its {@link ParseStatus}, allowing fast determination whether
-         * parsing is required in a call, see {@link #ensureParsed}. N.B. parsing happens at the
-         * module level, so all exported functions in one module share the same {@link ParseStatus}
-         * instance.
-         */
-        Map<String, ParseStatus> parseStatusMap = new HashMap<>();
-
-        /**
-         * When a new {@link RContext} is created we have to re-parse the libR modules,
-         * unfortunately, as there is no way to propagate the LLVM state created in the initial
-         * context. TODO when do we really need to do this? This is certainly too early for contexts
-         * that will not invoke LLVM code (e.g. most unit tests)
-         */
-        @Override
-        public ContextState initialize(RContext context) {
-            for (LLVM_IR ir : truffleDLL.libRModules) {
-                addExportsToMap(this, "libR", ir, (name) -> name.endsWith("_llvm"));
-            }
-            if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
-                // must propagate all LLVM library exports
-                ArrayList<DLLInfo> loadedDLLs = DLL.getLoadedDLLs();
-                for (DLLInfo dllInfo : loadedDLLs) {
-                    if (dllInfo.handle instanceof LLVM_Handle) {
-                        LLVM_Handle llvmHandle = (LLVM_Handle) dllInfo.handle;
-                        for (LLVM_IR ir : llvmHandle.irs) {
-                            addExportsToMap(this, llvmHandle.libName, ir, (name) -> true);
-                        }
-                    }
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public void beforeDestroy(RContext context) {
-            if (!context.isInitial()) {
-                parseStatusMap = null;
-            }
-        }
-    }
-
-    private static TruffleLLVM_DLL truffleDLL;
-
-    TruffleLLVM_DLL() {
-        assert truffleDLL == null;
-        truffleDLL = this;
-    }
-
-    static ContextStateImpl newContextState() {
-        return new ContextStateImpl();
-    }
-
-    static boolean isBlacklisted(String libName) {
-        String libs = System.getenv("FASTR_TRUFFLE_LIBS");
-        if (libs == null) {
-            Utils.warn(String.format("TruffleDLL: %s, FASTR_TRUFFLE_LIBS is unset, defaulting to JNI", libName));
-            return true;
-        }
-        String[] libsElems = libs.split(",");
-        for (String libsElem : libsElems) {
-            if (libName.equals(libsElem)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    static class LLVM_Handle {
-        private final String libName;
-        private final LLVM_IR[] irs;
-
-        LLVM_Handle(String libName, LLVM_IR[] irs) {
-            this.libName = libName;
-            this.irs = irs;
-        }
-    }
-
-    @FunctionalInterface
-    interface ModuleNameMatch {
-        boolean match(String name);
-    }
-
-    private static class TruffleLLVM_DLOpenNode extends JNI_DLOpenNode {
-
-        /**
-         * If a library is enabled for LLVM, the IR for all the modules is retrieved and analyzed.
-         * Every exported symbol in the module added to the parseStatus map for the current
-         * {@link RContext}. This allows {@code dlsym} to definitively locate any symbol, even if
-         * the IR has not been parsed yet.
-         */
-        @Override
-        public Object execute(String path, boolean local, boolean now) {
-            try {
-                LLVM_IR[] irs = LLVM_IR.getLLVMIR(path);
-                String libName = getLibName(path);
-                // even if libR is not all LLVM executed, some parts have to be
-                // but they can't be parsed now
-                if (libName.equals("libR")) {
-                    truffleDLL.libRModules = irs;
-                }
-                if (irs == null || isBlacklisted(libName)) {
-                    return super.execute(path, local, now);
-                } else {
-                    ContextStateImpl contextState = getContextState();
-                    for (int i = 0; i < irs.length; i++) {
-                        LLVM_IR ir = irs[i];
-                        addExportsToMap(contextState, libName, ir, (name) -> true);
-                    }
-                    return new LLVM_Handle(libName, irs);
-                }
-            } catch (Exception ex) {
-                return null;
-            }
-        }
-    }
-
-    private static class TruffleLLVM_DLSymNode extends JNI_DLSymNode {
-        @Override
-        public SymbolHandle execute(Object handle, String symbol) throws UnsatisfiedLinkError {
-            if (handle instanceof LLVM_Handle) {
-                // If the symbol exists it will be in the map
-                ParseStatus parseStatus = getContextState().parseStatusMap.get(symbol);
-                if (parseStatus != null && parseStatus.libName.equals(((LLVM_Handle) handle).libName)) {
-                    // force a parse so we have a "value"
-                    if (!parseStatus.parsed) {
-                        ensureParsed(parseStatus.libName, symbol, true);
-                    }
-                    Object symValue = RContext.getInstance().getEnv().importSymbol("@" + symbol);
-                    assert symValue != null;
-                    return new SymbolHandle(symValue);
-                } else {
-                    // symbol not found (or not in requested library)
-                    throw new UnsatisfiedLinkError();
-                }
-            } else {
-                return super.execute(handle, symbol);
-            }
-        }
-    }
-
-    private static class TruffleLLVM_DLCloseNode extends JNI_DLCloseNode {
-        @Override
-        public int execute(Object handle) {
-            if (handle instanceof LLVM_Handle) {
-                return 0;
-            } else {
-                return super.execute(handle);
-            }
-        }
-
-    }
-
-    @Override
-    public DLOpenNode createDLOpenNode() {
-        return new TruffleLLVM_DLOpenNode();
-    }
-
-    @Override
-    public DLSymNode createDLSymNode() {
-        return new TruffleLLVM_DLSymNode();
-    }
-
-    @Override
-    public DLCloseNode createDLCloseNode() {
-        return new TruffleLLVM_DLCloseNode();
-    }
-
-    private static void addExportsToMap(ContextStateImpl contextState, String libName, LLVM_IR ir, ModuleNameMatch moduleNameMatch) {
-        ParseStatus parseStatus = new ParseStatus(libName, ir, false);
-        for (String export : ir.exports) {
-            if (moduleNameMatch.match(ir.name)) {
-                assert contextState.parseStatusMap.get(export) == null;
-                contextState.parseStatusMap.put(export, parseStatus);
-            }
-        }
-    }
-
-    private static String getLibName(String path) {
-        String fileName = FileSystems.getDefault().getPath(path).getFileName().toString();
-        int ix = fileName.lastIndexOf(".");
-        return fileName.substring(0, ix);
-    }
-
-    /**
-     * Record of the libR modules for subsequent parsing.
-     */
-    private LLVM_IR[] libRModules;
-
-    private static ContextStateImpl getContextState() {
-        return TruffleLLVM_RFFIContextState.getContextState().dllState;
-    }
-
-    /**
-     * About to invoke the (external) function denoted by {@code nativeCallInfo}. Therefore, it must
-     * have been parsed (in {code dlsym}) AND all dependent modules, recursively, must also be
-     * parsed. Evidently since the dependencies are expressed at a module level, this may parse more
-     * than strictly necessary.
-     *
-     * @param nativeCallInfo
-     */
-    static void ensureParsed(NativeCallInfo nativeCallInfo) {
-        ensureParsed(nativeCallInfo.dllInfo.name, nativeCallInfo.name, true);
-    }
-
-    /**
-     * Similar to {@link #ensureParsed(NativeCallInfo)} but with a function specified as a string
-     * (for internal use) and an optional check whether the function must exist.
-     */
-    @TruffleBoundary
-    static void ensureParsed(String libName, String name, boolean fatalIfMissing) {
-        ContextStateImpl contextState = getContextState();
-        Map<String, ParseStatus> parseStatusMap = contextState.parseStatusMap;
-        ParseStatus parseStatus = parseStatusMap.get(name);
-        assert parseStatus != null || !fatalIfMissing;
-        if (parseStatus != null && !parseStatus.parsed) {
-            parseLLVM(parseStatus.ir);
-            parseStatus.parsed = true;
-            boolean isPackageInit = isPackageInit(libName, name);
-            for (String importee : parseStatus.ir.imports) {
-                /*
-                 * If we are resolving a package init call, we do not want to resolve all the
-                 * imports if functions in the same library as this will cause everything in the
-                 * library to be parsed eagerly!
-                 */
-                ParseStatus importeeParseStatus = parseStatusMap.get(importee);
-                boolean internal = isPackageInit && importeeParseStatus.libName.equals(libName);
-                if (importeeParseStatus != null && !internal) {
-                    ensureParsed(libName, importee, false);
-                }
-            }
-        }
-    }
-
-    private static boolean isPackageInit(@SuppressWarnings("unused") String libName, String name) {
-        if (name.startsWith(DLL.R_INIT_PREFIX)) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    private static void parseLLVM(LLVM_IR ir) {
-        if (ir instanceof LLVM_IR.Binary) {
-            LLVM_IR.Binary bir = (LLVM_IR.Binary) ir;
-            parseBinary(bir);
-        } else {
-            throw RInternalError.unimplemented("LLVM text IR");
-        }
-    }
-
-    private static CallTarget parseBinary(LLVM_IR.Binary ir) {
-        long start = System.nanoTime();
-        RContext context = RContext.getInstance();
-        long nanos = 1000 * 1000 * 1000;
-        Source source = Source.newBuilder(ir.base64).name(ir.name).mimeType("application/x-llvm-ir-bitcode-base64").build();
-        CallTarget result = context.getEnv().parse(source);
-        if (System.getenv("LLVM_PARSE_TIME") != null) {
-            long end = System.nanoTime();
-            System.out.printf("parsed %s in %f secs%n", ir.name, ((double) (end - start)) / (double) nanos);
-        }
-        return result;
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_PkgInit.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_PkgInit.java
deleted file mode 100644
index 6c4b235ca5d9d86afc256813a820c6cf21d21811..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_PkgInit.java
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * 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
- * 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.ffi.llvm;
-
-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.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.ContextState;
-import com.oracle.truffle.r.runtime.ffi.DLL;
-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;
-
-class TruffleLLVM_PkgInit {
-
-    private static TruffleLLVM_PkgInit trufflePkgInit;
-    private static TruffleObject trufflePkgInitTruffleObject;
-
-    static class ContextStateImpl implements RContext.ContextState {
-        @Override
-        public ContextState initialize(RContext context) {
-            TruffleLLVM_PkgInit.initialize();
-            context.addExportedSymbol("_fastr_rffi_pkginit", trufflePkgInitTruffleObject);
-            return this;
-        }
-
-        @Override
-        public void beforeDestroy(RContext context) {
-        }
-    }
-
-    static ContextStateImpl newContextState() {
-        return new ContextStateImpl();
-    }
-
-    private static TruffleLLVM_PkgInit initialize() {
-        if (trufflePkgInit == null) {
-            trufflePkgInit = new TruffleLLVM_PkgInit();
-            trufflePkgInitTruffleObject = JavaInterop.asTruffleObject(trufflePkgInit);
-        }
-        return trufflePkgInit;
-    }
-
-    public void registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines) {
-        DotSymbol[] array = new DotSymbol[num];
-        SymbolHandle setSymbolHandle = new SymbolHandle(RContext.getInstance().getEnv().importSymbol("@" + "PkgInit_setSymbol"));
-        for (int i = 0; i < num; i++) {
-            Object sym = setSymbol(nstOrd, routines, i, setSymbolHandle);
-            array[i] = (DotSymbol) sym;
-        }
-        dllInfo.setNativeSymbols(nstOrd, array);
-    }
-
-    private static Object setSymbol(int nstOrd, long routines, int index, SymbolHandle symbolHandle) {
-        Node executeNode = Message.createExecute(3).createNode();
-        try {
-
-            Object result = ForeignAccess.sendExecute(executeNode, symbolHandle.asTruffleObject(), nstOrd, routines, index);
-            return result;
-        } catch (Throwable t) {
-            throw RInternalError.shouldNotReachHere();
-        }
-    }
-
-    @SuppressWarnings("unused")
-    public void registerCCallable(String pkgName, String functionName, long address) {
-        // TBD
-        System.console();
-    }
-
-    @SuppressWarnings({"unused", "static-method"})
-    private long getCCallable(String pkgName, String functionName) {
-        // TBD
-        throw RInternalError.unimplemented();
-    }
-
-    /**
-     * Upcall from native to create a {@link DotSymbol} value.
-     */
-    public DotSymbol createDotSymbol(String name, Object fundesc, int numArgs) {
-        return new DotSymbol(name, new SymbolHandle(fundesc), numArgs);
-    }
-
-    public int useDynamicSymbols(DLLInfo dllInfo, int value) {
-        return DLL.useDynamicSymbols(dllInfo, value);
-    }
-
-    public int forceSymbols(DLLInfo dllInfo, int value) {
-        return DLL.forceSymbols(dllInfo, value);
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_RFFIFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_RFFIFactory.java
deleted file mode 100644
index 5a3324b95123c9149e5ed714018a3e5bc8e8416e..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_RFFIFactory.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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
- * 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.ffi.llvm;
-
-import com.oracle.truffle.r.runtime.context.RContext.ContextState;
-import com.oracle.truffle.r.runtime.ffi.CRFFI;
-import com.oracle.truffle.r.runtime.ffi.CallRFFI;
-import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFI;
-import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
-import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
-import com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory;
-
-/**
- * Incremental approach to using Truffle, defaults to the JNI factory.
- *
- */
-public class TruffleLLVM_RFFIFactory extends JNI_RFFIFactory implements RFFI {
-
-    @Override
-    public ContextState newContextState() {
-        return new TruffleLLVM_RFFIContextState(super.newContextState());
-    }
-
-    private CRFFI cRFFI;
-
-    @Override
-    public CRFFI getCRFFI() {
-        if (cRFFI == null) {
-            cRFFI = new TruffleLLVM_C();
-        }
-        return cRFFI;
-    }
-
-    private DLLRFFI dllRFFI;
-
-    @Override
-    public DLLRFFI getDLLRFFI() {
-        if (dllRFFI == null) {
-            dllRFFI = new TruffleLLVM_DLL();
-        }
-        return dllRFFI;
-    }
-
-    private UserRngRFFI truffleUserRngRFFI;
-
-    @Override
-    public UserRngRFFI getUserRngRFFI() {
-        if (truffleUserRngRFFI == null) {
-            truffleUserRngRFFI = new TruffleLLVM_UserRng();
-        }
-        return truffleUserRngRFFI;
-    }
-
-    private CallRFFI truffleCallRFFI;
-
-    @Override
-    public CallRFFI getCallRFFI() {
-        if (truffleCallRFFI == null) {
-            truffleCallRFFI = new TruffleLLVM_Call();
-        }
-        return truffleCallRFFI;
-    }
-
-    private StatsRFFI truffleStatsRFFI;
-
-    @Override
-    public StatsRFFI getStatsRFFI() {
-        if (TruffleLLVM_DLL.isBlacklisted("stats")) {
-            return super.getStatsRFFI();
-        }
-        if (truffleStatsRFFI == null) {
-            truffleStatsRFFI = new TruffleLLVM_Stats();
-        }
-        return truffleStatsRFFI;
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java
deleted file mode 100644
index bf5eeed417c045b2d985d2659a550f544863abca..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UpCallsRFFIImpl.java
+++ /dev/null
@@ -1,322 +0,0 @@
-/*
- * 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.ffi.llvm;
-
-import java.nio.charset.StandardCharsets;
-
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.r.engine.interop.NativeCharArray;
-import com.oracle.truffle.r.engine.interop.NativeDoubleArray;
-import com.oracle.truffle.r.engine.interop.NativeIntegerArray;
-import com.oracle.truffle.r.engine.interop.NativeLogicalArray;
-import com.oracle.truffle.r.engine.interop.NativeRawArray;
-import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
-import com.oracle.truffle.r.nodes.ffi.JavaUpCallsRFFIImpl;
-import com.oracle.truffle.r.runtime.REnvVars;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RDouble;
-import com.oracle.truffle.r.runtime.data.RInteger;
-import com.oracle.truffle.r.runtime.data.RLogical;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RScalar;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.data.RUnboundValue;
-import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
-import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
-import com.oracle.truffle.r.runtime.ffi.jni.JNIUpCallsRFFIImpl;
-
-/**
- * (Incomplete) Variant of {@link JavaUpCallsRFFIImpl} for Truffle LLVM.
- *
- */
-public class TruffleLLVM_UpCallsRFFIImpl extends JNIUpCallsRFFIImpl implements VariableUpCallsRFFI {
-    private static TruffleLLVM_UpCallsRFFIImpl singleton;
-    private static TruffleObject singletonTruffleObject;
-
-    public static TruffleObject initialize() {
-        if (singleton == null) {
-            singleton = new TruffleLLVM_UpCallsRFFIImpl();
-            singletonTruffleObject = JavaInterop.asTruffleObject(singleton);
-        }
-        return singletonTruffleObject;
-    }
-
-    public Object charSXPToNativeCharArray(Object x) {
-        CharSXPWrapper chars = RFFIUtils.guaranteeInstanceOf(x, CharSXPWrapper.class);
-        return new NativeCharArray(chars.getContents().getBytes());
-    }
-
-    // Checkstyle: stop method name check
-
-    @Override
-    public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) {
-        if (bytes instanceof NativeCharArray) {
-            return super.Rf_mkCharLenCE(((NativeCharArray) bytes).getBytes(), len, encoding);
-        } else {
-            throw RInternalError.unimplemented();
-        }
-    }
-
-    @Override
-    public Object Rf_install(Object name) {
-        if (name instanceof NativeCharArray) {
-            return RDataFactory.createSymbolInterned(new String(((NativeCharArray) name).getBytes(), StandardCharsets.UTF_8));
-        } else {
-            throw RInternalError.unimplemented();
-        }
-    }
-
-    @Override
-    public Object RAW(Object x) {
-        byte[] value = (byte[]) super.RAW(x);
-        return new NativeRawArray(value);
-    }
-
-    @Override
-    public Object LOGICAL(Object x) {
-        byte[] value = (byte[]) super.LOGICAL(x);
-        return new NativeLogicalArray(x, value);
-    }
-
-    @Override
-    public Object INTEGER(Object x) {
-        int[] value = (int[]) super.INTEGER(x);
-        return new NativeIntegerArray(x, value);
-    }
-
-    @Override
-    public Object REAL(Object x) {
-        // Special handling in Truffle variant
-        double[] value = (double[]) super.REAL(x);
-        return new NativeDoubleArray(x, value);
-    }
-
-    public Object R_Home() {
-        byte[] sbytes = REnvVars.rHome().getBytes();
-        return new NativeCharArray(sbytes);
-    }
-
-    @Override
-    public Object Rf_findVar(Object symbolArg, Object envArg) {
-        Object v = super.Rf_findVar(symbolArg, envArg);
-        if (v instanceof RTypedValue) {
-            return v;
-        } else {
-            return wrapPrimitive(v);
-        }
-    }
-
-    public Object bytesToNativeCharArray(byte[] bytes) {
-        return new NativeCharArray(bytes);
-    }
-
-    private static RScalar wrapPrimitive(Object x) {
-        if (x instanceof Double) {
-            return RDouble.valueOf((double) x);
-        } else if (x instanceof Integer) {
-            return RInteger.valueOf((int) x);
-        } else if (x instanceof Byte) {
-            return RLogical.valueOf((byte) x);
-        } else {
-            throw RInternalError.shouldNotReachHere();
-        }
-    }
-
-    @Override
-    public Object R_NilValue() {
-        return RNull.instance;
-    }
-
-    @Override
-    public Object R_UnboundValue() {
-        return RUnboundValue.instance;
-    }
-
-    @Override
-    public Object R_Srcref() {
-        return RFFIVariables.R_Srcref.getValue();
-    }
-
-    @Override
-    public Object R_MissingArg() {
-        return RFFIVariables.R_MissingArg.getValue();
-    }
-
-    @Override
-    public Object R_BaseSymbol() {
-        return RFFIVariables.R_BaseSymbol.getValue();
-    }
-
-    @Override
-    public Object R_BraceSymbol() {
-        return RFFIVariables.R_BraceSymbol.getValue();
-    }
-
-    @Override
-    public Object R_Bracket2Symbol() {
-        return RFFIVariables.R_Bracket2Symbol.getValue();
-    }
-
-    @Override
-    public Object R_BracketSymbol() {
-        return RFFIVariables.R_BracketSymbol.getValue();
-    }
-
-    @Override
-    public Object R_ClassSymbol() {
-        return RFFIVariables.R_ClassSymbol.getValue();
-    }
-
-    @Override
-    public Object R_DeviceSymbol() {
-        return RFFIVariables.R_DeviceSymbol.getValue();
-    }
-
-    @Override
-    public Object R_DimNamesSymbol() {
-        return RFFIVariables.R_DimNamesSymbol.getValue();
-    }
-
-    @Override
-    public Object R_DimSymbol() {
-        return RFFIVariables.R_DimSymbol.getValue();
-    }
-
-    @Override
-    public Object R_DollarSymbol() {
-        return RFFIVariables.R_DollarSymbol.getValue();
-    }
-
-    @Override
-    public Object R_DotsSymbol() {
-        return RFFIVariables.R_DotsSymbol.getValue();
-    }
-
-    @Override
-    public Object R_DropSymbol() {
-        return RFFIVariables.R_DropSymbol.getValue();
-    }
-
-    @Override
-    public Object R_LastvalueSymbol() {
-        return RFFIVariables.R_LastvalueSymbol.getValue();
-    }
-
-    @Override
-    public Object R_LevelsSymbol() {
-        return RFFIVariables.R_LevelsSymbol.getValue();
-    }
-
-    @Override
-    public Object R_ModeSymbol() {
-        return RFFIVariables.R_ModeSymbol.getValue();
-    }
-
-    @Override
-    public Object R_NaRmSymbol() {
-        return RFFIVariables.R_NaRmSymbol.getValue();
-    }
-
-    @Override
-    public Object R_NameSymbol() {
-        return RFFIVariables.R_NameSymbol.getValue();
-    }
-
-    @Override
-    public Object R_NamesSymbol() {
-        return RFFIVariables.R_NamesSymbol.getValue();
-    }
-
-    @Override
-    public Object R_NamespaceEnvSymbol() {
-        return RFFIVariables.R_NamespaceEnvSymbol.getValue();
-    }
-
-    @Override
-    public Object R_PackageSymbol() {
-        return RFFIVariables.R_PackageSymbol.getValue();
-    }
-
-    @Override
-    public Object R_QuoteSymbol() {
-        return RFFIVariables.R_QuoteSymbol.getValue();
-    }
-
-    @Override
-    public Object R_RowNamesSymbol() {
-        return RFFIVariables.R_RowNamesSymbol.getValue();
-    }
-
-    @Override
-    public Object R_SeedsSymbol() {
-        return RFFIVariables.R_SeedsSymbol.getValue();
-    }
-
-    @Override
-    public Object R_SourceSymbol() {
-        return RFFIVariables.R_SourceSymbol.getValue();
-    }
-
-    @Override
-    public Object R_TspSymbol() {
-        return RFFIVariables.R_TspSymbol.getValue();
-    }
-
-    @Override
-    public Object R_dot_defined() {
-        return RFFIVariables.R_dot_defined.getValue();
-    }
-
-    @Override
-    public Object R_dot_Method() {
-        return RFFIVariables.R_dot_Method.getValue();
-    }
-
-    @Override
-    public Object R_dot_target() {
-        return RFFIVariables.R_dot_target.getValue();
-    }
-
-    @Override
-    public Object R_NaString() {
-        return RFFIVariables.R_NaString.getValue();
-    }
-
-    @Override
-    public Object R_BlankString() {
-        return RFFIVariables.R_BlankString.getValue();
-    }
-
-    @Override
-    public Object R_BlankScalarString() {
-        return RFFIVariables.R_BlankScalarString.getValue();
-    }
-
-    @Override
-    public Object R_EmptyEnv() {
-        return RFFIVariables.R_EmptyEnv.getValue();
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UserRng.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UserRng.java
deleted file mode 100644
index 74dbb58f09a6dee2952996225d2e94c439f6fd15..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_UserRng.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.ffi.llvm;
-
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
-import com.oracle.truffle.r.runtime.rng.user.UserRNG.Function;
-
-public class TruffleLLVM_UserRng implements UserRngRFFI {
-    private static class TruffleUserRngRFFINode extends UserRngRFFINode {
-        Node initMessage;
-        Node randMessage;
-        Node nSeedMessage;
-        Node seedsMessage;
-        Node readPointerNode = Message.createExecute(1).createNode();
-
-        @Override
-        public void init(int seed) {
-            if (initMessage == null) {
-                initMessage = Message.createExecute(1).createNode();
-            }
-            try {
-                ForeignAccess.sendExecute(initMessage, Function.Init.getSymbolHandle().asTruffleObject(), seed);
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-
-        @Override
-        public double rand() {
-            if (randMessage == null) {
-                randMessage = Message.createExecute(0).createNode();
-            }
-            try {
-                Object address = ForeignAccess.sendExecute(randMessage, Function.Rand.getSymbolHandle().asTruffleObject());
-                Object value = ForeignAccess.sendExecute(readPointerNode, TruffleLLVM_CAccess.Function.READ_POINTER_DOUBLE.getSymbolHandle().asTruffleObject(), address);
-                return (double) value;
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-
-        @Override
-        public int nSeed() {
-            if (nSeedMessage == null) {
-                nSeedMessage = Message.createExecute(0).createNode();
-            }
-            try {
-                Object address = ForeignAccess.sendExecute(nSeedMessage, Function.NSeed.getSymbolHandle().asTruffleObject());
-                Object n = ForeignAccess.sendExecute(readPointerNode, TruffleLLVM_CAccess.Function.READ_POINTER_INT.getSymbolHandle().asTruffleObject(), address);
-                return (int) n;
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-
-        @Override
-        public void seeds(int[] n) {
-            if (seedsMessage == null) {
-                seedsMessage = Message.createExecute(0).createNode();
-            }
-            try {
-                Object address = ForeignAccess.sendExecute(seedsMessage, Function.Seedloc.getSymbolHandle().asTruffleObject());
-                for (int i = 0; i < n.length; i++) {
-                    Object seed = ForeignAccess.sendExecute(readPointerNode, TruffleLLVM_CAccess.Function.READ_ARRAY_INT.getSymbolHandle().asTruffleObject(), address, i);
-                    n[i] = (int) seed;
-                }
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-    }
-
-    @Override
-    public UserRngRFFINode createUserRngRFFINode() {
-        return new TruffleUserRngRFFINode();
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/VariableUpCallsRFFI.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/VariableUpCallsRFFI.java
deleted file mode 100644
index b1749e8e99b73274a59308a74f546a8a9310f371..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/VariableUpCallsRFFI.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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
- * 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.ffi.llvm;
-
-import com.oracle.truffle.api.interop.TruffleObject;
-
-/**
- * This exists because {@link TruffleObject} instances cannot currently be stored in memory, so
- * upcall to get the values.
- *
- * TODO Some of these, e.g. {@link #R_NilValue}, are performance sensitive, but most are not. So we
- * could collapse those into a single upcall that returned all the values in one go and extract the
- * value with another upcall.
- */
-public interface VariableUpCallsRFFI {
-    // Checkstyle: stop method name check
-
-    Object R_EmptyEnv();
-
-    Object R_NilValue();
-
-    Object R_UnboundValue();
-
-    Object R_Srcref();
-
-    Object R_MissingArg();
-
-    Object R_BaseSymbol();
-
-    Object R_BraceSymbol();
-
-    Object R_Bracket2Symbol();
-
-    Object R_BracketSymbol();
-
-    Object R_ClassSymbol();
-
-    Object R_DeviceSymbol();
-
-    Object R_DimNamesSymbol();
-
-    Object R_DimSymbol();
-
-    Object R_DollarSymbol();
-
-    Object R_DotsSymbol();
-
-    Object R_DropSymbol();
-
-    Object R_LastvalueSymbol();
-
-    Object R_LevelsSymbol();
-
-    Object R_ModeSymbol();
-
-    Object R_NaRmSymbol();
-
-    Object R_NameSymbol();
-
-    Object R_NamesSymbol();
-
-    Object R_NamespaceEnvSymbol();
-
-    Object R_PackageSymbol();
-
-    Object R_QuoteSymbol();
-
-    Object R_RowNamesSymbol();
-
-    Object R_SeedsSymbol();
-
-    Object R_SourceSymbol();
-
-    Object R_TspSymbol();
-
-    Object R_dot_defined();
-
-    Object R_dot_Method();
-
-    Object R_dot_target();
-
-    Object R_NaString();
-
-    Object R_BlankString();
-
-    Object R_BlankScalarString();
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
deleted file mode 100644
index 3ad8a7f1da8940084e236abec1033023f40d4d32..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Base.java
+++ /dev/null
@@ -1,399 +0,0 @@
-/*
- * 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
- * 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.ffi.nfi;
-
-import java.io.IOException;
-import java.util.ArrayList;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.InteropException;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
-import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
-
-public class TruffleNFI_Base implements BaseRFFI {
-
-    private enum Function {
-        getpid("(): sint32", true),
-        getcwd("([uint8], sint32): sint32", true),
-        chdir("(string): sint32", true),
-        mkdir("(string, sint32): sint32", true),
-        call_readlink("((string, sint32): void, string): void", false),
-        mkdtemp("([uint8]): sint32", true),
-        chmod("(string, sint32): sint32", true),
-        call_strtol("((sint64, sint32): void, string, sint32): void", false),
-        call_uname("((string, string, string, string, string): void): void", false),
-        call_glob("(string, (string): void): void", false);
-
-        private final int argCount;
-        private final String signature;
-        private final boolean useDefaultLibrary;
-        private Node message;
-        private TruffleObject function;
-
-        Function() {
-            this(null, true);
-        }
-
-        Function(String signature, boolean useDefaultLibrary) {
-            this.argCount = TruffleNFI_Utils.getArgCount(signature);
-            this.signature = signature;
-            this.useDefaultLibrary = useDefaultLibrary;
-        }
-
-        private void initialize() {
-            if (message == null) {
-                message = Message.createExecute(argCount).createNode();
-            }
-            if (function == null) {
-                function = TruffleNFI_Utils.lookupAndBind(name(), useDefaultLibrary, signature);
-            }
-        }
-    }
-
-    public static class TruffleNFI_GetpidNode extends GetpidNode {
-        @Override
-        public int execute() {
-            Function.getpid.initialize();
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.getpid.message, Function.getpid.function);
-                return result;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-
-        }
-    }
-
-    public static class TruffleNFI_GetwdNode extends GetwdNode {
-        @TruffleBoundary
-        @Override
-        public String execute() {
-            byte[] buf = new byte[4096];
-            Function.getcwd.initialize();
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.getcwd.message, Function.getcwd.function, JavaInterop.asTruffleObject(buf), buf.length);
-                if (result == 0) {
-                    return null;
-                } else {
-                    int i = 0;
-                    while (buf[i] != 0 && i < buf.length) {
-                        i++;
-                    }
-                    return new String(buf, 0, i);
-                }
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    public static class TruffleNFI_SetwdNode extends SetwdNode {
-        @Override
-        public int execute(String dir) {
-            Function.chdir.initialize();
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.chdir.message, Function.chdir.function, dir);
-                return result;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    public static class TruffleNFI_MkdirNode extends MkdirNode {
-        @Override
-        public void execute(String dir, int mode) throws IOException {
-            Function.mkdir.initialize();
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.mkdir.message, Function.mkdir.function, dir, mode);
-                if (result != 0) {
-                    throw new IOException("mkdir " + dir + " failed");
-                }
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    public static class TruffleNFI_ReadlinkNode extends ReadlinkNode {
-        private static final int EINVAL = 22;
-
-        interface SetResult {
-            void setResult(String link, int errno);
-        }
-
-        public static class SetResultImpl implements SetResult, RTruffleObject {
-            private String link;
-            private int errno;
-
-            @Override
-            public void setResult(String link, int errno) {
-                this.link = link;
-                this.errno = errno;
-            }
-
-        }
-
-        @Override
-        public String execute(String path) throws IOException {
-            Function.call_readlink.initialize();
-            try {
-                SetResultImpl setResultImpl = new SetResultImpl();
-                ForeignAccess.sendExecute(Function.call_readlink.message, Function.call_readlink.function, setResultImpl, path);
-                if (setResultImpl.link == null) {
-                    if (setResultImpl.errno == EINVAL) {
-                        return path;
-                    } else {
-                        // some other error
-                        throw new IOException("readlink failed: " + setResultImpl.errno);
-                    }
-                }
-                return setResultImpl.link;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    public static class TruffleNFI_MkdtempNode extends MkdtempNode {
-        @TruffleBoundary
-        @Override
-        public String execute(String template) {
-            /*
-             * Not only must the (C) string end in XXXXXX it must also be null-terminated. Since it
-             * is modified by mkdtemp we must make a copy.
-             */
-            byte[] bytes = template.getBytes();
-            byte[] ztbytes = new byte[bytes.length + 1];
-            System.arraycopy(bytes, 0, ztbytes, 0, bytes.length);
-            ztbytes[bytes.length] = 0;
-            Function.mkdtemp.initialize();
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.mkdtemp.message, Function.mkdtemp.function, JavaInterop.asTruffleObject(ztbytes));
-                if (result == 0) {
-                    return null;
-                } else {
-                    return new String(ztbytes, 0, bytes.length);
-                }
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    public static class TruffleNFI_ChmodNode extends ChmodNode {
-        @Override
-        public int execute(String path, int mode) {
-            Function.chmod.initialize();
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.chmod.message, Function.chmod.function, path, mode);
-                return result;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    public static class TruffleNFI_StrolNode extends StrolNode {
-        interface SetResult {
-            void setResult(long result, int errno);
-        }
-
-        private static class SetResultImpl implements SetResult {
-            private long result;
-            private int errno;
-
-            @Override
-            public void setResult(long result, int errno) {
-                this.result = result;
-                this.errno = errno;
-            }
-        }
-
-        @Override
-        public long execute(String s, int base) throws IllegalArgumentException {
-            Function.call_strtol.initialize();
-            try {
-                SetResultImpl setResultImpl = new SetResultImpl();
-                ForeignAccess.sendExecute(Function.call_strtol.message, Function.call_strtol.function, JavaInterop.asTruffleFunction(SetResult.class, setResultImpl), s, base);
-                if (setResultImpl.errno != 0) {
-                    throw new IllegalArgumentException("strtol failure");
-                } else {
-                    return setResultImpl.result;
-                }
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    public static class TruffleNFI_UnameNode extends UnameNode {
-        private static UnameUpCallImpl unameUpCallImpl;
-
-        private interface UnameUpCall {
-            void unameUpCall(String sysname, String release, String version, String machine, String nodename);
-        }
-
-        public static class UnameUpCallImpl implements UnameUpCall, UtsName, RTruffleObject {
-            private String sysname;
-            private String release;
-            private String version;
-            private String machine;
-            private String nodename;
-
-            @Override
-            public void unameUpCall(String sysnameA, String releaseA, String versionA, String machineA, String nodenameA) {
-                sysname = sysnameA;
-                release = releaseA;
-                version = versionA;
-                machine = machineA;
-                nodename = nodenameA;
-            }
-
-            @Override
-            public String sysname() {
-                return sysname;
-            }
-
-            @Override
-            public String release() {
-                return release;
-            }
-
-            @Override
-            public String version() {
-                return version;
-            }
-
-            @Override
-            public String machine() {
-                return machine;
-            }
-
-            @Override
-            public String nodename() {
-                return nodename;
-            }
-
-        }
-
-        @Override
-        public UtsName execute() {
-            Function.call_uname.initialize();
-            if (unameUpCallImpl == null) {
-                unameUpCallImpl = new UnameUpCallImpl();
-                try {
-                    ForeignAccess.sendExecute(Function.call_uname.message, Function.call_uname.function, unameUpCallImpl);
-                } catch (InteropException e) {
-                    throw RInternalError.shouldNotReachHere(e);
-                }
-            }
-            return unameUpCallImpl;
-        }
-    }
-
-    public static class TruffleNFI_GlobNode extends GlobNode {
-        private interface GlobUpCall {
-            void addPath(String path);
-        }
-
-        public static class GlobUpCallImpl implements GlobUpCall, RTruffleObject {
-            private ArrayList<String> paths = new ArrayList<>();
-
-            @Override
-            public void addPath(String path) {
-                paths.add(path);
-            }
-        }
-
-        @Override
-        public ArrayList<String> glob(String pattern) {
-            Function.call_glob.initialize();
-            GlobUpCallImpl globUpCallImpl = new GlobUpCallImpl();
-            try {
-                ForeignAccess.sendExecute(Function.call_glob.message, Function.call_glob.function, pattern, globUpCallImpl);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-            return globUpCallImpl.paths;
-        }
-
-    }
-
-    @Override
-    public GetpidNode createGetpidNode() {
-        return new TruffleNFI_GetpidNode();
-    }
-
-    @Override
-    public GetwdNode createGetwdNode() {
-        return new TruffleNFI_GetwdNode();
-    }
-
-    @Override
-    public SetwdNode createSetwdNode() {
-        return new TruffleNFI_SetwdNode();
-    }
-
-    @Override
-    public MkdirNode createMkdirNode() {
-        return new TruffleNFI_MkdirNode();
-    }
-
-    @Override
-    public ReadlinkNode createReadlinkNode() {
-        return new TruffleNFI_ReadlinkNode();
-    }
-
-    @Override
-    public MkdtempNode createMkdtempNode() {
-        return new TruffleNFI_MkdtempNode();
-    }
-
-    @Override
-    public ChmodNode createChmodNode() {
-        return new TruffleNFI_ChmodNode();
-    }
-
-    @Override
-    public StrolNode createStrolNode() {
-        return new TruffleNFI_StrolNode();
-    }
-
-    @Override
-    public UnameNode createUnameNode() {
-        return new TruffleNFI_UnameNode();
-    }
-
-    @Override
-    public GlobNode createGlobNode() {
-        return new TruffleNFI_GlobNode();
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java
deleted file mode 100644
index dbb6ece117d9ea866e4f85229fe517678b073a94..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_C.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2017, 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.ffi.nfi;
-
-import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.InteropException;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CFactory.TruffleNFI_InvokeCNodeGen;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.CRFFI;
-import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
-
-public class TruffleNFI_C implements CRFFI {
-    public abstract static class TruffleNFI_InvokeCNode extends InvokeCNode {
-
-        @Child Node bindNode = Message.createInvoke(1).createNode();
-
-        @Specialization(guards = "args.length == 0")
-        protected void invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args,
-                        @Cached("createExecute(args.length)") Node executeNode) {
-            synchronized (TruffleNFI_Call.class) {
-                try {
-                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
-                                    nativeCallInfo.address.asTruffleObject(), "bind", "(): object");
-                    ForeignAccess.sendExecute(executeNode, callFunction);
-                } catch (InteropException ex) {
-                    throw RInternalError.shouldNotReachHere(ex);
-                }
-            }
-        }
-
-        public static Node createExecute(int n) {
-            return Message.createExecute(n).createNode();
-        }
-
-    }
-
-    @Override
-    public InvokeCNode createInvokeCNode() {
-        return TruffleNFI_InvokeCNodeGen.create();
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java
deleted file mode 100644
index bfb50624dc9b50882c26eec3eb44f518e2fb8b5e..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Lapack.java
+++ /dev/null
@@ -1,318 +0,0 @@
-/*
- * 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
- * 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.ffi.nfi;
-
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.InteropException;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
-
-public class TruffleNFI_Lapack implements LapackRFFI {
-    enum Function {
-        ilaver("([sint32]): void"),
-        dgeev("(uint8, uint8, sint32, [double], sint32, [double], [double], [double], sint32, [double], sint32, [double], sint32) : sint32"),
-        dgeqp3("(sint32, sint32, [double], sint32, [sint32], [double], [double], sint32) : sint32"),
-        dormq("(uint8, uint8, sint32, sint32, sint32, [double], sint32, [double], [double], sint32, [double], sint32) : sint32"),
-        dtrtrs("(uint8, uint8, uint8, sint32, sint32, [double], sint32, [double], sint32) : sint32"),
-        dgetrf("(sint32, sint32, [double], sint32, [sint32]) : sint32"),
-        dpotrf("(uint8, sint32, [double], sint32) : sint32"),
-        dpotri("(uint8, sint32, [double], sint32) : sint32"),
-        dpstrf("uint8, sint32, [double], sint32, [sint32], [sint32], double, [double]) : sint32"),
-        dgesv("(sint32, sint32, [double], sint32, [sint32], [double], sint32) : sint32"),
-        dlange("(uint8, sint32, sint32, [double], sint32, [double]) : double"),
-        dgecon("(uint8, sint32, [double], sint32, double, [double], [double], [sint32]) : sint32"),
-        dsyevr("(uint8, uint8, uint8, sint32, [double], sint32, double, double, sint32, sint32, double, [sint32], [double], [double], sint32, [sint32], [double], sint32, [sint32], sint32) : sint32");
-
-        private final int argCount;
-        private final String signature;
-        @CompilationFinal private Node executeNode;
-        @CompilationFinal private TruffleObject function;
-
-        Function(String signature) {
-            this.argCount = TruffleNFI_Utils.getArgCount(signature);
-            this.signature = signature;
-        }
-
-        private void initialize() {
-            if (executeNode == null) {
-                executeNode = Message.createExecute(argCount).createNode();
-            }
-            if (function == null) {
-                function = TruffleNFI_Utils.lookupAndBind("call_" + name(), false, signature);
-            }
-        }
-    }
-
-    private static class TruffleNFI_IlaverNode extends IlaverNode {
-
-        @Override
-        public void execute(int[] version) {
-            Function.ilaver.initialize();
-            try {
-                ForeignAccess.sendExecute(Function.ilaver.executeNode, Function.ilaver.function, JavaInterop.asTruffleObject(version));
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-
-        }
-    }
-
-    private static class TruffleNFI_DgeevNode extends DgeevNode {
-
-        @Override
-        public int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
-            Function.dgeev.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dgeev.executeNode, Function.dgeev.function, jobVL, jobVR, n, JavaInterop.asTruffleObject(a), lda,
-                                JavaInterop.asTruffleObject(wr), JavaInterop.asTruffleObject(wi), JavaInterop.asTruffleObject(vl), ldvl,
-                                JavaInterop.asTruffleObject(vr), ldvr, JavaInterop.asTruffleObject(work), lwork);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_Dgeqp3Node extends Dgeqp3Node {
-
-        @Override
-        public int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
-            Function.dgeqp3.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dgeqp3.executeNode, Function.dgeqp3.function, m, n, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(jpvt),
-                                JavaInterop.asTruffleObject(tau), JavaInterop.asTruffleObject(work), lwork);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DormqrNode extends DormqrNode {
-
-        @Override
-        public int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
-            Function.dormq.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dormq.executeNode, Function.dormq.function, side, trans, m, n, k, JavaInterop.asTruffleObject(a), lda,
-                                JavaInterop.asTruffleObject(tau), JavaInterop.asTruffleObject(c), ldc, JavaInterop.asTruffleObject(work), lwork);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DtrtrsNode extends DtrtrsNode {
-
-        @Override
-        public int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
-            Function.dtrtrs.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dtrtrs.executeNode, Function.dtrtrs.function, uplo, trans, diag, n, nrhs, JavaInterop.asTruffleObject(a), lda,
-                                JavaInterop.asTruffleObject(b), ldb);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DgetrfNode extends DgetrfNode {
-
-        @Override
-        public int execute(int m, int n, double[] a, int lda, int[] ipiv) {
-            Function.dgetrf.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dgetrf.executeNode, Function.dgetrf.function, m, n, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(ipiv));
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DpotrfNode extends DpotrfNode {
-
-        @Override
-        public int execute(char uplo, int n, double[] a, int lda) {
-            Function.dpotrf.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dpotrf.executeNode, Function.dpotrf.function, uplo, n, JavaInterop.asTruffleObject(a), lda);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DpotriNode extends DpotriNode {
-
-        @Override
-        public int execute(char uplo, int n, double[] a, int lda) {
-            Function.dpotri.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dpotri.executeNode, Function.dpotri.function, uplo, n, JavaInterop.asTruffleObject(a), lda);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DpstrfNode extends DpstrfNode {
-
-        @Override
-        public int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
-            Function.dpstrf.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dpstrf.executeNode, Function.dpstrf.function, uplo, n, JavaInterop.asTruffleObject(a), lda,
-                                JavaInterop.asTruffleObject(piv), JavaInterop.asTruffleObject(rank), tol, JavaInterop.asTruffleObject(work));
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DgesvNode extends DgesvNode {
-
-        @Override
-        public int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
-            Function.dgesv.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dgesv.executeNode, Function.dgesv.function, n, nrhs, JavaInterop.asTruffleObject(a), lda, JavaInterop.asTruffleObject(ipiv),
-                                JavaInterop.asTruffleObject(b), ldb);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DlangeNode extends DlangeNode {
-
-        @Override
-        public double execute(char norm, int m, int n, double[] a, int lda, double[] work) {
-            Function.dlange.initialize();
-            try {
-                return (double) ForeignAccess.sendExecute(Function.dlange.executeNode, Function.dlange.function, norm, m, n, JavaInterop.asTruffleObject(a), lda,
-                                JavaInterop.asTruffleObject(work));
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DgeconNode extends DgeconNode {
-
-        @Override
-        public int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
-            Function.dgecon.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dgecon.executeNode, Function.dgecon.function, norm, n, JavaInterop.asTruffleObject(a), lda, anorm, JavaInterop.asTruffleObject(rcond),
-                                JavaInterop.asTruffleObject(work), JavaInterop.asTruffleObject(iwork));
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_DsyevrNode extends DsyevrNode {
-
-        @Override
-        public int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, double[] z, int ldz, int[] isuppz,
-                        double[] work, int lwork, int[] iwork, int liwork) {
-            Function.dsyevr.initialize();
-            try {
-                return (int) ForeignAccess.sendExecute(Function.dsyevr.executeNode, Function.dsyevr.function, jobz, range, uplo, n, JavaInterop.asTruffleObject(a),
-                                lda, vl, vu, il, iu, abstol, JavaInterop.asTruffleObject(m), JavaInterop.asTruffleObject(w), JavaInterop.asTruffleObject(z), ldz,
-                                JavaInterop.asTruffleObject(isuppz), JavaInterop.asTruffleObject(work), lwork, JavaInterop.asTruffleObject(iwork), liwork);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    @Override
-    public IlaverNode createIlaverNode() {
-        return new TruffleNFI_IlaverNode();
-    }
-
-    @Override
-    public DgeevNode createDgeevNode() {
-        return new TruffleNFI_DgeevNode();
-    }
-
-    @Override
-    public Dgeqp3Node createDgeqp3Node() {
-        return new TruffleNFI_Dgeqp3Node();
-    }
-
-    @Override
-    public DormqrNode createDormqrNode() {
-        return new TruffleNFI_DormqrNode();
-    }
-
-    @Override
-    public DtrtrsNode createDtrtrsNode() {
-        return new TruffleNFI_DtrtrsNode();
-    }
-
-    @Override
-    public DgetrfNode createDgetrfNode() {
-        return new TruffleNFI_DgetrfNode();
-    }
-
-    @Override
-    public DpotrfNode createDpotrfNode() {
-        return new TruffleNFI_DpotrfNode();
-    }
-
-    @Override
-    public DpotriNode createDpotriNode() {
-        return new TruffleNFI_DpotriNode();
-    }
-
-    @Override
-    public DpstrfNode createDpstrfNode() {
-        return new TruffleNFI_DpstrfNode();
-    }
-
-    @Override
-    public DgesvNode createDgesvNode() {
-        return new TruffleNFI_DgesvNode();
-    }
-
-    @Override
-    public DlangeNode createDlangeNode() {
-        return new TruffleNFI_DlangeNode();
-    }
-
-    @Override
-    public DgeconNode createDgeconNode() {
-        return new TruffleNFI_DgeconNode();
-    }
-
-    @Override
-    public DsyevrNode createDsyevrNode() {
-        return new TruffleNFI_DsyevrNode();
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
deleted file mode 100644
index 50b713e9625588e2f5ef4eff05da7647d9f8f8be..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PCRE.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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
- * 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.ffi.nfi;
-
-import java.nio.charset.StandardCharsets;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.InteropException;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
-import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
-
-public class TruffleNFI_PCRE implements PCRERFFI {
-    private enum Function {
-        maketables("(): sint64", true),
-        compile("((uint64, string, sint32): void, string, sint32, uint64): void", false),
-        getcapturecount("(uint64, uint64): sint32", false),
-        getcapturenames("((sint32, string): void, uint64, uint64): sint32", false),
-        study("(uint64, sint32): void", false),
-        exec("(uint64, uint64, [uint8], sint32, sint32, sint32, [sint32], sint32): sint32", true);
-
-        private final int argCount;
-        private final String signature;
-        private final String callName;
-        private Node executeNode;
-        private TruffleObject function;
-
-        Function(String signature, boolean direct) {
-            this.argCount = TruffleNFI_Utils.getArgCount(signature);
-            this.signature = signature;
-            this.callName = (direct ? "pcre_" : "call_") + name();
-        }
-
-        private void initialize() {
-            if (executeNode == null) {
-                executeNode = Message.createExecute(argCount).createNode();
-            }
-            if (function == null) {
-                function = TruffleNFI_Utils.lookupAndBind(callName, false, signature);
-            }
-        }
-    }
-
-    private static class TruffleNFI_MaketablesNode extends MaketablesNode {
-
-        @Override
-        public long execute() {
-            Function.maketables.initialize();
-            try {
-                long result = (long) ForeignAccess.sendExecute(Function.maketables.executeNode, Function.maketables.function);
-                return result;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-
-    }
-
-    private static class TruffleNFI_GetCaptureCountNode extends GetCaptureCountNode {
-
-        @Override
-        public int execute(long code, long extra) {
-            Function.getcapturecount.initialize();
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.getcapturecount.executeNode, Function.getcapturecount.function, code, extra);
-                return result;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    public static class TruffleNFI_GetCaptureNamesNode extends GetCaptureNamesNode {
-        interface CaptureNames {
-            void addName(int i, String name);
-        }
-
-        public static final class CaptureNamesImpl implements CaptureNames, RTruffleObject {
-            private final String[] captureNames;
-
-            private CaptureNamesImpl(int captureCount) {
-                captureNames = new String[captureCount];
-            }
-
-            @Override
-            public void addName(int i, String name) {
-                captureNames[i] = name;
-            }
-
-        }
-
-        @Override
-        public String[] execute(long code, long extra, int captureCount) {
-            Function.getcapturenames.initialize();
-            try {
-                CaptureNamesImpl captureNamesImpl = new CaptureNamesImpl(captureCount);
-                int result = (int) ForeignAccess.sendExecute(Function.getcapturenames.executeNode, Function.getcapturenames.function,
-                                captureNamesImpl, code, extra);
-                if (result < 0) {
-                    CompilerDirectives.transferToInterpreter();
-                    throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, result);
-                } else {
-                    return captureNamesImpl.captureNames;
-                }
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-
-    }
-
-    public static class TruffleNFI_CompileNode extends CompileNode {
-        interface MakeResult {
-            void makeresult(long pcreResult, String errorMessage, int errOffset);
-        }
-
-        public static class MakeResultImpl implements MakeResult, RTruffleObject {
-            private PCRERFFI.Result result;
-
-            @Override
-            public void makeresult(long pcreResult, String errorMessage, int errOffset) {
-                result = new PCRERFFI.Result(pcreResult, errorMessage, errOffset);
-            }
-        }
-
-        @Override
-        public Result execute(String pattern, int options, long tables) {
-            Function.compile.initialize();
-            try {
-                MakeResultImpl makeResultImpl = new MakeResultImpl();
-                ForeignAccess.sendExecute(Function.compile.executeNode, Function.compile.function, makeResultImpl,
-                                pattern, options, tables);
-                return makeResultImpl.result;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-
-    }
-
-    private static class TruffleNFI_ExecNode extends ExecNode {
-
-        @Override
-        public int execute(long code, long extra, String subject, int offset, int options, int[] ovector) {
-            Function.exec.initialize();
-            try {
-
-                byte[] subjectBytes = subject.getBytes(StandardCharsets.UTF_8);
-                return (int) ForeignAccess.sendExecute(Function.exec.executeNode, Function.exec.function, code, extra,
-                                JavaInterop.asTruffleObject(subjectBytes), subjectBytes.length,
-                                offset, options, JavaInterop.asTruffleObject(ovector), ovector.length);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-
-    }
-
-    @Override
-    public MaketablesNode createMaketablesNode() {
-        return new TruffleNFI_MaketablesNode();
-    }
-
-    @Override
-    public CompileNode createCompileNode() {
-        return new TruffleNFI_CompileNode();
-    }
-
-    @Override
-    public GetCaptureCountNode createGetCaptureCountNode() {
-        return new TruffleNFI_GetCaptureCountNode();
-    }
-
-    @Override
-    public GetCaptureNamesNode createGetCaptureNamesNode() {
-        return new TruffleNFI_GetCaptureNamesNode();
-    }
-
-    @Override
-    public StudyNode createStudyNode() {
-        throw RInternalError.unimplemented();
-    }
-
-    @Override
-    public ExecNode createExecNode() {
-        return new TruffleNFI_ExecNode();
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
deleted file mode 100644
index 2621894a9023bdad32f2c628be578698b03a4c4f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_PkgInit.java
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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
- * 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.ffi.nfi;
-
-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.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.DLL;
-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;
-
-public final class TruffleNFI_PkgInit {
-
-    private enum UpCall {
-        registerRoutines("(object, sint32, sint32, uint64): void"),
-        useDynamicSymbols("(object, sint32): sint32"),
-        setDotSymbolValues("(object, string, pointer, sint32): object"),
-        forceSymbols("(object, sint32): sint32");
-        private final String signature;
-
-        UpCall(String signature) {
-            this.signature = signature;
-        }
-    }
-
-    /**
-     * The upcalls from native code that support symbol registration.
-     */
-    interface UpCalls {
-
-        /**
-         * This is the start, called from {@code R_RegisterRoutines}.
-         *
-         * @param dllInfo library the symbols are defined in
-         * @param nstOrd the ordinal value corresponding to
-         *            {@link com.oracle.truffle.r.runtime.ffi.DLL.NativeSymbolType}.
-         * @param num the number of functions being registered
-         * @param routines the C address of the function table (not interpreted).
-         */
-        void registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines);
-
-        /**
-         * Internal upcall used by {@code Rdynload_setSymbol}. The {@code fun} value must be
-         * converted to a {@link TruffleObject} representing the symbol}.
-         *
-         * @param dllInfo library the symbol is defined in
-         * @param name name of function
-         * @param fun the C address of the function (in the table)
-         * @param numArgs the number of arguments the function takes.
-         */
-        DotSymbol setDotSymbolValues(DLLInfo dllInfo, String name, TruffleObject fun, int numArgs);
-
-        /**
-         * Directly implements {@code R_useDynamicSymbols}.
-         */
-        int useDynamicSymbols(DLLInfo dllInfo, int value);
-
-        /**
-         * Directly implements {@code R_forceSymbols}.
-         */
-        int forceSymbols(DLLInfo dllInfo, int value);
-
-    }
-
-    private static class UpCallsImpl implements UpCalls {
-        /**
-         * First create the array, then downcall to native to get the specific info for each symbol
-         * which is delivered by {@link #setDotSymbolValues}.
-         */
-        @Override
-        public void registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines) {
-            DotSymbol[] array = new DotSymbol[num];
-            for (int i = 0; i < num; i++) {
-                array[i] = setSymbol(dllInfo, nstOrd, routines, i);
-            }
-            dllInfo.setNativeSymbols(nstOrd, array);
-        }
-
-        @Override
-        public int useDynamicSymbols(DLLInfo dllInfo, int value) {
-            return DLL.useDynamicSymbols(dllInfo, value);
-        }
-
-        @Override
-        public DotSymbol setDotSymbolValues(DLLInfo dllInfo, String name, TruffleObject fun, int numArgs) {
-            /*
-             * We don't know the NFI signature at this point, so we cannot bind the function here.
-             */
-            DotSymbol result = new DotSymbol(name, new SymbolHandle(fun), numArgs);
-            return result;
-        }
-
-        @Override
-        public int forceSymbols(DLLInfo dllInfo, int value) {
-            return DLL.forceSymbols(dllInfo, value);
-        }
-    }
-
-    private static final String SETSYMBOL_SIGNATURE = "(object, sint32, uint64, sint32): object";
-    private static TruffleObject setSymbolFunction;
-
-    static void initialize() {
-        Node bind = Message.createInvoke(1).createNode();
-        SymbolHandle symbolHandle = DLL.findSymbol("Rdynload_init", null);
-        Node executeNode = Message.createExecute(2).createNode();
-        UpCallsImpl upCalls = new UpCallsImpl();
-        TruffleObject upCallsObject = JavaInterop.asTruffleObject(upCalls);
-        Node readNode = Message.READ.createNode();
-        try {
-            for (UpCall upCall : UpCall.values()) {
-                Object upCallMethodObject = ForeignAccess.sendRead(readNode, upCallsObject, upCall.name());
-                String addCallbackSignature = String.format("(sint32, %s): void", upCall.signature);
-                TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature);
-                ForeignAccess.sendExecute(executeNode, addCallbackFunction, upCall.ordinal(), upCallMethodObject);
-            }
-            symbolHandle = DLL.findSymbol("Rdynload_setSymbol", null);
-            setSymbolFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", SETSYMBOL_SIGNATURE);
-        } catch (Throwable t) {
-            throw RInternalError.shouldNotReachHere(t);
-        }
-    }
-
-    private static DotSymbol setSymbol(DLLInfo dllInfo, int nstOrd, long routines, int index) {
-        Node executeNode = Message.createExecute(4).createNode();
-        try {
-            DotSymbol result = (DotSymbol) ForeignAccess.sendExecute(executeNode, setSymbolFunction, dllInfo, nstOrd, routines, index);
-            return result;
-        } catch (Throwable t) {
-            throw RInternalError.shouldNotReachHere(t);
-        }
-
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java
deleted file mode 100644
index e0289cdacb3859fe985e575944e9ae99bfb82276..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RAppl.java
+++ /dev/null
@@ -1,146 +0,0 @@
-/*
- * 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
- * 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.ffi.nfi;
-
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.InteropException;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
-
-public class TruffleNFI_RAppl implements RApplRFFI {
-    enum Function {
-        dqrdc2("([double], sint32, sint32, sint32, double, [sint32], [double], [sint32], [double]): void"),
-        dqrcf("([double], sint32, sint32, [double], [double], sint32, [double], [sint32]): void"),
-        dqrls("([double], sint32, sint32, [double], sint32, double, [double], [double], [double], [sint32], [sint32], [double], [double]): void");
-
-        private final int argCount;
-        private final String signature;
-        @CompilationFinal private Node executeNode;
-        @CompilationFinal private TruffleObject function;
-
-        Function(String signature) {
-            this.argCount = TruffleNFI_Utils.getArgCount(signature);
-            this.signature = signature;
-        }
-
-        private void initialize() {
-            if (executeNode == null) {
-                executeNode = Message.createExecute(argCount).createNode();
-            }
-            if (function == null) {
-                function = TruffleNFI_Utils.lookupAndBind("call_" + name(), false, signature);
-            }
-        }
-    }
-
-    private static class TruffleNFI_Dqrdc2Node extends Dqrdc2Node {
-
-        @Override
-        public void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
-            Function.dqrdc2.initialize();
-            try {
-                ForeignAccess.sendExecute(Function.dqrdc2.executeNode, Function.dqrdc2.function,
-                                JavaInterop.asTruffleObject(x),
-                                ldx, n, p, tol,
-                                JavaInterop.asTruffleObject(rank),
-                                JavaInterop.asTruffleObject(qraux),
-                                JavaInterop.asTruffleObject(pivot),
-                                JavaInterop.asTruffleObject(work));
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-
-        }
-
-    }
-
-    private static class TruffleNFI_DqrcfNode extends DqrcfNode {
-
-        @Override
-        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) {
-            Function.dqrcf.initialize();
-            try {
-                ForeignAccess.sendExecute(Function.dqrcf.executeNode, Function.dqrcf.function,
-                                JavaInterop.asTruffleObject(x),
-                                n, k,
-                                JavaInterop.asTruffleObject(qraux),
-                                JavaInterop.asTruffleObject(y),
-                                ny,
-                                JavaInterop.asTruffleObject(b),
-                                JavaInterop.asTruffleObject(info));
-
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-
-    }
-
-    private static class TruffleNFI_DqrlsNode extends DqrlsNode {
-
-        @Override
-        public void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
-            Function.dqrls.initialize();
-            try {
-                ForeignAccess.sendExecute(Function.dqrls.executeNode, Function.dqrls.function,
-                                JavaInterop.asTruffleObject(x),
-                                n, p,
-                                JavaInterop.asTruffleObject(y),
-                                ny, tol,
-                                JavaInterop.asTruffleObject(b),
-                                JavaInterop.asTruffleObject(rsd),
-                                JavaInterop.asTruffleObject(qty),
-                                JavaInterop.asTruffleObject(k),
-                                JavaInterop.asTruffleObject(jpvt),
-                                JavaInterop.asTruffleObject(qraux),
-                                JavaInterop.asTruffleObject(work));
-
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-
-        }
-
-    }
-
-    @Override
-    public Dqrdc2Node createDqrdc2Node() {
-        return new TruffleNFI_Dqrdc2Node();
-    }
-
-    @Override
-    public DqrcfNode createDqrcfNode() {
-        return new TruffleNFI_DqrcfNode();
-    }
-
-    @Override
-    public DqrlsNode createDqrlsNode() {
-        return new TruffleNFI_DqrlsNode();
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
deleted file mode 100644
index a892fb8876d8fc1524dd660a2db4706d7aef253c..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_RFFIFactory.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * Copyright (c) 2017, 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.ffi.nfi;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.ContextState;
-import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
-import com.oracle.truffle.r.runtime.ffi.CRFFI;
-import com.oracle.truffle.r.runtime.ffi.CallRFFI;
-import com.oracle.truffle.r.runtime.ffi.DLL;
-import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
-import com.oracle.truffle.r.runtime.ffi.LibPaths;
-import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
-import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
-import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
-import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
-import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
-import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
-import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
-import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
-
-public class TruffleNFI_RFFIFactory extends RFFIFactory implements RFFI {
-    private static class ContextStateImpl implements RContext.ContextState {
-        @Override
-        public ContextState initialize(RContext context) {
-            if (context.isInitial()) {
-                String librffiPath = LibPaths.getBuiltinLibPath("R");
-                DLL.loadLibR(librffiPath);
-            }
-            return this;
-        }
-    }
-
-    @Override
-    public ContextState newContextState() {
-        return new ContextStateImpl();
-    }
-
-    @Override
-    protected RFFI createRFFI() {
-        return this;
-    }
-
-    @CompilationFinal private CRFFI cRFFI;
-
-    @Override
-    public CRFFI getCRFFI() {
-        if (cRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            cRFFI = new TruffleNFI_C();
-        }
-        return cRFFI;
-    }
-
-    @CompilationFinal private BaseRFFI baseRFFI;
-
-    @Override
-    public BaseRFFI getBaseRFFI() {
-        if (baseRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            baseRFFI = new TruffleNFI_Base();
-        }
-        return baseRFFI;
-    }
-
-    @CompilationFinal private CallRFFI callRFFI;
-
-    @Override
-    public CallRFFI getCallRFFI() {
-        if (callRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            callRFFI = new TruffleNFI_Call();
-        }
-        return callRFFI;
-    }
-
-    @CompilationFinal private DLLRFFI dllRFFI;
-
-    @Override
-    public DLLRFFI getDLLRFFI() {
-        if (dllRFFI == null) {
-            dllRFFI = new TruffleNFI_DLL();
-        }
-        return dllRFFI;
-    }
-
-    @CompilationFinal private UserRngRFFI userRngRFFI;
-
-    @Override
-    public UserRngRFFI getUserRngRFFI() {
-        if (userRngRFFI == null) {
-            userRngRFFI = new TruffleNFI_UserRng();
-        }
-        return userRngRFFI;
-    }
-
-    @CompilationFinal private ZipRFFI zipRFFI;
-
-    @Override
-    public ZipRFFI getZipRFFI() {
-        if (zipRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            zipRFFI = new TruffleNFI_Zip();
-        }
-        return zipRFFI;
-    }
-
-    @CompilationFinal private PCRERFFI pcreRFFI;
-
-    @Override
-    public PCRERFFI getPCRERFFI() {
-        if (pcreRFFI == null) {
-            pcreRFFI = new TruffleNFI_PCRE();
-        }
-        return pcreRFFI;
-    }
-
-    @CompilationFinal private LapackRFFI lapackRFFI;
-
-    @Override
-    public LapackRFFI getLapackRFFI() {
-        if (lapackRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            lapackRFFI = new TruffleNFI_Lapack();
-        }
-        return lapackRFFI;
-    }
-
-    @CompilationFinal private RApplRFFI rApplRFFI;
-
-    @Override
-    public RApplRFFI getRApplRFFI() {
-        if (rApplRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            rApplRFFI = new TruffleNFI_RAppl();
-        }
-        return rApplRFFI;
-    }
-
-    @CompilationFinal private StatsRFFI statsRFFI;
-
-    @Override
-    public StatsRFFI getStatsRFFI() {
-        if (statsRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            statsRFFI = new TruffleNFI_Stats();
-        }
-        return statsRFFI;
-    }
-
-    @CompilationFinal private ToolsRFFI toolsRFFI;
-
-    @Override
-    public ToolsRFFI getToolsRFFI() {
-        if (toolsRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            toolsRFFI = new TruffleNFI_Tools();
-        }
-        return toolsRFFI;
-    }
-
-    private REmbedRFFI rEmbedRFFI;
-
-    @Override
-    public REmbedRFFI getREmbedRFFI() {
-        if (rEmbedRFFI == null) {
-            rEmbedRFFI = new TruffleNFI_REmbed();
-        }
-        return rEmbedRFFI;
-    }
-
-    private MiscRFFI miscRFFI;
-
-    @Override
-    public MiscRFFI getMiscRFFI() {
-        if (miscRFFI == null) {
-            miscRFFI = new TruffleNFI_Misc();
-        }
-        return miscRFFI;
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java
deleted file mode 100644
index f6c8d87e1640ad50158ca3e719616916556b9028..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Stats.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * 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
- * 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.ffi.nfi;
-
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.InteropException;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.DLL;
-import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
-import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
-import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
-import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
-
-public class TruffleNFI_Stats implements StatsRFFI {
-
-    private static class TruffleNFI_FactorNode extends FactorNode {
-        private static final String FFT_FACTOR = "fft_factor";
-        private static final String FFT_FACTOR_SIGNATURE = "(sint32, [sint32], [sint32]): void";
-
-        @Child Node factorMessage = Message.createExecute(3).createNode();
-        @Child DLLRFFI.DLSymNode dlsymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
-
-        @CompilationFinal private TruffleObject fftFactorFunction;
-
-        @Override
-        public void execute(int n, int[] pmaxf, int[] pmaxp) {
-            try {
-                if (fftFactorFunction == null) {
-                    Node bind = Message.createInvoke(1).createNode();
-                    fftFactorFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, findSymbol(FFT_FACTOR, dlsymNode).asTruffleObject(), "bind", FFT_FACTOR_SIGNATURE);
-                }
-                ForeignAccess.sendExecute(factorMessage, fftFactorFunction, n, JavaInterop.asTruffleObject(pmaxf), JavaInterop.asTruffleObject(pmaxp));
-            } catch (InteropException t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-    }
-
-    private static class TruffleNFI_WorkNode extends WorkNode {
-        private static final String FFT_WORK = "fft_work";
-        private static final String FFT_WORK_SIGNATURE = "([double], sint32, sint32, sint32, sint32, [double], [sint32]): sint32";
-
-        @Child DLLRFFI.DLSymNode dlsymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
-        @Child Node workMessage = Message.createExecute(7).createNode();
-        @CompilationFinal private TruffleObject fftWorkFunction;
-
-        @Override
-        public int execute(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) {
-            try {
-                if (fftWorkFunction == null) {
-                    Node bind = Message.createInvoke(1).createNode();
-                    fftWorkFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, findSymbol(FFT_WORK, dlsymNode).asTruffleObject(), "bind", FFT_WORK_SIGNATURE);
-                }
-                return (int) ForeignAccess.sendExecute(workMessage, fftWorkFunction, JavaInterop.asTruffleObject(a), nseg, n, nspn, isn,
-                                JavaInterop.asTruffleObject(work), JavaInterop.asTruffleObject(iwork));
-            } catch (InteropException t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-
-    }
-
-    private static SymbolHandle findSymbol(String symbol, DLLRFFI.DLSymNode dlsymNode) {
-        SymbolHandle fftAddress;
-        DLLInfo dllInfo = DLL.findLibrary("stats");
-        assert dllInfo != null;
-        fftAddress = dlsymNode.execute(dllInfo.handle, symbol);
-        assert fftAddress != DLL.SYMBOL_NOT_FOUND;
-        return fftAddress;
-    }
-
-    @Override
-    public FactorNode createFactorNode() {
-        return new TruffleNFI_FactorNode();
-    }
-
-    @Override
-    public WorkNode createWorkNode() {
-        return new TruffleNFI_WorkNode();
-    }
-
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java
deleted file mode 100644
index e94994edaf5cceb5843f062d8836a40112c4d8d1..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UserRng.java
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) 2017, 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.ffi.nfi;
-
-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.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
-import com.oracle.truffle.r.runtime.rng.user.UserRNG.Function;
-
-public class TruffleNFI_UserRng implements UserRngRFFI {
-
-    private static class NFIUserRngRFFINode extends UserRngRFFINode {
-        Node initMessage;
-        Node randMessage;
-        Node nSeedMessage;
-        Node seedsMessage;
-        Node readPointerNode = Message.createExecute(1).createNode();
-
-        TruffleObject initFunction;
-        TruffleObject nSeedFunction;
-        TruffleObject randFunction;
-        TruffleObject seedsFunction;
-
-        @Override
-        public void init(int seed) {
-            if (initMessage == null) {
-                initMessage = Message.createExecute(1).createNode();
-            }
-            try {
-                if (initFunction == null) {
-                    Node bind = Message.createInvoke(1).createNode();
-                    initFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Init.getSymbolHandle().asTruffleObject(), "bind", "(sint32): void");
-                }
-                ForeignAccess.sendExecute(initMessage, initFunction, seed);
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-
-        @Override
-        public double rand() {
-            if (randMessage == null) {
-                randMessage = Message.createExecute(0).createNode();
-            }
-            try {
-                if (randFunction == null) {
-                    Node bind = Message.createInvoke(1).createNode();
-                    randFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Rand.getSymbolHandle().asTruffleObject(), "bind", "(): pointer");
-                }
-                Object address = ForeignAccess.sendExecute(randMessage, randFunction);
-                Object value = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_POINTER_DOUBLE.getSymbolFunction(), address);
-                return (double) value;
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-
-        @Override
-        public int nSeed() {
-            if (nSeedMessage == null) {
-                nSeedMessage = Message.createExecute(0).createNode();
-            }
-            try {
-                if (nSeedFunction == null) {
-                    Node bind = Message.createInvoke(1).createNode();
-                    nSeedFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.NSeed.getSymbolHandle().asTruffleObject(), "bind", "(): pointer");
-                }
-                Object address = ForeignAccess.sendExecute(nSeedMessage, nSeedFunction);
-                Object n = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_POINTER_INT.getSymbolFunction(), address);
-                return (int) n;
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-
-        @Override
-        public void seeds(int[] n) {
-            if (seedsMessage == null) {
-                seedsMessage = Message.createExecute(0).createNode();
-            }
-            try {
-                if (seedsFunction == null) {
-                    Node bind = Message.createInvoke(1).createNode();
-                    seedsFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, Function.Seedloc.getSymbolHandle().asTruffleObject(), "bind", "(): pointer");
-                }
-                Object address = ForeignAccess.sendExecute(seedsMessage, seedsFunction);
-                for (int i = 0; i < n.length; i++) {
-                    Object seed = ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_ARRAY_INT.getSymbolFunction(), address, i);
-                    n[i] = (int) seed;
-                }
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere();
-            }
-        }
-    }
-
-    @Override
-    public UserRngRFFINode createUserRngRFFINode() {
-        return new NFIUserRngRFFINode();
-    }
-}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java
deleted file mode 100644
index 957b88ea243c08d4ee217dcf951bc25882d321ec..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Zip.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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
- * 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.ffi.nfi;
-
-import com.oracle.truffle.api.interop.ForeignAccess;
-import com.oracle.truffle.api.interop.InteropException;
-import com.oracle.truffle.api.interop.Message;
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
-
-public class TruffleNFI_Zip implements ZipRFFI {
-
-    private enum Function {
-        compress("([uint8], [uint64], [uint8], uint64): sint32"),
-        uncompress("([uint8], [uint64], [uint8], uint64): sint32");
-
-        private final int argCount;
-        private final String signature;
-        private Node executeNode;
-        private TruffleObject function;
-
-        Function(String signature) {
-            this.argCount = TruffleNFI_Utils.getArgCount(signature);
-            this.signature = signature;
-        }
-
-        private void initialize() {
-            if (executeNode == null) {
-                executeNode = Message.createExecute(argCount).createNode();
-            }
-            if (function == null) {
-                function = TruffleNFI_Utils.lookupAndBind(name(), true, signature);
-            }
-        }
-    }
-
-    private static class TruffleNFI_CompressNode extends ZipRFFI.CompressNode {
-
-        @Override
-        public int execute(byte[] dest, byte[] source) {
-            Function.compress.initialize();
-            long[] destlen = new long[]{dest.length};
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.compress.executeNode, Function.compress.function,
-                                JavaInterop.asTruffleObject(dest), JavaInterop.asTruffleObject(destlen),
-                                JavaInterop.asTruffleObject(source), JavaInterop.asTruffleObject(source.length));
-                return result;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    private static class TruffleNFI_UncompressNode extends ZipRFFI.UncompressNode {
-        @Override
-        public int execute(byte[] dest, byte[] source) {
-            Function.uncompress.initialize();
-            long[] destlen = new long[]{dest.length};
-            try {
-                int result = (int) ForeignAccess.sendExecute(Function.uncompress.executeNode, Function.uncompress.function,
-                                JavaInterop.asTruffleObject(dest), JavaInterop.asTruffleObject(destlen),
-                                JavaInterop.asTruffleObject(source), JavaInterop.asTruffleObject(source.length));
-                return result;
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        }
-    }
-
-    @Override
-    public CompressNode createCompressNode() {
-        return new TruffleNFI_CompressNode();
-    }
-
-    @Override
-    public UncompressNode createUncompressNode() {
-        return new TruffleNFI_UncompressNode();
-    }
-
-}
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 c47155062d8634fd1b9d7b965304af8a6ccc7779..df5ee9b5ec6870758839cdfc5d89b3fef497a123 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
@@ -23,10 +23,11 @@
 package com.oracle.truffle.r.engine.shell;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
+import com.oracle.truffle.r.launcher.DefaultConsoleHandler;
+import com.oracle.truffle.r.launcher.JLineConsoleHandler;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.RInterfaceCallbacks;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
 import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
@@ -55,63 +56,63 @@ public class EmbeddedConsoleHandler extends ConsoleHandler {
     @TruffleBoundary
     private REmbedRFFI getREmbedRFFI() {
         if (rEmbedRFFI == null) {
-            rEmbedRFFI = RFFIFactory.getRFFI().getREmbedRFFI();
+            rEmbedRFFI = RFFIFactory.getREmbedRFFI();
             if (!(RInterfaceCallbacks.R_WriteConsole.isOverridden() || RInterfaceCallbacks.R_ReadConsole.isOverridden())) {
-                if (startParams.getNoReadline()) {
+                if (startParams.noReadline()) {
                     delegate = new DefaultConsoleHandler(System.in, System.out);
                 } else {
-                    delegate = new JLineConsoleHandler(startParams, System.in, System.out);
+                    delegate = new JLineConsoleHandler(System.in, System.out, startParams.isSlave());
                 }
             }
         }
         return rEmbedRFFI;
     }
 
-    @Override
-    @TruffleBoundary
-    public void println(String s) {
-        getREmbedRFFI();
-        if (delegate == null) {
-            getREmbedRFFI().writeConsole(s);
-            getREmbedRFFI().writeConsole("\n");
-        } else {
-            delegate.println(s);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void print(String s) {
-        getREmbedRFFI();
-        if (delegate == null) {
-            rEmbedRFFI.writeConsole(s);
-        } else {
-            delegate.print(s);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printErrorln(String s) {
-        getREmbedRFFI();
-        if (delegate == null) {
-            rEmbedRFFI.writeErrConsole(s);
-            rEmbedRFFI.writeErrConsole("\n");
-        } else {
-            delegate.printErrorln(s);
-        }
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printError(String s) {
-        getREmbedRFFI();
-        if (delegate == null) {
-            rEmbedRFFI.writeErrConsole(s);
-        } else {
-            delegate.printError(s);
-        }
-    }
+    // @Override
+    // @TruffleBoundary
+    // public void println(String s) {
+    // getREmbedRFFI();
+    // if (delegate == null) {
+    // getREmbedRFFI().writeConsole(s);
+    // getREmbedRFFI().writeConsole("\n");
+    // } else {
+    // delegate.println(s);
+    // }
+    // }
+    //
+    // @Override
+    // @TruffleBoundary
+    // public void print(String s) {
+    // getREmbedRFFI();
+    // if (delegate == null) {
+    // rEmbedRFFI.writeConsole(s);
+    // } else {
+    // delegate.print(s);
+    // }
+    // }
+    //
+    // @Override
+    // @TruffleBoundary
+    // public void printErrorln(String s) {
+    // getREmbedRFFI();
+    // if (delegate == null) {
+    // rEmbedRFFI.writeErrConsole(s);
+    // rEmbedRFFI.writeErrConsole("\n");
+    // } else {
+    // delegate.printErrorln(s);
+    // }
+    // }
+    //
+    // @Override
+    // @TruffleBoundary
+    // public void printError(String s) {
+    // getREmbedRFFI();
+    // if (delegate == null) {
+    // rEmbedRFFI.writeErrConsole(s);
+    // } else {
+    // delegate.printError(s);
+    // }
+    // }
 
     @Override
     @TruffleBoundary
@@ -124,16 +125,6 @@ public class EmbeddedConsoleHandler extends ConsoleHandler {
         }
     }
 
-    @Override
-    public boolean isInteractive() {
-        return startParams.getInteractive();
-    }
-
-    @Override
-    public String getPrompt() {
-        return prompt;
-    }
-
     @Override
     @TruffleBoundary
     public void setPrompt(String prompt) {
@@ -142,9 +133,4 @@ public class EmbeddedConsoleHandler extends ConsoleHandler {
             delegate.setPrompt(prompt);
         }
     }
-
-    @Override
-    public String getInputDescription() {
-        return "<embedded input>";
-    }
 }
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
deleted file mode 100644
index b5e7c8ae1eb3dec0c024c9185b453d5e7ee94507..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleCompleter.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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.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 jline.console.completer.Completer;
-
-public class JLineConsoleCompleter implements Completer {
-    private final ConsoleHandler console;
-
-    private static boolean isTesting = false;
-
-    public static void testingMode() {
-        isTesting = true;
-    }
-
-    public JLineConsoleCompleter(ConsoleHandler console) {
-        this.console = console;
-    }
-
-    @Override
-    public int complete(String buffer, int cursor, List<CharSequence> candidates) {
-        try {
-            return completeImpl(buffer, cursor, candidates);
-        } catch (Throwable e) {
-            if (isTesting) {
-                throw e;
-            }
-            RInternalError.reportErrorAndConsoleLog(e, console, 0);
-        }
-        return cursor;
-    }
-
-    @SuppressWarnings("try")
-    private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
-        if (buffer.isEmpty()) {
-            return cursor;
-        }
-
-        try (RCloseable c = RContext.withinContext(console.getContext())) {
-
-            REnvironment utils = REnvironment.getRegisteredNamespace("utils");
-            Object o = utils.get(".completeToken");
-            if (o instanceof RPromise) {
-                o = PromiseHelperNode.evaluateSlowPath((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), true, 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));
-            }
-            Collections.sort(ret, String.CASE_INSENSITIVE_ORDER);
-            candidates.addAll(ret);
-            return start;
-        }
-    }
-
-    private static int getStart(String buffer, REnvironment env, int cursor) {
-        int start = 0;
-        Object o = env.get("options");
-        if (o instanceof RList) {
-            RList opt = (RList) o;
-            start = lastIdxOf(buffer, opt, "funarg.suffix", start, cursor);
-            start = lastIdxOf(buffer, opt, "function.suffix", start, cursor);
-        }
-        start = lastIdxOf(buffer, "\"", start, cursor);
-        start = lastIdxOf(buffer, "'", start, cursor);
-        return start;
-    }
-
-    private static int lastIdxOf(String buffer, RList opt, String key, int start, int cursor) {
-        int optIdx = opt.getElementIndexByName(key);
-        if (optIdx > -1) {
-            Object o = opt.getDataAt(optIdx);
-            if (o instanceof RAbstractStringVector) {
-                RAbstractStringVector v = (RAbstractStringVector) o;
-                return lastIdxOf(buffer, v.getLength() > 0 ? v.getDataAt(0) : null, start, cursor);
-            }
-        }
-        return start;
-    }
-
-    private static int lastIdxOf(String buffer, String subs, int start, int cursor) {
-        if (null != subs && !subs.isEmpty()) {
-            int idx = buffer.lastIndexOf(subs, cursor);
-            if (idx == cursor) {
-                idx = buffer.lastIndexOf(subs, cursor - 1);
-            }
-            if (idx > -1) {
-                idx += subs.length();
-                return idx > start ? idx : start;
-            }
-        }
-        return start;
-    }
-}
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
deleted file mode 100644
index 6353be6e9a9fc9199ef8dea6a3744c386a8f8908..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/JLineConsoleHandler.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * 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
- * 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.shell;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-
-import jline.console.ConsoleReader;
-import jline.console.UserInterruptException;
-import jline.console.history.FileHistory;
-import jline.console.history.History;
-
-class JLineConsoleHandler extends ConsoleHandler {
-    private final ConsoleReader console;
-    private final boolean isInteractive;
-    private final PrintWriter printWriter;
-
-    JLineConsoleHandler(RStartParams startParams, InputStream inStream, OutputStream outStream) {
-        try {
-            console = new ConsoleReader(inStream, outStream);
-            console.addCompleter(new JLineConsoleCompleter(this));
-            console.setHandleUserInterrupt(true);
-            console.setExpandEvents(false);
-        } catch (IOException ex) {
-            throw Utils.rSuicide("unexpected error opening console reader");
-        }
-        // long start = System.currentTimeMillis();
-        printWriter = new PrintWriter(console.getOutput());
-        this.isInteractive = startParams.getInteractive();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void println(String s) {
-        printWriter.println(s);
-        printWriter.flush();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void print(String s) {
-        printWriter.print(s);
-        printWriter.flush();
-    }
-
-    @Override
-    @TruffleBoundary
-    public String readLine() {
-        try {
-            console.getTerminal().init();
-            return console.readLine();
-        } catch (UserInterruptException e) {
-            throw e;
-        } catch (Exception ex) {
-            throw Utils.rSuicide("unexpected error reading console input: " + ex);
-        }
-    }
-
-    @Override
-    public boolean isInteractive() {
-        return isInteractive;
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printErrorln(String s) {
-        println(s);
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printError(String s) {
-        print(s);
-    }
-
-    @Override
-    @TruffleBoundary
-    public String getPrompt() {
-        return console.getPrompt();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void setPrompt(String prompt) {
-        console.setPrompt(prompt);
-    }
-
-    @Override
-    public String getInputDescription() {
-        return RSource.Internal.SHELL_INPUT.string;
-    }
-
-    @Override
-    public void setHistoryFrom(File file) {
-        try {
-            console.setHistory(new FileHistory(file));
-        } catch (IOException x) {
-            // silent - there will simply be no history
-        }
-    }
-
-    @Override
-    public void flushHistory() {
-        History history = console.getHistory();
-        if (history instanceof FileHistory) {
-            try {
-                history.removeLast();
-                ((FileHistory) history).flush();
-            } catch (IOException x) {
-                // silent - no history appended
-            }
-        }
-    }
-}
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
deleted file mode 100644
index b48d4d484ac9d48719bceb299b3178ab290caaee..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ /dev/null
@@ -1,343 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.engine.shell;
-
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.EXPR;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.FILE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.INTERACTIVE;
-
-import java.io.Console;
-import java.io.EOFException;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.nio.file.Files;
-import java.util.List;
-
-import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.api.vm.PolyglotEngine.Value;
-import com.oracle.truffle.r.nodes.builtin.base.Quit;
-import com.oracle.truffle.r.runtime.ExitException;
-import com.oracle.truffle.r.runtime.JumpToTopLevelException;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
-import com.oracle.truffle.r.runtime.Utils;
-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;
-
-/**
- * Emulates the (Gnu)R command as precisely as possible.
- */
-public class RCommand {
-
-    // CheckStyle: stop system..print check
-
-    public static void main(String[] args) {
-        doMain(args, null, true, System.in, System.out);
-        // never returns
-        throw RInternalError.shouldNotReachHere();
-    }
-
-    public static int doMain(String[] args, String[] env, boolean initial, InputStream inStream, OutputStream outStream) {
-        RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false);
-        options.printHelpAndVersion();
-        ContextInfo info = createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env);
-        return readEvalPrint(info.createVM(), info);
-    }
-
-    /**
-     * The standard R script escapes spaces to "~+~" in "-e" and "-f" commands.
-     */
-    private static String unescapeSpace(String input) {
-        return input.replace("~+~", " ");
-    }
-
-    static ContextInfo createContextInfoFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) {
-        RStartParams rsp = new RStartParams(options, embedded);
-
-        String fileArg = options.getString(FILE);
-        if (fileArg != null) {
-            if (options.getStringList(EXPR) != null) {
-                Utils.rSuicide("cannot use -e with -f or --file");
-            }
-            if (!rsp.getSlave()) {
-                rsp.setSaveAction(SA_TYPE.NOSAVE);
-            }
-            if (fileArg.equals("-")) {
-                // means stdin, but still implies NO_SAVE
-                fileArg = null;
-            } else {
-                fileArg = unescapeSpace(fileArg);
-            }
-            // cf GNU R
-            rsp.setInteractive(false);
-        }
-
-        /*
-         * Outputting the welcome message here has the virtue that the VM initialization delay
-         * occurs later. However, it does not work in embedded mode as console redirects have not
-         * been installed at this point. So we do it later in REmbedded.
-         */
-        if (!rsp.getQuiet() && !embedded) {
-            System.out.println(RRuntime.WELCOME_MESSAGE);
-        }
-        /*
-         * Whether the input is from stdin, a file (-f), or an expression on the command line (-e)
-         * it goes through the console. N.B. -f and -e can't be used together and this is already
-         * checked.
-         */
-        ConsoleHandler consoleHandler;
-        if (fileArg != null) {
-            List<String> lines;
-            String filePath;
-            try {
-                /*
-                 * If initial==false, ~ expansion will not have been done and the open will fail.
-                 * It's harmless to always do it.
-                 */
-                File file = new File(Utils.tildeExpand(fileArg));
-                lines = Files.readAllLines(file.toPath());
-                filePath = file.getCanonicalPath();
-            } catch (IOException e) {
-                if (initial) {
-                    throw Utils.rSuicide(String.format(RError.Message.NO_SUCH_FILE.message, fileArg));
-                } else {
-                    throw RError.error(RError.NO_CALLER, RError.Message.NO_SUCH_FILE, fileArg);
-                }
-            }
-            consoleHandler = new StringConsoleHandler(lines, outStream, filePath);
-        } else if (options.getStringList(EXPR) != null) {
-            List<String> exprs = options.getStringList(EXPR);
-            for (int i = 0; i < exprs.size(); i++) {
-                exprs.set(i, unescapeSpace(exprs.get(i)));
-            }
-            if (!rsp.getSlave()) {
-                rsp.setSaveAction(SA_TYPE.NOSAVE);
-            }
-            // cf GNU R
-            rsp.setInteractive(false);
-            consoleHandler = new StringConsoleHandler(exprs, outStream, RSource.Internal.EXPRESSION_INPUT.string);
-        } else {
-            /*
-             * GnuR behavior differs from the manual entry for {@code interactive} in that {@code
-             * --interactive} never applies to {@code -e/-f}, only to console input that has been
-             * redirected from a pipe/file etc.
-             *
-             * If we are in embedded mode, the creation of ConsoleReader and the ConsoleHandler
-             * should be lazy, as these may not be necessary and can cause hangs if stdin has been
-             * redirected.
-             */
-            Console sysConsole = System.console(); // TODO fix for context sessions
-            boolean isInteractive = options.getBoolean(INTERACTIVE) || sysConsole != null;
-            if (!isInteractive && rsp.getSaveAction() != SA_TYPE.SAVE && rsp.getSaveAction() != SA_TYPE.NOSAVE) {
-                String msg = "you must specify '--save', '--no-save' or '--vanilla'";
-                if (initial) {
-                    throw Utils.rSuicide(msg);
-                } else {
-                    throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, msg);
-                }
-            }
-            if (embedded) {
-                consoleHandler = new EmbeddedConsoleHandler(rsp);
-            } else {
-                boolean useReadLine = !rsp.getNoReadline();
-                if (useReadLine) {
-                    consoleHandler = new JLineConsoleHandler(rsp, inStream, outStream);
-                } else {
-                    consoleHandler = new DefaultConsoleHandler(inStream, outStream);
-                }
-            }
-        }
-        return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler);
-    }
-
-    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
-     * file. There are two ways the repl can terminate:
-     * <ol>
-     * <li>A {@code quit} command is executed successfully, which case the system exits from the
-     * {@link Quit} {@code .Internal} .</li>
-     * <li>EOF on the input.</li>
-     * </ol>
-     * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before
-     * exiting. So,in either case, we never return.
-     */
-    static int readEvalPrint(PolyglotEngine vm, ContextInfo info) {
-        int lastStatus = 0;
-        ConsoleHandler consoleHandler = info.getConsoleHandler();
-        try {
-            // console.println("initialize time: " + (System.currentTimeMillis() - start));
-            REPL: for (;;) {
-                boolean doEcho = doEcho(vm);
-                consoleHandler.setPrompt(doEcho ? "> " : null);
-                try {
-                    String input = consoleHandler.readLine();
-                    if (input == null) {
-                        throw new EOFException();
-                    }
-                    String trInput = input.trim();
-                    if (trInput.equals("") || trInput.charAt(0) == '#') {
-                        // nothing to parse
-                        continue;
-                    }
-
-                    String continuePrompt = getContinuePrompt(vm);
-                    StringBuilder sb = new StringBuilder(input);
-                    Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
-                    boolean hasExecutor = hasExectuor(vm);
-                    while (true) {
-                        lastStatus = 0;
-                        try {
-                            try {
-                                Value val = vm.eval(source);
-                                if (hasExecutor) {
-                                    val.get();
-                                }
-                                // checked exceptions are wrapped in RuntimeExceptions
-                            } catch (RuntimeException e) {
-                                if (e.getCause() instanceof com.oracle.truffle.api.vm.IncompleteSourceException) {
-                                    throw e.getCause().getCause();
-                                }
-                                throw e;
-                            }
-                        } catch (IncompleteSourceException e) {
-                            // read another line of input
-                            consoleHandler.setPrompt(doEcho ? continuePrompt : null);
-                            String additionalInput = consoleHandler.readLine();
-                            if (additionalInput == null) {
-                                throw new EOFException();
-                            }
-                            sb.append('\n');
-                            sb.append(additionalInput);
-                            source = RSource.fromTextInternal(sb.toString(), RSource.Internal.SHELL_INPUT);
-                            // The only continuation in the while loop
-                            continue;
-                        } catch (ParseException e) {
-                            e.report(consoleHandler);
-                            lastStatus = 1;
-                        } catch (RError e) {
-                            // drop through to continue REPL and remember last eval was an error
-                            lastStatus = 1;
-                        } catch (JumpToTopLevelException e) {
-                            // drop through to continue REPL
-                        } catch (DebugExitException e) {
-                            throw (RuntimeException) e.getCause();
-                        } catch (ExitException e) {
-                            // usually from quit
-                            int status = e.getStatus();
-                            if (info.getParent() == null) {
-                                vm.dispose();
-                                Utils.systemExit(status);
-                            } else {
-                                return status;
-                            }
-                        } catch (Throwable e) {
-                            RInternalError.reportErrorAndConsoleLog(e, consoleHandler, 0);
-                            // We continue the repl even though the system may be broken
-                            lastStatus = 1;
-                        }
-                        continue REPL;
-                    }
-                } catch (UserInterruptException e) {
-                    // interrupted by ctrl-c
-                }
-            }
-        } catch (JumpToTopLevelException | EOFException ex) {
-            // JumpToTopLevelException can happen if user profile invokes browser (unlikely but
-            // possible)
-            try {
-                vm.eval(QUIT_EOF).get();
-            } catch (JumpToTopLevelException e) {
-                Utils.systemExit(0);
-            } catch (ExitException e) {
-                // normal quit, but with exit code based on lastStatus
-                if (info.getParent() == null) {
-                    Utils.systemExit(lastStatus);
-                } else {
-                    return lastStatus;
-                }
-            } catch (Throwable e) {
-                throw RInternalError.shouldNotReachHere(e);
-            }
-        } finally {
-            vm.dispose();
-        }
-        return 0;
-    }
-
-    private static boolean doEcho(PolyglotEngine vm) {
-        PolyglotEngine.Value echoValue = vm.eval(GET_ECHO);
-        Object echo = echoValue.get();
-        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) {
-            return RRuntime.fromLogical((Byte) echo);
-        } else {
-            throw RInternalError.shouldNotReachHere();
-        }
-    }
-
-    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/REmbedded.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
index d396a37419bbc799889fdca017ec5db3f5e8af88..a05716cad3a656ba005a8874cedd2838d2173c8b 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
@@ -22,15 +22,19 @@
  */
 package com.oracle.truffle.r.engine.shell;
 
-import com.oracle.truffle.api.source.Source;
+import org.graalvm.polyglot.Context;
+import org.graalvm.polyglot.Engine;
+import org.graalvm.polyglot.Source;
+
 import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.r.runtime.RCmdOptions;
+import com.oracle.truffle.r.launcher.ConsoleHandler;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RCommand;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RSource.Internal;
-import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.ChildContextInfo;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
@@ -50,32 +54,36 @@ import com.oracle.truffle.r.runtime.context.RContext;
  * </pre>
  *
  * {@code Rf_initialize_R} invokes {@link #initializeR(String[])}. This creates an
- * {@link RStartParams} object in {@code embedded} mode that is recorded in the {@link ContextInfo}
- * object which is itself stored as a global symbol in the associated {@link PolyglotEngine}
- * instance. The FastR {@link PolyglotEngine} is then partially initialized. The call to
- * {@code R_SetParams} will adjust the values stored in the {@link RStartParams} object and then
- * {@code Rf_mainloop}, which calls {@link #setupRmainloop()} and then {@link #runRmainloop()},
- * which will complete the FastR initialization and enter the read-eval-print loop.
+ * {@link RStartParams} object in {@code embedded} mode that is recorded in the
+ * {@link ChildContextInfo} object which is itself stored as a global symbol in the associated
+ * {@link PolyglotEngine} instance. The FastR {@link PolyglotEngine} is then partially initialized.
+ * The call to {@code R_SetParams} will adjust the values stored in the {@link RStartParams} object
+ * and then {@code Rf_mainloop}, which calls {@link #setupRmainloop()} and then
+ * {@link #runRmainloop()}, which will complete the FastR initialization and enter the
+ * read-eval-print loop.
  */
 public class REmbedded {
 
-    private static ContextInfo info;
-    private static PolyglotEngine vm;
+    private static ConsoleHandler consoleHandler;
+    private static Context context;
 
     /**
-     * Creates the {@link PolyglotEngine} and initializes it. Called from native code when FastR is
+     * Creates the {@link Engine} and initializes it. Called from native code when FastR is
      * embedded. Corresponds to FFI method {@code Rf_initialize_R}. N.B. This does not completely
      * initialize FastR as we cannot do that until the embedding system has had a chance to adjust
      * the {@link RStartParams}, which happens after this call returns.
      */
     private static void initializeR(String[] args) {
-        assert vm == null;
-        assert info == null;
+        assert context == null;
         RContext.setEmbedded();
-        RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, true);
-        info = RCommand.createContextInfoFromCommandLine(options, true, true, System.in, System.out, null);
-        vm = info.createVM();
-        vm.eval(INIT);
+        RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false);
+
+        consoleHandler = RCommand.createConsoleHandler(options, true, System.in, System.out);
+        try (Context cntx = Context.newBuilder().arguments("R", options.getArguments()).in(consoleHandler.createInputStream()).out(System.out).err(System.err).build()) {
+            context = cntx;
+            consoleHandler.setContext(context);
+            context.eval(INIT);
+        }
     }
 
     /**
@@ -83,7 +91,7 @@ public class REmbedded {
      * is evaluated the R builtins have not been installed, see {@link #initializeR}. The
      * suppression of printing is handled a a special case based on {@link Internal#INIT_EMBEDDED}.
      */
-    private static final Source INIT = RSource.fromTextInternal("1", RSource.Internal.INIT_EMBEDDED);
+    private static final Source INIT = Source.newBuilder("R", "1", "<embedded>").buildLiteral();
 
     /**
      * GnuR distinguishes {@code setup_Rmainloop} and {@code run_Rmainloop}. Currently we don't have
@@ -99,10 +107,12 @@ public class REmbedded {
      */
     private static void runRmainloop() {
         RContext.getInstance().completeEmbeddedInitialization();
-        if (!RContext.getInstance().getStartParams().getQuiet()) {
-            RContext.getInstance().getConsoleHandler().println(RRuntime.WELCOME_MESSAGE);
+        if (!RContext.getInstance().getStartParams().isQuiet()) {
+            System.out.println(RRuntime.WELCOME_MESSAGE);
         }
-        RCommand.readEvalPrint(vm, info);
+        int status = RCommand.readEvalPrint(context, consoleHandler);
+        context.close();
+        Utils.systemExit(status);
     }
 
     /**
@@ -110,10 +120,6 @@ public class REmbedded {
      */
     public static void main(String[] args) {
         initializeR(args);
-        RStartParams startParams = info.getStartParams();
-        startParams.setEmbedded();
-        startParams.setLoadInitFile(false);
-        startParams.setNoRenviron(true);
         setupRmainloop();
         runRmainloop();
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java
index 4a65dc84dbbce67cdc35a1cfb883e4dcd9a32547..10ebdf1654928f2c4d481e0e886375599d6c55c0 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RMain.java
@@ -22,6 +22,9 @@
  */
 package com.oracle.truffle.r.engine.shell;
 
+import com.oracle.truffle.r.launcher.RCommand;
+import com.oracle.truffle.r.launcher.RscriptCommand;
+
 /**
  * Convenience class that allows the R/Rscript entry to be chosen by an initial argument.
  */
@@ -66,5 +69,4 @@ public class RMain {
         System.arraycopy(args, 1, nargs, 0, nargs.length);
         return nargs;
     }
-
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/DownCallNode.java
similarity index 56%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/DownCallNode.java
index 9baa8a501139a8b5267323d2151848e71733c1fa..95d2bbafb9cd14fd5b7920fcc1623b367421d48c 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Misc.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/DownCallNode.java
@@ -20,40 +20,40 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
+package com.oracle.truffle.r.ffi.impl.common;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
 
-public class TruffleNFI_Misc implements MiscRFFI {
+public abstract class DownCallNode<T extends NativeFunction> extends Node {
 
-    private static class TruffleNFI_ExactSumNode extends ExactSumNode {
-        @Child Node messageNode = Message.createExecute(4).createNode();
-        private TruffleObject function;
+    @Child private Node message;
 
-        @Override
-        public double execute(double[] values, boolean hasNa, boolean naRm) {
-            if (function == null) {
-                function = TruffleNFI_Utils.lookupAndBind("exactSumFunc", false, "([double], sint32, sint32, sint32): double");
-            }
-            try {
-                return (double) ForeignAccess.sendExecute(messageNode, function, JavaInterop.asTruffleObject(values), values.length, hasNa ? 1 : 0, naRm ? 1 : 0);
-            } catch (InteropException e) {
-                throw RInternalError.shouldNotReachHere(e);
+    protected abstract TruffleObject getTarget();
+
+    protected abstract T getFunction();
+
+    protected final Object call(Object... args) {
+        try {
+            if (message == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                message = insert(Message.createExecute(getFunction().getArgumentCount()).createNode());
             }
+            wrapArguments(args);
+            return ForeignAccess.sendExecute(message, getTarget(), args);
+        } catch (InteropException e) {
+            throw RInternalError.shouldNotReachHere(e);
+        } finally {
+            finishArguments(args);
         }
-
     }
 
-    @Override
-    public ExactSumNode createExactSumNode() {
-        return new TruffleNFI_ExactSumNode();
-    }
+    protected abstract void wrapArguments(Object[] args);
 
+    protected abstract void finishArguments(Object[] args);
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/Generic_PkgInit.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/Generic_PkgInit.java
new file mode 100644
index 0000000000000000000000000000000000000000..b1147fa64c28605f1a444964b7ddab5e766d7047
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/Generic_PkgInit.java
@@ -0,0 +1,67 @@
+/*
+ * 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.ffi.impl.common;
+
+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;
+
+public abstract class Generic_PkgInit implements PkgInitUpCalls {
+    @Override
+    public int registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines) {
+        DotSymbol[] array = new DotSymbol[num];
+        for (int i = 0; i < num; i++) {
+            Object sym = setSymbol(dllInfo, nstOrd, routines, i);
+            array[i] = (DotSymbol) sym;
+        }
+        dllInfo.setNativeSymbols(nstOrd, array);
+        return 0;
+    }
+
+    @Override
+    public int registerCCallable(String pkgName, String functionName, Object address) {
+        DLLInfo lib = DLL.safeFindLibrary(pkgName);
+        lib.registerCEntry(new CEntry(functionName, new SymbolHandle(address)));
+        return 0;
+    }
+
+    @Override
+    public int useDynamicSymbols(DLLInfo dllInfo, int value) {
+        return DLL.useDynamicSymbols(dllInfo, value);
+    }
+
+    @Override
+    public int forceSymbols(DLLInfo dllInfo, int value) {
+        return DLL.forceSymbols(dllInfo, value);
+    }
+
+    @Override
+    public DotSymbol setDotSymbolValues(DLLInfo dllInfo, String name, Object fun, int numArgs) {
+        DotSymbol result = new DotSymbol(name, new SymbolHandle(fun), numArgs);
+        return result;
+    }
+
+    protected abstract Object setSymbol(DLLInfo dllInfo, int nstOrd, long routines, int index);
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/Generic_Tools.java
similarity index 94%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/Generic_Tools.java
index 06d6fa23d773cae35a188f753570fd4ad67b0751..f8ca6ded284e5886eed5f9e9de131f5a5369b1d2 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/generic/Generic_Tools.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/Generic_Tools.java
@@ -20,9 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.generic;
+package com.oracle.truffle.r.ffi.impl.common;
 
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
@@ -37,11 +38,11 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 
 public class Generic_Tools implements ToolsRFFI {
-    public static class Generic_ToolsRFFINode extends ParseRdNode {
+    public static class Generic_ToolsRFFINode extends Node implements ParseRdNode {
         private static final String C_PARSE_RD = "C_parseRd";
         protected static final String TOOLS = "tools";
 
-        @Child private CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
+        @Child private CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getCallRFFI().createInvokeCallNode();
         @Child private DLL.RFindSymbolNode findSymbolNode = DLL.RFindSymbolNode.create();
 
         @CompilationFinal private NativeCallInfo nativeCallInfo;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
similarity index 79%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
index 5e88b23d2c8ba06309f6249d69c0fd12e26bd681..ed489a3e28ac1dd64e86b4f372b20fe4b19a3c66 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/JavaUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java
@@ -20,16 +20,17 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.common;
 
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guarantee;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guaranteeInstanceOf;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.unimplemented;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.guarantee;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.guaranteeInstanceOf;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.unimplemented;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Function;
@@ -41,8 +42,11 @@ import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.ffi.impl.common.ParseResult.ParseStatus;
+import com.oracle.truffle.r.ffi.impl.nodes.FFIUpCallRootNode;
+import com.oracle.truffle.r.ffi.impl.upcalls.RFFIUpCallTable;
+import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.ffi.ParseResult.ParseStatus;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -50,12 +54,12 @@ import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RCleanUp;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RSrcref;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
@@ -64,6 +68,7 @@ import com.oracle.truffle.r.runtime.conn.NativeConnections.NativeRConnection;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -80,6 +85,7 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RSequence;
@@ -102,8 +108,9 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
+import com.oracle.truffle.r.runtime.gnur.SA_TYPE;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+import com.oracle.truffle.r.runtime.nmath.distr.Unif;
 import com.oracle.truffle.r.runtime.nodes.DuplicationHelper;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -111,7 +118,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG;
 
 /**
  * This class provides a simple Java-based implementation of {@link UpCallsRFFI}, where all the
- * argument values are standarde Java types, i.e. no special types used by Truffle NFI or Truffle
+ * argument values are standard Java types, i.e. no special types used by Truffle NFI or Truffle
  * LLVM.
  *
  * TODO Many of the implementations here are incomplete and/or duplicate code that exists in the
@@ -156,27 +163,27 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public int Rf_asInteger(Object x) {
-        return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asInteger).call(x);
+        return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_asInteger).call(x);
     }
 
     @Override
     public double Rf_asReal(Object x) {
-        return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asReal).call(x);
+        return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_asReal).call(x);
     }
 
     @Override
     public int Rf_asLogical(Object x) {
-        return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asLogical).call(x);
+        return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_asLogical).call(x);
     }
 
     @Override
     public Object Rf_asChar(Object x) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_asChar).call(x);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_asChar).call(x);
     }
 
     @Override
     public Object Rf_coerceVector(Object x, int mode) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.Rf_coerceVector).call(x, mode);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_coerceVector).call(x, mode);
     }
 
     @Override
@@ -191,7 +198,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_defineVar(Object symbolArg, Object value, Object envArg) {
+    public int Rf_defineVar(Object symbolArg, Object value, Object envArg) {
         REnvironment env = (REnvironment) envArg;
         RSymbol name = (RSymbol) symbolArg;
         try {
@@ -199,6 +206,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         } catch (PutException ex) {
             throw RError.error(RError.SHOW_CALLER2, ex);
         }
+        return 0;
     }
 
     @Override
@@ -210,7 +218,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public Object R_do_new_object(Object classDef) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_new_object).call(classDef);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.R_do_new_object).call(classDef);
     }
 
     @Override
@@ -253,6 +261,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return RUnboundValue.instance;
     }
 
+    @Override
+    public Object ATTRIB(Object obj) {
+        if (obj instanceof RAttributable) {
+            return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.ATTRIB).call(obj);
+        }
+        return RNull.instance;
+    }
+
     @Override
     public Object Rf_getAttrib(Object obj, Object name) {
         Object result = RNull.instance;
@@ -272,7 +288,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     @TruffleBoundary
-    public void Rf_setAttrib(Object obj, Object name, Object val) {
+    public int Rf_setAttrib(Object obj, Object name, Object val) {
         if (obj instanceof RAttributable) {
             RAttributable attrObj = (RAttributable) obj;
             String nameAsString;
@@ -290,7 +306,10 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
             } else {
                 attrObj.setAttr(nameAsString, val);
             }
+        } else {
+            throw RInternalError.shouldNotReachHere();
         }
+        return 0;
     }
 
     @TruffleBoundary
@@ -357,47 +376,56 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_error(Object msg) {
+    public int Rf_error(Object msg) {
         throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, msg);
     }
 
     @Override
-    public void Rf_warning(Object msg) {
+    public int Rf_warning(Object msg) {
         RError.warning(RError.SHOW_CALLER2, RError.Message.GENERIC, msg);
+        return 0;
     }
 
     @Override
-    public void Rf_warningcall(Object call, Object msg) {
+    public int Rf_warningcall(Object call, Object msg) {
         RErrorHandling.warningcallRFFI(call, (String) msg);
+        return 0;
     }
 
     @Override
-    public Object Rf_allocVector(int mode, int n) {
+    public int Rf_errorcall(Object call, Object msg) {
+        RErrorHandling.errorcallRFFI(call, (String) msg);
+        return 0;
+    }
+
+    @Override
+    public Object Rf_allocVector(int mode, long n) {
         SEXPTYPE type = SEXPTYPE.mapInt(mode);
-        if (n < 0) {
-            throw RError.error(RError.SHOW_CALLER2, RError.Message.NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED);
+        if (n > Integer.MAX_VALUE) {
+            throw RError.error(RError.SHOW_CALLER2, RError.Message.LONG_VECTORS_NOT_SUPPORTED);
             // TODO check long vector
         }
+        int ni = (int) n;
         switch (type) {
             case INTSXP:
-                return RDataFactory.createIntVector(new int[n], RDataFactory.COMPLETE_VECTOR);
+                return RDataFactory.createIntVector(new int[ni], RDataFactory.COMPLETE_VECTOR);
             case REALSXP:
-                return RDataFactory.createDoubleVector(new double[n], RDataFactory.COMPLETE_VECTOR);
+                return RDataFactory.createDoubleVector(new double[ni], RDataFactory.COMPLETE_VECTOR);
             case LGLSXP:
-                return RDataFactory.createLogicalVector(new byte[n], RDataFactory.COMPLETE_VECTOR);
+                return RDataFactory.createLogicalVector(new byte[ni], RDataFactory.COMPLETE_VECTOR);
             case STRSXP:
                 // fill list with empty strings
-                String[] data = new String[n];
+                String[] data = new String[ni];
                 Arrays.fill(data, "");
                 return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
             case CPLXSXP:
-                return RDataFactory.createComplexVector(new double[2 * n], RDataFactory.COMPLETE_VECTOR);
+                return RDataFactory.createComplexVector(new double[2 * ni], RDataFactory.COMPLETE_VECTOR);
             case RAWSXP:
-                return RDataFactory.createRawVector(new byte[n]);
+                return RDataFactory.createRawVector(new byte[ni]);
             case VECSXP:
-                return RDataFactory.createList(n);
+                return RDataFactory.createList(ni);
             case LANGSXP:
-                return RDataFactory.createLangPairList(n);
+                return RDataFactory.createLangPairList(ni);
             default:
                 throw unimplemented("unexpected SEXPTYPE " + type);
         }
@@ -462,20 +490,26 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public int LENGTH(Object x) {
-        return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.LENGTH).call(x);
+        return (int) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.LENGTH).call(x);
     }
 
     @Override
-    public void SET_STRING_ELT(Object x, int i, Object v) {
+    public int SET_STRING_ELT(Object x, long i, Object v) {
         RStringVector vector = guaranteeInstanceOf(x, RStringVector.class);
         CharSXPWrapper element = guaranteeInstanceOf(v, CharSXPWrapper.class);
-        vector.setElement(i, element.getContents());
+        String value = element.getContents();
+        if (RRuntime.isNA(value)) {
+            vector.setComplete(false);
+        }
+        vector.setElement((int) i, value);
+        return 0;
     }
 
     @Override
-    public void SET_VECTOR_ELT(Object x, int i, Object v) {
+    public int SET_VECTOR_ELT(Object x, long i, Object v) {
         RList list = guaranteeInstanceOf(x, RList.class);
-        list.setElement(i, v);
+        list.setElement((int) i, v);
+        return 0;
     }
 
     @Override
@@ -534,28 +568,59 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object STRING_ELT(Object x, int i) {
+    public Object STRING_ELT(Object x, long i) {
         RAbstractStringVector vector = guaranteeInstanceOf(RRuntime.asAbstractVector(x), RAbstractStringVector.class);
-        return CharSXPWrapper.create(vector.getDataAt(i));
+        return CharSXPWrapper.create(vector.getDataAt((int) i));
     }
 
     @Override
-    public Object VECTOR_ELT(Object x, int i) {
+    public Object VECTOR_ELT(Object x, long i) {
         Object vec = x;
         if (vec instanceof RExpression) {
-            return ((RExpression) vec).getDataAt(i);
+            return ((RExpression) vec).getDataAt((int) i);
         }
         RAbstractListVector list = guaranteeInstanceOf(RRuntime.asAbstractVector(vec), RAbstractListVector.class);
-        return list.getDataAt(i);
+        return list.getDataAt((int) i);
     }
 
     @Override
     public int NAMED(Object x) {
         if (x instanceof RShareable) {
-            return ((RShareable) x).isShared() ? 1 : 0;
+            return getNamed((RShareable) x);
         } else {
-            throw unimplemented();
+            // Note: it may be that we need to remember this for all types, GNUR does
+            return 2;
+        }
+    }
+
+    @Override
+    public Object SET_NAMED_FASTR(Object x, int v) {
+        // Note: In GNUR this is a macro that sets the sxpinfo.named regardless of whether it makes
+        // sense to name the actual value, for compatibilty we simply ignore values that are not
+        // RShareable, e.g. RSymbol. However we ignore and report attemps to decrease the ref-count,
+        // which as it seems GNUR would just let proceede
+        if (x instanceof RShareable) {
+            RShareable r = (RShareable) x;
+            int actual = getNamed(r);
+            if (v < actual) {
+                RError.warning(RError.NO_CALLER, Message.GENERIC, "Native code attempted to decrease the reference count. This operation is ignored.");
+                return RNull.instance;
+            }
+            if (v == 2) {
+                // we play it safe: if the caller wants this instance to be shared, they may expect
+                // it to never become non-shared again, which could happen in FastR
+                r.makeSharedPermanent();
+                return RNull.instance;
+            }
+            if (v == 1 && r.isTemporary()) {
+                r.incRefCount();
+            }
         }
+        return RNull.instance;
+    }
+
+    private static int getNamed(RShareable r) {
+        return r.isTemporary() ? 0 : r.isShared() ? 2 : 1;
     }
 
     @Override
@@ -602,7 +667,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int Rf_any_duplicated(Object x, int fromLast) {
+    public long Rf_any_duplicated(Object x, int fromLast) {
         RAbstractVector vec = (RAbstractVector) x;
         if (vec.getLength() == 0) {
             return 0;
@@ -621,6 +686,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     public Object TAG(Object e) {
         if (e instanceof RPairList) {
             return ((RPairList) e).getTag();
+        } else if (e instanceof RArgsValuesAndNames) {
+            ArgumentsSignature signature = ((RArgsValuesAndNames) e).getSignature();
+            if (signature.getLength() > 0 && signature.getName(0) != null) {
+                return signature.getName(0);
+            }
+            return RNull.instance;
         } else {
             guaranteeInstanceOf(e, RExternalPtr.class);
             // at the moment, this can only be used to null out the pointer
@@ -630,27 +701,28 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public Object CAR(Object e) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CAR).call(e);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.CAR).call(e);
     }
 
     @Override
     public Object CDR(Object e) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CDR).call(e);
+        Object result = FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.CDR).call(e);
+        return result;
     }
 
     @Override
     public Object CADR(Object e) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CADR).call(e);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.CADR).call(e);
     }
 
     @Override
     public Object CADDR(Object e) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CADDR).call(e);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.CADDR).call(e);
     }
 
     @Override
     public Object CDDR(Object e) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.CDDR).call(e);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.CDDR).call(e);
     }
 
     @Override
@@ -667,8 +739,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public Object SETCAR(Object x, Object y) {
-        guaranteeInstanceOf(x, RPairList.class);
-        ((RPairList) x).setCar(y);
+        RPairList pl;
+        if (x instanceof RLanguage) {
+            pl = ((RLanguage) x).getPairList();
+        } else {
+            guaranteeInstanceOf(x, RPairList.class);
+            pl = (RPairList) x;
+        }
+        pl.setCar(y);
         return y;
     }
 
@@ -699,11 +777,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_SYMVALUE(Object x, Object v) {
+    public int SET_SYMVALUE(Object x, Object v) {
         if (!(x instanceof RSymbol)) {
             throw RInternalError.shouldNotReachHere();
         }
         REnvironment.baseEnv().safePut(((RSymbol) x).getName(), v);
+        return 0;
     }
 
     @Override
@@ -719,6 +798,24 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return result;
     }
 
+    private static final Object processResult(Object value) {
+        if (value instanceof Integer) {
+            int v = (int) value;
+            return RDataFactory.createIntVector(new int[]{v}, RRuntime.isNA(v));
+        } else if (value instanceof Double) {
+            double v = (double) value;
+            return RDataFactory.createDoubleVector(new double[]{v}, RRuntime.isNA(v));
+        } else if (value instanceof Byte) {
+            byte v = (byte) value;
+            return RDataFactory.createLogicalVector(new byte[]{v}, RRuntime.isNA(v));
+        } else if (value instanceof String) {
+            String v = (String) value;
+            return RDataFactory.createStringVector(new String[]{v}, RRuntime.isNA(v));
+        } else {
+            return value;
+        }
+    }
+
     @Override
     public Object Rf_eval(Object expr, Object env) {
         guarantee(env instanceof REnvironment);
@@ -741,11 +838,14 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
                                 ArgumentsSignature.fromNamesAttribute(argsList.getNames()),
                                 argsList.getDataNonShared());
             }
+        } else if (expr instanceof RSymbol) {
+            RSyntaxNode lookup = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) expr).getName(), false);
+            result = RContext.getEngine().eval(RDataFactory.createLanguage(lookup.asRNode()), (REnvironment) env, RCaller.topLevel);
         } else {
             // just return value
             result = expr;
         }
-        return result;
+        return processResult(result);
     }
 
     @Override
@@ -772,7 +872,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_gsetVar(Object symbol, Object value, Object rho) {
+    public int Rf_gsetVar(Object symbol, Object value, Object rho) {
         guarantee(symbol instanceof RSymbol);
         REnvironment baseEnv = RContext.getInstance().stateREnvironment.getBaseEnv();
         guarantee(rho == baseEnv);
@@ -781,33 +881,36 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         } catch (PutException e) {
             e.printStackTrace();
         }
+        return 0;
     }
 
     @Override
-    public void DUPLICATE_ATTRIB(Object to, Object from) {
+    public int DUPLICATE_ATTRIB(Object to, Object from) {
         if (from instanceof RAttributable) {
             guaranteeInstanceOf(to, RAttributable.class);
             DynamicObject attributes = ((RAttributable) from).getAttributes();
             ((RAttributable) to).initAttributes(attributes == null ? null : RAttributesLayout.copy(attributes));
         }
         // TODO: copy OBJECT? and S4 attributes
+        return 0;
     }
 
     @Override
+    @TruffleBoundary
     public int R_compute_identical(Object x, Object y, int flags) {
-        RFunction indenticalBuiltin = RContext.lookupBuiltin("identical");
+        RFunction indenticalBuiltin = RContext.getInstance().lookupBuiltin("identical");
         Object res = RContext.getEngine().evalFunction(indenticalBuiltin, null, null, true, null, x, y, RRuntime.asLogical((!((flags & 1) == 0))),
                         RRuntime.asLogical((!((flags & 2) == 0))), RRuntime.asLogical((!((flags & 4) == 0))), RRuntime.asLogical((!((flags & 8) == 0))), RRuntime.asLogical((!((flags & 16) == 0))));
         return (int) res;
     }
 
     @Override
-    public void Rf_copyListMatrix(Object t, Object s, int byrow) {
+    public int Rf_copyListMatrix(Object t, Object s, int byrow) {
         throw unimplemented();
     }
 
     @Override
-    public void Rf_copyMatrix(Object t, Object s, int byRow) {
+    public int Rf_copyMatrix(Object t, Object s, int byRow) {
         int tRows = RRuntime.nrows(t);
         int tCols = RRuntime.ncols(t);
         final Object sav = RRuntime.asAbstractVector(s);
@@ -923,10 +1026,10 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
                     }
                 }
             }
-
         } else { // source is non-RAbstractContainer
             throw unimplemented();
         }
+        return 0;
     }
 
     /**
@@ -939,7 +1042,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object R_tryEval(Object expr, Object env, boolean silent) {
+    public Object R_tryEval(Object expr, Object env, int silent) {
         Object handlerStack = RErrorHandling.getHandlerStack();
         Object restartStack = RErrorHandling.getRestartStack();
         try {
@@ -977,7 +1080,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_RDEBUG(Object x, int v) {
+    public int SET_RDEBUG(Object x, int v) {
         REnvironment env = guaranteeInstanceOf(x, REnvironment.class);
         if (env instanceof REnvironment.Function) {
             REnvironment.Function funcEnv = (REnvironment.Function) env;
@@ -988,6 +1091,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
                 RContext.getRRuntimeASTAccess().disableDebug(func);
             }
         }
+        return 0;
     }
 
     @Override
@@ -998,7 +1102,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_RSTEP(Object x, int v) {
+    public int SET_RSTEP(Object x, int v) {
         @SuppressWarnings("unused")
         REnvironment env = guaranteeInstanceOf(x, REnvironment.class);
         throw RInternalError.unimplemented("SET_RSTEP");
@@ -1052,8 +1156,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void R_CleanUp(int sa, int status, int runlast) {
+    public int R_CleanUp(int sa, int status, int runlast) {
         RCleanUp.stdCleanUp(SA_TYPE.values()[sa], status, runlast != 0);
+        return 0;
     }
 
     @Override
@@ -1101,28 +1206,33 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_S4_OBJECT(Object x) {
+    public int SET_S4_OBJECT(Object x) {
         guaranteeInstanceOf(x, RTypedValue.class).setS4();
+        return 0;
     }
 
     @Override
-    public void UNSET_S4_OBJECT(Object x) {
+    public int UNSET_S4_OBJECT(Object x) {
         guaranteeInstanceOf(x, RTypedValue.class).unsetS4();
+        return 0;
     }
 
     @Override
-    public void Rprintf(Object message) {
-        RContext.getInstance().getConsoleHandler().print((String) message);
+    public int Rprintf(Object message) {
+        RContext.getInstance().getConsole().print((String) message);
+        return 0;
     }
 
     @Override
-    public void GetRNGstate() {
+    public int GetRNGstate() {
         RRNG.getRNGState();
+        return 0;
     }
 
     @Override
-    public void PutRNGstate() {
+    public int PutRNGstate() {
         RRNG.putRNGState();
+        return 0;
     }
 
     @Override
@@ -1287,28 +1397,31 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void R_SetExternalPtrAddr(Object x, long addr) {
+    public int R_SetExternalPtrAddr(Object x, long addr) {
         RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class);
         p.setAddr(new SymbolHandle(addr));
+        return 0;
     }
 
     @Override
-    public void R_SetExternalPtrTag(Object x, Object tag) {
+    public int R_SetExternalPtrTag(Object x, Object tag) {
         RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class);
         p.setTag(tag);
+        return 0;
     }
 
     @Override
-    public void R_SetExternalPtrProtected(Object x, Object prot) {
+    public int R_SetExternalPtrProtected(Object x, Object prot) {
         RExternalPtr p = guaranteeInstanceOf(x, RExternalPtr.class);
         p.setProt(prot);
+        return 0;
     }
 
     @Override
-    public REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize) {
+    public REnvironment R_NewHashedEnv(Object parent, Object initialSize) {
         // We know this is an RIntVector from use site in gramRd.c
         REnvironment env = RDataFactory.createNewEnv(REnvironment.UNNAMED, true, ((RIntVector) initialSize).getDataAt(0));
-        RArguments.initializeEnclosingFrame(env.getFrame(), parent.getFrame());
+        RArguments.initializeEnclosingFrame(env.getFrame(), guaranteeInstanceOf(parent, REnvironment.class).getFrame());
         return env;
     }
 
@@ -1321,6 +1434,9 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     @Override
     public Object PRENV(Object x) {
         RPromise promise = RFFIUtils.guaranteeInstanceOf(x, RPromise.class);
+        if (promise instanceof EagerPromise) {
+            ((EagerPromise) promise).materialize();
+        }
         final MaterializedFrame frame = promise.getFrame();
         return frame != null ? REnvironment.frameToEnvironment(frame) : RNull.instance;
     }
@@ -1354,8 +1470,8 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int R_ReadConnection(int fd, byte[] buf) {
-
+    public int R_ReadConnection(int fd, Object bufObj) {
+        byte[] buf = (byte[]) bufObj;
         try (BaseRConnection fromIndex = RConnection.fromIndex(fd)) {
             Arrays.fill(buf, (byte) 0);
             return fromIndex.readBin(ByteBuffer.wrap(buf));
@@ -1365,7 +1481,8 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int R_WriteConnection(int fd, byte[] buf) {
+    public int R_WriteConnection(int fd, Object bufObj) {
+        byte[] buf = (byte[]) bufObj;
         try (BaseRConnection fromIndex = RConnection.fromIndex(fd)) {
             Arrays.fill(buf, (byte) 0);
             final ByteBuffer wrapped = ByteBuffer.wrap(buf);
@@ -1407,12 +1524,12 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
 
     @Override
     public Object R_do_slot(Object o, Object name) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_slot).call(o, name);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.R_do_slot).call(o, name);
     }
 
     @Override
     public Object R_do_slot_assign(Object o, Object name, Object value) {
-        return FFIUpCallRootNode.getCallTarget(RFFIUpCallMethod.R_do_slot_assign).call(o, name, value);
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.R_do_slot_assign).call(o, name, value);
     }
 
     @Override
@@ -1420,4 +1537,75 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI {
         return REnvironment.getRegisteredNamespace("methods");
     }
 
+    private HashMap<String, Integer> name2typeTable;
+
+    @Override
+    @TruffleBoundary
+    public int Rf_str2type(Object name) {
+        if (name == null) {
+            return -1;
+        }
+        initName2typeTable();
+        Integer result = name2typeTable.get(name);
+        return result != null ? result : -1;
+    }
+
+    private void initName2typeTable() {
+        if (name2typeTable != null) {
+            return;
+        }
+        name2typeTable = new HashMap<>(26);
+        name2typeTable.put("NULL", SEXPTYPE.NILSXP.code); /* real types */
+        name2typeTable.put("symbol", SEXPTYPE.SYMSXP.code);
+        name2typeTable.put("pairlist", SEXPTYPE.LISTSXP.code);
+        name2typeTable.put("closure", SEXPTYPE.CLOSXP.code);
+        name2typeTable.put("environment", SEXPTYPE.ENVSXP.code);
+        name2typeTable.put("promise", SEXPTYPE.PROMSXP.code);
+        name2typeTable.put("language", SEXPTYPE.LANGSXP.code);
+        name2typeTable.put("special", SEXPTYPE.SPECIALSXP.code);
+        name2typeTable.put("builtin", SEXPTYPE.BUILTINSXP.code);
+        name2typeTable.put("char", SEXPTYPE.CHARSXP.code);
+        name2typeTable.put("logical", SEXPTYPE.LGLSXP.code);
+        name2typeTable.put("integer", SEXPTYPE.INTSXP.code);
+        name2typeTable.put("double", SEXPTYPE.REALSXP.code); /*-  "real", for R <= 0.61.x */
+        name2typeTable.put("complex", SEXPTYPE.CPLXSXP.code);
+        name2typeTable.put("character", SEXPTYPE.STRSXP.code);
+        name2typeTable.put("...", SEXPTYPE.DOTSXP.code);
+        name2typeTable.put("any", SEXPTYPE.ANYSXP.code);
+        name2typeTable.put("expression", SEXPTYPE.EXPRSXP.code);
+        name2typeTable.put("list", SEXPTYPE.VECSXP.code);
+        name2typeTable.put("externalptr", SEXPTYPE.EXTPTRSXP.code);
+        name2typeTable.put("bytecode", SEXPTYPE.BCODESXP.code);
+        name2typeTable.put("weakref", SEXPTYPE.WEAKREFSXP.code);
+        name2typeTable.put("raw", SEXPTYPE.RAWSXP.code);
+        name2typeTable.put("S4", SEXPTYPE.S4SXP.code);
+        name2typeTable.put("numeric", SEXPTYPE.REALSXP.code);
+        name2typeTable.put("name", SEXPTYPE.SYMSXP.code);
+    }
+
+    @Override
+    public double Rf_dunif(double a, double b, double c, int d) {
+        return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_dunif).call(a, b, c, d);
+    }
+
+    @Override
+    public double Rf_qunif(double a, double b, double c, int d, int e) {
+        return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_qunif).call(a, b, c, d, e);
+    }
+
+    @Override
+    public double Rf_punif(double a, double b, double c, int d, int e) {
+        return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_punif).call(a, b, c, d, e);
+    }
+
+    @Override
+    public double Rf_runif(double a, double b) {
+        return (double) FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_runif).call(a, b);
+    }
+
+    @Override
+    public Object Rf_namesgets(Object x, Object y) {
+        return FFIUpCallRootNode.getCallTarget(RFFIUpCallTable.Rf_namesgets).call(x, y);
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/LibPaths.java
similarity index 98%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/LibPaths.java
index 86b8d0a62c33348b68b95270c11e0f69816917dd..bc6dbebba257597494fe01459ef3703f6303711d 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/LibPaths.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/LibPaths.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.ffi.impl.common;
 
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/llvm_dummy.f b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/NativeFunction.java
similarity index 79%
rename from com.oracle.truffle.r.native/fficall/src/truffle_llvm/llvm_dummy.f
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/NativeFunction.java
index 6c4e6cee29e0ca31cc15e3c1429d33061508786a..dca5d7ddc72378f8c859088778df052414d7bf7d 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/llvm_dummy.f
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/NativeFunction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -20,5 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-// A dummy file that is compiled (by fastr-fc) in place of any actual .f file in this directory.
-// This allows the IR for the actual .f file to be merged with the empty .o for llvm_dummy.
+
+package com.oracle.truffle.r.ffi.impl.common;
+
+public interface NativeFunction {
+
+    int getArgumentCount();
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/ParseResult.java
similarity index 93%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/ParseResult.java
index 1a5dc11242769558430a273c3f16dc61f598b8bb..58cf577ae84cdb4e2567e0833b33cb903da95543 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ParseResult.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/ParseResult.java
@@ -20,9 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.common;
 
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
+import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 
 /**
  * Used in implementation of {@link UpCallsRFFI#R_ParseVector(Object, int, Object)}.
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/PkgInitUpCalls.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/PkgInitUpCalls.java
new file mode 100644
index 0000000000000000000000000000000000000000..42a795396a94d14ecc457af27357e6bcc2e7daeb
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/PkgInitUpCalls.java
@@ -0,0 +1,86 @@
+/*
+ * 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.ffi.impl.common;
+
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+import com.oracle.truffle.r.runtime.ffi.DLL.DotSymbol;
+
+public interface PkgInitUpCalls {
+    enum Index {
+        registerRoutines("(object, sint32, sint32, uint64): void"),
+        setDotSymbolValues("(object, string, pointer, sint32): object"),
+        useDynamicSymbols("(object, sint32): sint32"),
+        forceSymbols("(object, sint32): sint32"),
+        registerCCallable("(string, string, uint64): sint32"),
+        getCCallable("(string, string): uint64");
+
+        public final String signature;
+
+        Index(String signature) {
+            this.signature = signature;
+        }
+    }
+
+    /**
+     * This is the start, called from {@code R_RegisterRoutines}.
+     *
+     * @param dllInfo library the symbols are defined in
+     * @param nstOrd the ordinal value corresponding to
+     *            {@link com.oracle.truffle.r.runtime.ffi.DLL.NativeSymbolType}.
+     * @param num the number of functions being registered
+     * @param routines the C address of the function table (not interpreted).
+     */
+    int registerRoutines(DLLInfo dllInfo, int nstOrd, int num, long routines);
+
+    /**
+     * Internal upcall used by {@code Rdynload_setSymbol}. The {@code fun} value must be converted
+     * to a {@link TruffleObject} representing the symbol}.
+     *
+     * @param dllInfo library the symbol is defined in
+     * @param name name of function
+     * @param fun a representation of the the C address of the function (in the table)
+     * @param numArgs the number of arguments the function takes.
+     */
+    DotSymbol setDotSymbolValues(DLLInfo dllInfo, String name, Object fun, int numArgs);
+
+    /**
+     * Directly implements {@code R_useDynamicSymbols}.
+     */
+    int useDynamicSymbols(DLLInfo dllInfo, int value);
+
+    /**
+     * Directly implements {@code R_forceSymbols}.
+     */
+    int forceSymbols(DLLInfo dllInfo, int value);
+
+    /**
+     * Directly implements {@code R_RegisterCCallable}.
+     */
+    int registerCCallable(String pkgName, String functionName, Object fun);
+
+    /**
+     * Directly implements {@code R_GetCCallable}.
+     */
+    Object getCCallable(String pkgName, String functionName);
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java
similarity index 89%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java
index 46cb7f66b63e67c513ce3c85ba3af744404ff616..760388b62c206b1aad234f6834d43cd961e9d013 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUtils.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/RFFIUtils.java
@@ -20,21 +20,22 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.common;
 
 import java.io.FileDescriptor;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.nio.file.Path;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.r.ffi.impl.nodes.FFIUpCallRootNode;
+import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 /**
  * Mostly support for tracing R FFI up/down calls. Currently tracing of the arguments to calls is
@@ -191,10 +192,12 @@ public class RFFIUtils {
 
     // Error handling
     static RuntimeException unimplemented() {
+        CompilerDirectives.transferToInterpreter();
         return unimplemented("");
     }
 
     static RuntimeException unimplemented(String message) {
+        CompilerDirectives.transferToInterpreter();
         throw RInternalError.unimplemented(message);
     }
 
@@ -204,35 +207,19 @@ public class RFFIUtils {
 
     static void guarantee(boolean condition, String message) {
         if (!condition) {
+            CompilerDirectives.transferToInterpreter();
             unimplemented(message);
         }
     }
 
     public static <T> T guaranteeInstanceOf(Object x, Class<T> clazz) {
         if (x == null) {
-            guarantee(false, "unexpected type: null instead of " + clazz.getSimpleName());
+            CompilerDirectives.transferToInterpreter();
+            unimplemented("unexpected type: null instead of " + clazz.getSimpleName());
         } else if (!clazz.isInstance(x)) {
-            guarantee(false, "unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName());
+            CompilerDirectives.transferToInterpreter();
+            unimplemented("unexpected type: " + x + " is " + x.getClass().getSimpleName() + " instead of " + clazz.getSimpleName());
         }
         return clazz.cast(x);
     }
-
-    // Miscellaneous support functions
-
-    public static byte[] wrapChar(char v) {
-        return new byte[]{(byte) v};
-    }
-
-    public static int[] wrapInt(int v) {
-        return new int[]{v};
-    }
-
-    public static double[] wrapDouble(double v) {
-        return new double[]{v};
-    }
-
-    @TruffleBoundary
-    public static IOException ioex(String errMsg) throws IOException {
-        throw new IOException(errMsg);
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
similarity index 82%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
index 2bf8a0d955c98ac8da791351f6bc146bde2e9ad7..8b5fc1e7b73848a4d471312f981c1bc9350174b9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/TracingUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/TracingUpCallsRFFIImpl.java
@@ -20,15 +20,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.common;
 
+import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     // Checkstyle: stop method name check
@@ -106,9 +105,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_defineVar(Object symbolArg, Object value, Object envArg) {
+    public int Rf_defineVar(Object symbolArg, Object value, Object envArg) {
         RFFIUtils.traceUpCall("Rf_defineVar", symbolArg, value, envArg);
-        delegate.Rf_defineVar(symbolArg, value, envArg);
+        return delegate.Rf_defineVar(symbolArg, value, envArg);
     }
 
     @Override
@@ -141,6 +140,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.Rf_findVarInFrame3(envArg, symbolArg, doGet);
     }
 
+    @Override
+    public Object ATTRIB(Object obj) {
+        RFFIUtils.traceUpCall("ATTRIB");
+        return delegate.ATTRIB(obj);
+    }
+
     @Override
     public Object Rf_getAttrib(Object obj, Object name) {
         RFFIUtils.traceUpCall("Rf_getAttrib", obj, name);
@@ -148,9 +153,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_setAttrib(Object obj, Object name, Object val) {
+    public int Rf_setAttrib(Object obj, Object name, Object val) {
         RFFIUtils.traceUpCall("Rf_setAttrib", obj, name, val);
-        delegate.Rf_setAttrib(obj, name, val);
+        return delegate.Rf_setAttrib(obj, name, val);
     }
 
     @Override
@@ -196,25 +201,31 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_error(Object msg) {
+    public int Rf_error(Object msg) {
         RFFIUtils.traceUpCall("Rf_error", msg);
-        delegate.Rf_error(msg);
+        return delegate.Rf_error(msg);
     }
 
     @Override
-    public void Rf_warning(Object msg) {
+    public int Rf_warning(Object msg) {
         RFFIUtils.traceUpCall("Rf_warning", msg);
-        delegate.Rf_warning(msg);
+        return delegate.Rf_warning(msg);
     }
 
     @Override
-    public void Rf_warningcall(Object call, Object msg) {
+    public int Rf_warningcall(Object call, Object msg) {
         RFFIUtils.traceUpCall("Rf_warningcall", call, msg);
-        delegate.Rf_warningcall(call, msg);
+        return delegate.Rf_warningcall(call, msg);
     }
 
     @Override
-    public Object Rf_allocVector(int mode, int n) {
+    public int Rf_errorcall(Object call, Object msg) {
+        RFFIUtils.traceUpCall("Rf_errorcall", call, msg);
+        return delegate.Rf_errorcall(call, msg);
+    }
+
+    @Override
+    public Object Rf_allocVector(int mode, long n) {
         RFFIUtils.traceUpCall("Rf_allocateVector", mode, n);
         return delegate.Rf_allocVector(mode, n);
     }
@@ -250,15 +261,15 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_STRING_ELT(Object x, int i, Object v) {
+    public int SET_STRING_ELT(Object x, long i, Object v) {
         RFFIUtils.traceUpCall("SET_STRING_ELT", x, i, v);
-        delegate.SET_STRING_ELT(x, i, v);
+        return delegate.SET_STRING_ELT(x, i, v);
     }
 
     @Override
-    public void SET_VECTOR_ELT(Object x, int i, Object v) {
+    public int SET_VECTOR_ELT(Object x, long i, Object v) {
         RFFIUtils.traceUpCall("SET_VECTOR_ELT", i, v);
-        delegate.SET_VECTOR_ELT(x, i, v);
+        return delegate.SET_VECTOR_ELT(x, i, v);
     }
 
     @Override
@@ -286,13 +297,13 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public Object STRING_ELT(Object x, int i) {
+    public Object STRING_ELT(Object x, long i) {
         RFFIUtils.traceUpCall("STRING_ELT", x, i);
         return delegate.STRING_ELT(x, i);
     }
 
     @Override
-    public Object VECTOR_ELT(Object x, int i) {
+    public Object VECTOR_ELT(Object x, long i) {
         RFFIUtils.traceUpCall("VECTOR_ELT", x, i);
         return delegate.VECTOR_ELT(x, i);
     }
@@ -303,6 +314,12 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.NAMED(x);
     }
 
+    @Override
+    public Object SET_NAMED_FASTR(Object x, int v) {
+        RFFIUtils.traceUpCall("SET_NAMED_FASTR", x, v);
+        return delegate.SET_NAMED_FASTR(x, v);
+    }
+
     @Override
     public Object SET_TYPEOF_FASTR(Object x, int v) {
         RFFIUtils.traceUpCall("SET_TYPEOF_FASTR", x, v);
@@ -328,7 +345,7 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int Rf_any_duplicated(Object x, int fromLast) {
+    public long Rf_any_duplicated(Object x, int fromLast) {
         RFFIUtils.traceUpCall("Rf_anyDuplicated", x, fromLast);
         return delegate.Rf_any_duplicated(x, fromLast);
     }
@@ -406,9 +423,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_SYMVALUE(Object x, Object v) {
+    public int SET_SYMVALUE(Object x, Object v) {
         RFFIUtils.traceUpCall("SET_SYMVALUE", x, v);
-        delegate.SET_SYMVALUE(x, v);
+        return delegate.SET_SYMVALUE(x, v);
     }
 
     @Override
@@ -442,15 +459,15 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_gsetVar(Object symbol, Object value, Object rho) {
+    public int Rf_gsetVar(Object symbol, Object value, Object rho) {
         RFFIUtils.traceUpCall("Rf_gsetVar", symbol, value, rho);
-        delegate.Rf_gsetVar(symbol, value, rho);
+        return delegate.Rf_gsetVar(symbol, value, rho);
     }
 
     @Override
-    public void DUPLICATE_ATTRIB(Object to, Object from) {
+    public int DUPLICATE_ATTRIB(Object to, Object from) {
         RFFIUtils.traceUpCall("DUPLICATE_ATTRIB", to, from);
-        delegate.DUPLICATE_ATTRIB(to, from);
+        return delegate.DUPLICATE_ATTRIB(to, from);
     }
 
     @Override
@@ -460,19 +477,19 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void Rf_copyListMatrix(Object s, Object t, int byrow) {
+    public int Rf_copyListMatrix(Object s, Object t, int byrow) {
         RFFIUtils.traceUpCall("Rf_copyListMatrix", t, byrow);
-        delegate.Rf_copyListMatrix(s, t, byrow);
+        return delegate.Rf_copyListMatrix(s, t, byrow);
     }
 
     @Override
-    public void Rf_copyMatrix(Object s, Object t, int byrow) {
+    public int Rf_copyMatrix(Object s, Object t, int byrow) {
         RFFIUtils.traceUpCall("Rf_copyMatrix", t, byrow);
-        delegate.Rf_copyMatrix(s, t, byrow);
+        return delegate.Rf_copyMatrix(s, t, byrow);
     }
 
     @Override
-    public Object R_tryEval(Object expr, Object env, boolean silent) {
+    public Object R_tryEval(Object expr, Object env, int silent) {
         RFFIUtils.traceUpCall("R_tryEval", expr, env, silent);
         return delegate.R_tryEval(expr, env, silent);
     }
@@ -490,9 +507,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_RDEBUG(Object x, int v) {
+    public int SET_RDEBUG(Object x, int v) {
         RFFIUtils.traceUpCall("SET_RDEBUG", x, v);
-        delegate.SET_RDEBUG(x, v);
+        return delegate.SET_RDEBUG(x, v);
     }
 
     @Override
@@ -502,9 +519,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_RSTEP(Object x, int v) {
+    public int SET_RSTEP(Object x, int v) {
         RFFIUtils.traceUpCall("SET_RSTEP", x, v);
-        delegate.SET_RSTEP(x, v);
+        return delegate.SET_RSTEP(x, v);
     }
 
     @Override
@@ -538,9 +555,9 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void R_CleanUp(int sa, int status, int runlast) {
+    public int R_CleanUp(int sa, int status, int runlast) {
         RFFIUtils.traceUpCall("R_Cleanup", sa, status, runlast);
-        delegate.R_CleanUp(sa, status, runlast);
+        return delegate.R_CleanUp(sa, status, runlast);
     }
 
     @Override
@@ -586,33 +603,33 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void SET_S4_OBJECT(Object x) {
+    public int SET_S4_OBJECT(Object x) {
         RFFIUtils.traceUpCall("setS4Object");
-        delegate.SET_S4_OBJECT(x);
+        return delegate.SET_S4_OBJECT(x);
     }
 
     @Override
-    public void UNSET_S4_OBJECT(Object x) {
+    public int UNSET_S4_OBJECT(Object x) {
         RFFIUtils.traceUpCall("unsetS4Object");
-        delegate.UNSET_S4_OBJECT(x);
+        return delegate.UNSET_S4_OBJECT(x);
     }
 
     @Override
-    public void Rprintf(Object message) {
+    public int Rprintf(Object message) {
         RFFIUtils.traceUpCall("Rprintf", message);
-        delegate.Rprintf(message);
+        return delegate.Rprintf(message);
     }
 
     @Override
-    public void GetRNGstate() {
+    public int GetRNGstate() {
         RFFIUtils.traceUpCall("GetRNGstate");
-        delegate.GetRNGstate();
+        return delegate.GetRNGstate();
     }
 
     @Override
-    public void PutRNGstate() {
+    public int PutRNGstate() {
         RFFIUtils.traceUpCall("PutRNGstate");
-        delegate.PutRNGstate();
+        return delegate.PutRNGstate();
     }
 
     @Override
@@ -706,25 +723,25 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public void R_SetExternalPtrAddr(Object x, long addr) {
+    public int R_SetExternalPtrAddr(Object x, long addr) {
         RFFIUtils.traceUpCall("R_SetExternalPtrAddr", x);
-        delegate.R_SetExternalPtrAddr(x, addr);
+        return delegate.R_SetExternalPtrAddr(x, addr);
     }
 
     @Override
-    public void R_SetExternalPtrTag(Object x, Object tag) {
+    public int R_SetExternalPtrTag(Object x, Object tag) {
         RFFIUtils.traceUpCall("R_SetExternalPtrTag", x);
-        delegate.R_SetExternalPtrTag(x, tag);
+        return delegate.R_SetExternalPtrTag(x, tag);
     }
 
     @Override
-    public void R_SetExternalPtrProtected(Object x, Object prot) {
+    public int R_SetExternalPtrProtected(Object x, Object prot) {
         RFFIUtils.traceUpCall("R_ExternalPtrProt", x);
-        delegate.R_SetExternalPtrProtected(x, prot);
+        return delegate.R_SetExternalPtrProtected(x, prot);
     }
 
     @Override
-    public REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize) {
+    public Object R_NewHashedEnv(Object parent, Object initialSize) {
         RFFIUtils.traceUpCall("R_NewHashedEnv", parent, initialSize);
         return delegate.R_NewHashedEnv(parent, initialSize);
     }
@@ -766,13 +783,13 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
     }
 
     @Override
-    public int R_ReadConnection(int fd, byte[] buf) {
+    public int R_ReadConnection(int fd, Object buf) {
         RFFIUtils.traceUpCall("R_ReadConnection", fd, buf);
         return delegate.R_ReadConnection(fd, buf);
     }
 
     @Override
-    public int R_WriteConnection(int fd, byte[] buf) {
+    public int R_WriteConnection(int fd, Object buf) {
         RFFIUtils.traceUpCall("R_WriteConnection", fd, buf);
         return delegate.R_WriteConnection(fd, buf);
     }
@@ -825,4 +842,40 @@ final class TracingUpCallsRFFIImpl implements UpCallsRFFI {
         return delegate.R_MethodsNamespace();
     }
 
+    @Override
+    public int Rf_str2type(Object name) {
+        RFFIUtils.traceUpCall("Rf_str2type");
+        return delegate.Rf_str2type(name);
+    }
+
+    @Override
+    public double Rf_dunif(double a, double b, double c, int d) {
+        RFFIUtils.traceUpCall("Rf_dunif", a, b, c, d);
+        return delegate.Rf_dunif(a, b, c, d);
+    }
+
+    @Override
+    public double Rf_qunif(double a, double b, double c, int d, int e) {
+        RFFIUtils.traceUpCall("Rf_qunif", a, b, c, d, e);
+        return delegate.Rf_qunif(a, b, c, d, e);
+    }
+
+    @Override
+    public double Rf_punif(double a, double b, double c, int d, int e) {
+        RFFIUtils.traceUpCall("Rf_punif", a, b, c, d, e);
+        return delegate.Rf_punif(a, b, c, d, e);
+    }
+
+    @Override
+    public double Rf_runif(double a, double b) {
+        RFFIUtils.traceUpCall("Rf_runif", a, b);
+        return delegate.Rf_runif(a, b);
+    }
+
+    @Override
+    public Object Rf_namesgets(Object vec, Object val) {
+        RFFIUtils.traceUpCall("Rf_namesgets", vec, val);
+        return delegate.Rf_namesgets(vec, val);
+    }
+
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java
new file mode 100644
index 0000000000000000000000000000000000000000..cbaa000be27e05852271586265fab913b3d6bba5
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/UpCallUnwrap.java
@@ -0,0 +1,101 @@
+/*
+ * 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.ffi.impl.common;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+
+public final class UpCallUnwrap extends Node {
+
+    @Child private Node isBoxed;
+    @Child private Node unbox;
+    private final BranchProfile nativePointerProfile = isLLVM() ? BranchProfile.create() : null;
+
+    /**
+     * There are three possibilities as enumerated below.
+     * <ul>
+     * <li>For an {@link RTruffleObject} there is nothing to do, and indeed, calling {@code unbox}
+     * would be disastrous, as that means, e.g., for a RVector, extract the first element!</li>
+     * <li>Or we could get a {@code TruffleObject} from another language domain, e.g a
+     * {@code JavaObject} that wraps, e.g., an {@code Integer}. Such a value has to be unboxed.
+     * Similarly a {@code NativePointer} encoding, e.g., a C char array. One special case in the
+     * LLVM implementation is {@code NativePointer} that represents an object stored to memory,
+     * which requires a lookup (and not an {@code UNBOX}).</li>
+     * <li>We could also get a plain {@link Integer} or similar type in which case there is nothing
+     * to do.</li>
+     * </ul>
+     */
+    public Object unwrap(Object x) {
+        if (x instanceof RTruffleObject) {
+            return x;
+        } else if (x instanceof TruffleObject) {
+            if (isBoxed == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                isBoxed = insert(Message.IS_BOXED.createNode());
+            }
+            TruffleObject xTo = (TruffleObject) x;
+            if (ForeignAccess.sendIsBoxed(isBoxed, xTo)) {
+                if (unbox == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    unbox = insert(Message.UNBOX.createNode());
+                }
+                try {
+                    return ForeignAccess.sendUnbox(unbox, xTo);
+                } catch (UnsupportedMessageException e) {
+                    throw RInternalError.shouldNotReachHere(e, "UNBOX message fails after IS_BOXED=true");
+                }
+            } else {
+                // didn't UNBOX or really was null (e.g. null String)
+                if (isLLVM()) {
+                    nativePointerProfile.enter();
+                    TruffleObject xtoObject = checkNativePointer(xTo);
+                    if (xtoObject != null) {
+                        return xtoObject;
+                    }
+                }
+                return x;
+            }
+        } else {
+            return x;
+        }
+    }
+
+    private static boolean isLLVM() {
+        return RFFIFactory.getType() == RFFIFactory.Type.LLVM;
+    }
+
+    @TruffleBoundary
+    private static TruffleObject checkNativePointer(TruffleObject xto) {
+        return NativePointer.check(xto);
+    }
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/llvm_dummy.c b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/package-info.java
similarity index 78%
rename from com.oracle.truffle.r.native/fficall/src/truffle_llvm/llvm_dummy.c
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/package-info.java
index 4ad1b6b8d8df5d22e2431a5652d1a4fbfe42b8f8..94d20325b8a69934ce8ba489757fa5d04bfc88ff 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/llvm_dummy.c
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -20,5 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-// A dummy file that is compiled (by fastr-cc) in place of any actual .c file in this directory.
-// This allows the IR for the actual .c file to be merged with the empty .o for llvm_dummy.
+/**
+ * Classes that are common to all FFI implementations.
+ */
+package com.oracle.truffle.r.ffi.impl.common;
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CharSXPWrapperMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/CharSXPWrapperMR.java
similarity index 89%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CharSXPWrapperMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/CharSXPWrapperMR.java
index 4e5a73a607ee27689111a5307a3b0b33d95baf1c..70f024e443059ff9902a8ae317dffb7ab6b546b2 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CharSXPWrapperMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/CharSXPWrapperMR.java
@@ -20,16 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 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.ffi.CharSXPWrapper;
 
-@MessageResolution(receiverType = CharSXPWrapper.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = CharSXPWrapper.class)
 public class CharSXPWrapperMR {
     @CanResolve
     public abstract static class CharSXPWrapperCheck extends Node {
@@ -38,5 +37,4 @@ public class CharSXPWrapperMR {
             return receiver instanceof CharSXPWrapper;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLDotSymbolMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/DLLDotSymbolMR.java
similarity index 89%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLDotSymbolMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/DLLDotSymbolMR.java
index 2a0374f7ec0579720527ad2c13a8c172abc4716a..6c29f5f5058dcac5a7632a1865c7232b97223a87 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLDotSymbolMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/DLLDotSymbolMR.java
@@ -20,16 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 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.ffi.DLL;
 
-@MessageResolution(receiverType = DLL.DotSymbol.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = DLL.DotSymbol.class)
 public class DLLDotSymbolMR {
     @CanResolve
     public abstract static class DotSymbolCheck extends Node {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLInfoMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/DLLInfoMR.java
similarity index 89%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLInfoMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/DLLInfoMR.java
index 1161da07d4d358c104533b8a6b5393044edb5193..60657d6cd23d5f9fb3b29ac914f007094b41fdc5 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/DLLInfoMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/DLLInfoMR.java
@@ -20,16 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.MessageResolution;
 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.ffi.DLL;
 
-@MessageResolution(receiverType = DLL.DLLInfo.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = DLL.DLLInfo.class)
 public class DLLInfoMR {
     @CanResolve
     public abstract static class DLLInfolCheck extends Node {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/FFI_RForeignAccessFactoryImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/FFI_RForeignAccessFactoryImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..d7c09261ed77d45475d3aca1a53df32378bbf30a
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/FFI_RForeignAccessFactoryImpl.java
@@ -0,0 +1,42 @@
+/*
+ * 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.ffi.impl.interop;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+
+public class FFI_RForeignAccessFactoryImpl {
+    public static ForeignAccess getForeignAccess(RTruffleObject obj) {
+        if (obj instanceof DLL.DLLInfo) {
+            return DLLInfoMRForeign.ACCESS;
+        } else if (obj instanceof DLL.DotSymbol) {
+            return DLLDotSymbolMRForeign.ACCESS;
+        } else if (obj instanceof CharSXPWrapper) {
+            return CharSXPWrapperMRForeign.ACCESS;
+        } else {
+            return null;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeCharArray.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeCharArray.java
similarity index 82%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeCharArray.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeCharArray.java
index e963bddd8e37d4a34fbe92902a8f61f1cd26aade..cbba5538b356b1c9f3d4448752e3654e34318916 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeCharArray.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeCharArray.java
@@ -20,17 +20,23 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
+import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.TruffleObject;
 
 /**
  * A {@link TruffleObject} that represents an array of {@code unsigned char} values, that is
  * {@code NULL} terminated in the C domain.
  */
-public class NativeCharArray extends NativeUInt8Array {
+public final class NativeCharArray extends NativeUInt8Array {
 
     public NativeCharArray(byte[] bytes) {
         super(bytes, true);
     }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return NativeCharArrayMRForeign.ACCESS;
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeCharArrayMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeCharArrayMR.java
similarity index 76%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeCharArrayMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeCharArrayMR.java
index 63a819b58992c1e52442843a366166e3fb52e51f..1b5d2ff3cab0d48d47247d3469a1578316767c4f 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeCharArrayMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeCharArrayMR.java
@@ -20,16 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.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;
 
-@MessageResolution(receiverType = NativeCharArray.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = NativeCharArray.class)
 public class NativeCharArrayMR {
     @Resolve(message = "READ")
     public abstract static class NCAReadNode extends Node {
@@ -60,10 +59,10 @@ public class NativeCharArrayMR {
         }
     }
 
-    @Resolve(message = "UNBOX")
-    public abstract static class NCAUnboxNode extends Node {
-        protected long access(NativeCharArray receiver) {
-            return receiver.convertToNative();
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class NCAToNativeNode extends Node {
+        protected Object access(NativeCharArray receiver) {
+            return new CharNativePointer(receiver);
         }
     }
 
@@ -74,4 +73,19 @@ public class NativeCharArrayMR {
             return receiver instanceof NativeCharArray;
         }
     }
+
+    private static final class CharNativePointer extends NativePointer {
+        private final NativeCharArray nativeCharArray;
+
+        private CharNativePointer(NativeCharArray object) {
+            super(object);
+            this.nativeCharArray = object;
+        }
+
+        @Override
+        protected long asPointerImpl() {
+            long result = nativeCharArray.convertToNative();
+            return result;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArray.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArray.java
new file mode 100644
index 0000000000000000000000000000000000000000..05267fdf39e9010c930420429531a0e73bfa315c
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArray.java
@@ -0,0 +1,80 @@
+/*
+ * 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.ffi.impl.interop;
+
+import static com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter.UNSAFE;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+import sun.misc.Unsafe;
+
+public final class NativeDoubleArray extends NativeNACheck<double[]> implements RTruffleObject {
+
+    public final double[] value;
+
+    public NativeDoubleArray(Object obj, double[] value) {
+        super(obj);
+        this.value = value;
+    }
+
+    public NativeDoubleArray(double[] value) {
+        this(null, value);
+    }
+
+    double read(int index) {
+        if (nativeAddress != 0) {
+            return UNSAFE.getDouble(nativeAddress + index * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+        } else {
+            return value[index];
+        }
+    }
+
+    void write(int index, double nv) {
+        if (nativeAddress != 0) {
+            UNSAFE.putDouble(nativeAddress + index * Unsafe.ARRAY_DOUBLE_INDEX_SCALE, nv);
+        } else {
+            value[index] = nv;
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    protected void allocateNative() {
+        nativeAddress = UNSAFE.allocateMemory(value.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+        UNSAFE.copyMemory(value, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, null, nativeAddress, value.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+    }
+
+    @Override
+    @TruffleBoundary
+    protected void copyBackFromNative() {
+        // copy back
+        UNSAFE.copyMemory(null, nativeAddress, value, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, value.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE);
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return NativeDoubleArrayMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeDoubleArrayMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArrayMR.java
similarity index 68%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeDoubleArrayMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArrayMR.java
index 573bdb61008a581c770c3396df82334d5e87acbc..556fd3763ce994eeafc31337d4e60524c8f521b2 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeDoubleArrayMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeDoubleArrayMR.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -20,23 +20,22 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.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.RRuntime;
 
-@MessageResolution(receiverType = NativeDoubleArray.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = NativeDoubleArray.class)
 public class NativeDoubleArrayMR {
 
     @Resolve(message = "READ")
     public abstract static class NDAReadNode extends Node {
         protected double access(NativeDoubleArray receiver, int index) {
-            return receiver.value[index];
+            return receiver.read(index);
         }
     }
 
@@ -46,11 +45,33 @@ public class NativeDoubleArrayMR {
             if (value == RRuntime.DOUBLE_NA) {
                 receiver.setIncomplete();
             }
-            receiver.value[index] = value;
+            receiver.write(index, value);
             return value;
         }
     }
 
+    @Resolve(message = "IS_POINTER")
+    public abstract static class NDAIsPointer extends Node {
+
+        public Object access(@SuppressWarnings("unused") NativeDoubleArray receiver) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "AS_POINTER")
+    public abstract static class NDAAsPointerNode extends Node {
+        protected long access(NativeDoubleArray receiver) {
+            return receiver.convertToNative();
+        }
+    }
+
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class NDAToNativeNode extends Node {
+        protected Object access(@SuppressWarnings("unused") NativeDoubleArray receiver) {
+            return this;
+        }
+    }
+
     @CanResolve
     public abstract static class NDACheck extends Node {
 
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArray.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArray.java
new file mode 100644
index 0000000000000000000000000000000000000000..17b238ed20aea5e69543eedfba4d5ac88e5901bf
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArray.java
@@ -0,0 +1,80 @@
+/*
+ * 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.ffi.impl.interop;
+
+import static com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter.UNSAFE;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+import sun.misc.Unsafe;
+
+public final class NativeIntegerArray extends NativeNACheck<int[]> implements RTruffleObject {
+
+    public final int[] value;
+
+    public NativeIntegerArray(Object obj, int[] value) {
+        super(obj);
+        this.value = value;
+    }
+
+    public NativeIntegerArray(int[] value) {
+        this(null, value);
+    }
+
+    int read(int index) {
+        if (nativeAddress != 0) {
+            return UNSAFE.getInt(nativeAddress + index * Unsafe.ARRAY_INT_INDEX_SCALE);
+        } else {
+            return value[index];
+        }
+    }
+
+    void write(int index, int nv) {
+        if (nativeAddress != 0) {
+            UNSAFE.putInt(nativeAddress + index * Unsafe.ARRAY_INT_INDEX_SCALE, nv);
+        } else {
+            value[index] = nv;
+        }
+    }
+
+    @Override
+    @TruffleBoundary
+    protected void allocateNative() {
+        nativeAddress = UNSAFE.allocateMemory(value.length * Unsafe.ARRAY_INT_INDEX_SCALE);
+        UNSAFE.copyMemory(value, Unsafe.ARRAY_INT_BASE_OFFSET, null, nativeAddress, value.length * Unsafe.ARRAY_INT_INDEX_SCALE);
+    }
+
+    @Override
+    @TruffleBoundary
+    protected void copyBackFromNative() {
+        // copy back
+        UNSAFE.copyMemory(null, nativeAddress, value, Unsafe.ARRAY_INT_BASE_OFFSET, value.length * Unsafe.ARRAY_INT_INDEX_SCALE);
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return NativeIntegerArrayMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeIntegerArrayMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArrayMR.java
similarity index 70%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeIntegerArrayMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArrayMR.java
index ed06bb6f140574611d4338a43462242c6acc3617..d92725c8fd8ea5bb3e3a1b63b8f5f258944ad4f2 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeIntegerArrayMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeIntegerArrayMR.java
@@ -20,23 +20,22 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.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.RRuntime;
 
-@MessageResolution(receiverType = NativeIntegerArray.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = NativeIntegerArray.class)
 public class NativeIntegerArrayMR {
 
     @Resolve(message = "READ")
     public abstract static class NIAReadNode extends Node {
         protected int access(NativeIntegerArray receiver, int index) {
-            return receiver.value[index];
+            return receiver.read(index);
         }
     }
 
@@ -46,11 +45,18 @@ public class NativeIntegerArrayMR {
             if (value == RRuntime.INT_NA) {
                 receiver.setIncomplete();
             }
-            receiver.value[index] = value;
+            receiver.write(index, value);
             return value;
         }
     }
 
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class NIAToNativeNode extends Node {
+        protected Object access(NativeIntegerArray receiver) {
+            return new IntegerNativePointer(receiver);
+        }
+    }
+
     @CanResolve
     public abstract static class NIACheck extends Node {
 
@@ -58,4 +64,19 @@ public class NativeIntegerArrayMR {
             return receiver instanceof NativeIntegerArray;
         }
     }
+
+    private static final class IntegerNativePointer extends NativePointer {
+        private final NativeIntegerArray nativeIntegerArray;
+
+        private IntegerNativePointer(NativeIntegerArray object) {
+            super(object);
+            this.nativeIntegerArray = object;
+        }
+
+        @Override
+        protected long asPointerImpl() {
+            long result = nativeIntegerArray.convertToNative();
+            return result;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeLogicalArray.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArray.java
similarity index 71%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeLogicalArray.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArray.java
index d8229921a159b81888e35baacb3cc9f160757faf..9819981f46b37646dc0a11b1a44640c4cbcd2055 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeLogicalArray.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArray.java
@@ -20,9 +20,11 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 
@@ -30,8 +32,9 @@ import com.oracle.truffle.r.runtime.data.RTruffleObject;
  * Handles the requirement that the R FFI sees "logical" arrays as {@code int[]} but the actual
  * array in FastR is represented as {@code byte[]}.
  */
-public class NativeLogicalArray extends NativeNACheck implements RTruffleObject {
-    @CompilationFinal(dimensions = 1) public final byte[] data;
+public final class NativeLogicalArray extends NativeNACheck<byte[]> implements RTruffleObject {
+
+    public final byte[] data;
 
     public NativeLogicalArray(Object obj, byte[] value) {
         super(obj);
@@ -52,4 +55,20 @@ public class NativeLogicalArray extends NativeNACheck implements RTruffleObject
         }
         data[index] = newVal;
     }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return NativeLogicalArrayMRForeign.ACCESS;
+    }
+
+    @Override
+    @TruffleBoundary
+    protected void allocateNative() {
+        throw RInternalError.shouldNotReachHere();
+    }
+
+    @Override
+    protected void copyBackFromNative() {
+        throw RInternalError.shouldNotReachHere();
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeLogicalArrayMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArrayMR.java
similarity index 92%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeLogicalArrayMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArrayMR.java
index 63612d60f40c714d524072465597482e94dfc8cb..6cadbb1a64d93009b616adbd20d40f59a7cb2ba7 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeLogicalArrayMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeLogicalArrayMR.java
@@ -20,16 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.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;
 
-@MessageResolution(receiverType = NativeLogicalArray.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = NativeLogicalArray.class)
 public class NativeLogicalArrayMR {
     @Resolve(message = "READ")
     public abstract static class NLAReadNode extends Node {
@@ -55,7 +54,6 @@ public class NativeLogicalArrayMR {
 
     @CanResolve
     public abstract static class NLACheck extends Node {
-
         protected static boolean test(TruffleObject receiver) {
             return receiver instanceof NativeLogicalArray;
         }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeNACheck.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeNACheck.java
similarity index 66%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeNACheck.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeNACheck.java
index 5d05ca62d81b769471452086d111723257ec6c83..b6aa85883db201fd5dbfc0c283b421996d471698 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeNACheck.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeNACheck.java
@@ -20,8 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
+import static com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter.UNSAFE;
 import com.oracle.truffle.r.runtime.data.RVector;
 
 /**
@@ -29,9 +30,16 @@ import com.oracle.truffle.r.runtime.data.RVector;
  * native code.
  *
  */
-public class NativeNACheck {
+public abstract class NativeNACheck<T> implements AutoCloseable {
+
     private final RVector<?> vec;
 
+    /**
+     * If the array escapes the Truffle world via {@link #convertToNative()}, this value will be
+     * non-zero and is used exclusively thereafter.
+     */
+    protected long nativeAddress;
+
     protected NativeNACheck(Object x) {
         if (x instanceof RVector<?>) {
             vec = (RVector<?>) x;
@@ -46,4 +54,23 @@ public class NativeNACheck {
             vec.setComplete(false);
         }
     }
+
+    protected abstract void allocateNative();
+
+    protected abstract void copyBackFromNative();
+
+    final long convertToNative() {
+        if (nativeAddress == 0) {
+            allocateNative();
+        }
+        return nativeAddress;
+    }
+
+    @Override
+    public final void close() {
+        if (nativeAddress != 0) {
+            copyBackFromNative();
+            UNSAFE.freeMemory(nativeAddress);
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointer.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointer.java
new file mode 100644
index 0000000000000000000000000000000000000000..4202b55d79b54e8f96eaf3149a1a7ddfe2b296f7
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointer.java
@@ -0,0 +1,116 @@
+/*
+ * 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.ffi.impl.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.r.ffi.impl.llvm.TruffleLLVM_Utils;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+/**
+ * Created when a {@link RTruffleObject} subclass has no meaningful native representation,
+ * nevertheless a {@link Message#TO_NATIVE} message is sent to it.
+ */
+public class NativePointer implements TruffleObject {
+
+    /**
+     * This is used when an {@link RNull} is stored in memory (LLVM).
+     */
+    private static final class NullNativePointer extends NativePointer {
+        private NullNativePointer() {
+            super(RNull.instance);
+        }
+
+        @Override
+        protected long asPointerImpl() {
+            return 0;
+        }
+    }
+
+    public static final NullNativePointer NULL_NATIVEPOINTER = new NullNativePointer();
+
+    private static Table[] table = new Table[16];
+    private static int tableHwm;
+
+    private static class Table {
+        private final RTruffleObject object;
+        private final long nativePointer;
+
+        Table(RTruffleObject object, long nativePointer) {
+            this.object = object;
+            this.nativePointer = nativePointer;
+        }
+    }
+
+    final RTruffleObject object;
+
+    public NativePointer(RTruffleObject object) {
+        this.object = object;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return NativePointerMRForeign.ACCESS;
+    }
+
+    public static boolean isInstance(TruffleObject obj) {
+        return obj instanceof NativePointer;
+    }
+
+    public static TruffleObject check(TruffleObject object) {
+        long nativePointer = TruffleLLVM_Utils.getNativeAddress(object);
+        for (int i = tableHwm - 1; i >= 0; i--) {
+            if (table[i].nativePointer == nativePointer) {
+                return table[i].object;
+            }
+        }
+        return null;
+    }
+
+    final long asPointer() {
+        long result = asPointerImpl();
+        boolean newPointer = true;
+        for (int i = 0; i < tableHwm; i++) {
+            if (table[i].nativePointer == result) {
+                newPointer = false;
+                break;
+            }
+        }
+        if (newPointer) {
+            // System.out.printf("as_pointer: %x from %s\n", result, object.getClass().getName());
+            if (tableHwm >= table.length) {
+                Table[] newTable = new Table[table.length * 2];
+                System.arraycopy(table, 0, newTable, 0, table.length);
+                table = newTable;
+            }
+            table[tableHwm++] = new Table(object, result);
+        }
+        return result;
+    }
+
+    protected long asPointerImpl() {
+        return System.identityHashCode(object);
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointerMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointerMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..b8b73f6378c2b02ff692b92b425fa8d69a5526d4
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativePointerMR.java
@@ -0,0 +1,44 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.interop;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+
+@MessageResolution(receiverType = NativePointer.class)
+public class NativePointerMR {
+    @Resolve(message = "IS_POINTER")
+    public abstract static class AcceptIsPointer extends Node {
+        public Object access(@SuppressWarnings("unused") NativePointer object) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "AS_POINTER")
+    public abstract static class AcceptAsPointer extends Node {
+        public long access(NativePointer object) {
+            return object.asPointer();
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeRawArray.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeRawArray.java
similarity index 80%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeRawArray.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeRawArray.java
index dfd1e629cde7c7249590644ead7331e65a20ee44..631188e69b63a5c702720eadfad09fff01772e19 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeRawArray.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeRawArray.java
@@ -20,11 +20,18 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
-public class NativeRawArray extends NativeUInt8Array {
+import com.oracle.truffle.api.interop.ForeignAccess;
+
+public final class NativeRawArray extends NativeUInt8Array {
 
     public NativeRawArray(byte[] bytes) {
         super(bytes, false);
     }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return NativeRawArrayMRForeign.ACCESS;
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeRawArrayMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeRawArrayMR.java
similarity index 75%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeRawArrayMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeRawArrayMR.java
index b694a9f56f6656d334821a3142c24c1ceb4d8914..a17becc8ed2f2a4433bccc8b11b32517df567f2f 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeRawArrayMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeRawArrayMR.java
@@ -20,16 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.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;
 
-@MessageResolution(receiverType = NativeRawArray.class, language = TruffleRLanguage.class)
+@MessageResolution(receiverType = NativeRawArray.class)
 public class NativeRawArrayMR {
     @Resolve(message = "READ")
     public abstract static class NRAReadNode extends Node {
@@ -53,10 +52,10 @@ public class NativeRawArrayMR {
         }
     }
 
-    @Resolve(message = "UNBOX")
-    public abstract static class NRAUnboxNode extends Node {
-        protected long access(NativeRawArray receiver) {
-            return receiver.convertToNative();
+    @Resolve(message = "TO_NATIVE")
+    public abstract static class NRAToNativeNode extends Node {
+        protected Object access(NativeRawArray receiver) {
+            return new RawNativePointer(receiver);
         }
     }
 
@@ -67,4 +66,19 @@ public class NativeRawArrayMR {
             return receiver instanceof NativeRawArray;
         }
     }
+
+    private static final class RawNativePointer extends NativePointer {
+        private final NativeRawArray nativeRawArray;
+
+        private RawNativePointer(NativeRawArray object) {
+            super(object);
+            this.nativeRawArray = object;
+        }
+
+        @Override
+        protected long asPointerImpl() {
+            long result = nativeRawArray.convertToNative();
+            return result;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeUInt8Array.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeUInt8Array.java
similarity index 81%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeUInt8Array.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeUInt8Array.java
index d8c54ac6e3b12b6943778e32eb9f70f276d65b18..4bf73b78c4c4c7517fd31ffb4dd4c53f95beed58 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeUInt8Array.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/NativeUInt8Array.java
@@ -20,12 +20,12 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
-import static com.oracle.truffle.r.engine.interop.UnsafeAdapter.UNSAFE;
+import static com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter.UNSAFE;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 
 import sun.misc.Unsafe;
@@ -42,6 +42,7 @@ import sun.misc.Unsafe;
  * similar for {@link #write}.
  */
 public abstract class NativeUInt8Array implements RTruffleObject {
+
     public final byte[] bytes;
 
     /**
@@ -97,21 +98,30 @@ public abstract class NativeUInt8Array implements RTruffleObject {
 
     long convertToNative() {
         if (nativeAddress == 0) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            nativeAddress = UNSAFE.allocateMemory(effectiveLength);
-            UNSAFE.copyMemory(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, nativeAddress, bytes.length);
-            if (fakeNull()) {
-                UNSAFE.putByte(nativeAddress + bytes.length, (byte) 0);
-            }
+            allocateNative();
         }
         return nativeAddress;
     }
 
-    public byte[] getBytes() {
+    @TruffleBoundary
+    private void allocateNative() {
+        nativeAddress = UNSAFE.allocateMemory(effectiveLength);
+        UNSAFE.copyMemory(bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, nativeAddress, bytes.length);
+        if (fakeNull()) {
+            UNSAFE.putByte(nativeAddress + bytes.length, (byte) 0);
+        }
+    }
+
+    public byte[] getValue() {
         if (nativeAddress != 0) {
-            // copy back
-            UNSAFE.copyMemory(null, nativeAddress, bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, bytes.length);
+            copyBackFromNative();
         }
         return bytes;
     }
+
+    @TruffleBoundary
+    private void copyBackFromNative() {
+        // copy back
+        UNSAFE.copyMemory(null, nativeAddress, bytes, Unsafe.ARRAY_BYTE_BASE_OFFSET, bytes.length);
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/UnsafeAdapter.java
similarity index 97%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/UnsafeAdapter.java
index 7ef0df76f752eda1c64afcae8f588763f148d80c..413e72ff60ed329f3b683fdd031dd392e730515a 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnsafeAdapter.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/UnsafeAdapter.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop;
 
 import java.lang.reflect.Field;
 
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResult.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..f16e91a2fd014471506fee031d659465fddc5608
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResult.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.base;
+
+import java.util.ArrayList;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public final class GlobResult implements RTruffleObject {
+    private final ArrayList<String> paths = new ArrayList<>();
+
+    public void addPath(String path) {
+        paths.add(path);
+    }
+
+    public ArrayList<String> getPaths() {
+        return paths;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return GlobResultMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResultMR.java
similarity index 63%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResultMR.java
index 3a614c0a7bcdaff7838f6f5a0e33b78a235ccab8..2c7d26e85ebb434f93a49538445f719cba5a7375 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/GlobUpCallImplMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/GlobResultMR.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -20,30 +20,34 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop.base;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
 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.engine.interop.ffi.nfi.TruffleNFI_Base;
 
-@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl.class, language = TruffleRLanguage.class)
-public class GlobUpCallImplMR {
+@MessageResolution(receiverType = GlobResult.class)
+public class GlobResultMR {
     @CanResolve
-    public abstract static class GlobUpCallImplCheck extends Node {
+    public abstract static class BaseGlobResultCallbackCheck extends Node {
 
         protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl;
+            return receiver instanceof GlobResult;
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class GlobResultIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") GlobResult receiver) {
+            return true;
         }
     }
 
     @Resolve(message = "EXECUTE")
-    public abstract static class GlobUpCallImplExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_GlobNode.GlobUpCallImpl receiver, Object[] arguments) {
+    public abstract static class BaseGlobResultCallbackExecute extends Node {
+        protected Object access(GlobResult receiver, Object[] arguments) {
             receiver.addPath((String) arguments[0]);
             return receiver;
         }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResult.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..266efc5acd98170a936c2be67035fd96826d5183
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResult.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ffi.impl.interop.base;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public final class ReadlinkResult implements RTruffleObject {
+    private String link;
+    private int errno;
+
+    public void setResult(String link, int errno) {
+        this.link = link;
+        this.errno = errno;
+    }
+
+    public String getLink() {
+        return link;
+    }
+
+    public int getErrno() {
+        return errno;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return ReadlinkResultMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResultMR.java
similarity index 63%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResultMR.java
index 69cf41035975ae5e192aa05979df3225a1e74749..56d518440ae3062513a00edd065a6da31272278e 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/SetResultImplMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/ReadlinkResultMR.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -20,30 +20,34 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop.base;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
 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.engine.interop.ffi.nfi.TruffleNFI_Base;
 
-@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl.class, language = TruffleRLanguage.class)
-public class SetResultImplMR {
+@MessageResolution(receiverType = ReadlinkResult.class)
+public class ReadlinkResultMR {
     @CanResolve
-    public abstract static class SetResultImplCheck extends Node {
+    public abstract static class BaseReadlinkResultCallbackCheck extends Node {
 
         protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl;
+            return receiver instanceof ReadlinkResult;
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class ReadlinkResultIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") ReadlinkResult receiver) {
+            return true;
         }
     }
 
     @Resolve(message = "EXECUTE")
-    public abstract static class SetResultImplExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_ReadlinkNode.SetResultImpl receiver, Object[] arguments) {
+    public abstract static class BaseReadlinkResultCallbackExecute extends Node {
+        protected Object access(ReadlinkResult receiver, Object[] arguments) {
             receiver.setResult((String) arguments[0], (int) arguments[1]);
             return receiver;
         }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResult.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..1884ad0bfabd6141941fe6c87e211e476a2bb673
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResult.java
@@ -0,0 +1,49 @@
+/*
+ * 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.ffi.impl.interop.base;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public final class StrtolResult implements RTruffleObject {
+    private long result;
+    private int errno;
+
+    public void setResult(long result, int errno) {
+        this.result = result;
+        this.errno = errno;
+    }
+
+    public long getResult() {
+        return result;
+    }
+
+    public int getErrno() {
+        return errno;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return StrtolResultMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResultMR.java
similarity index 58%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResultMR.java
index 6382443b4fd3d6aec17eba4afd4cd3e1b9ed9316..0b306587388575e332cb810dcfcb9bb583ae2f19 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/UnameUpCallImplMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/StrtolResultMR.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -20,33 +20,36 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop.base;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
 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.engine.interop.ffi.nfi.TruffleNFI_Base;
 
-@MessageResolution(receiverType = TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl.class, language = TruffleRLanguage.class)
-public class UnameUpCallImplMR {
+@MessageResolution(receiverType = StrtolResult.class)
+public class StrtolResultMR {
     @CanResolve
-    public abstract static class UnameUpCallImplCheck extends Node {
+    public abstract static class BaseStrtolResultCallbackCheck extends Node {
 
         protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl;
+            return receiver instanceof StrtolResult;
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class StrolResultIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") StrtolResult receiver) {
+            return true;
         }
     }
 
     @Resolve(message = "EXECUTE")
-    public abstract static class UnameUpCallImplExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_Base.TruffleNFI_UnameNode.UnameUpCallImpl receiver, Object[] arguments) {
-            receiver.unameUpCall((String) arguments[0], (String) arguments[1], (String) arguments[2], (String) arguments[3], (String) arguments[4]);
+    public abstract static class BaseStrtolResultCallbackExecute extends Node {
+        protected Object access(StrtolResult receiver, Object[] arguments) {
+            receiver.setResult((long) arguments[0], (int) arguments[1]);
             return receiver;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResult.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..097610794db07e03b3776ce21e35dade8c0e7d60
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResult.java
@@ -0,0 +1,73 @@
+/*
+ * 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.ffi.impl.interop.base;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+
+public final class UnameResult implements BaseRFFI.UtsName, RTruffleObject {
+    private String sysname;
+    private String release;
+    private String version;
+    private String machine;
+    private String nodename;
+
+    public void setResult(String sysnameA, String releaseA, String versionA, String machineA, String nodenameA) {
+        sysname = sysnameA;
+        release = releaseA;
+        version = versionA;
+        machine = machineA;
+        nodename = nodenameA;
+    }
+
+    @Override
+    public String sysname() {
+        return sysname;
+    }
+
+    @Override
+    public String release() {
+        return release;
+    }
+
+    @Override
+    public String version() {
+        return version;
+    }
+
+    @Override
+    public String machine() {
+        return machine;
+    }
+
+    @Override
+    public String nodename() {
+        return nodename;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return UnameResultMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResultMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResultMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..e63607fbadda495659e53bb855afef2f44343882
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/base/UnameResultMR.java
@@ -0,0 +1,55 @@
+/*
+ * 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.ffi.impl.interop.base;
+
+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;
+
+@MessageResolution(receiverType = UnameResult.class)
+public class UnameResultMR {
+    @CanResolve
+    public abstract static class BaseUnameResultCallbackCheck extends Node {
+
+        protected static boolean test(TruffleObject receiver) {
+            return receiver instanceof UnameResult;
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class BaseUnameResultIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") UnameResult receiver) {
+            return true;
+        }
+    }
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class BaseUnameResultCallbackExecute extends Node {
+        protected Object access(UnameResult receiver, Object[] arguments) {
+            receiver.setResult((String) arguments[0], (String) arguments[1], (String) arguments[2], (String) arguments[3], (String) arguments[4]);
+            return receiver;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..fbc35fd5b8e569580e0d4e09230646c916aab034
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/package-info.java
@@ -0,0 +1,33 @@
+/*
+ * 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.
+ */
+/**
+ * A collection of types and {@link com.oracle.truffle.api.interop.MessageResolution} classes that
+ * support the implementations. Not all are used in every implementation, particularly JNI since
+ * that does not use Truffle interop.
+ *
+ * See {@link com.oracle.truffle.r.ffi.impl.interop.base} and
+ * {@link com.oracle.truffle.r.ffi.impl.interop.pcre} for similar classes specific to the
+ * {@link com.oracle.truffle.r.runtime.ffi.BaseRFFI} and
+ * {@link com.oracle.truffle.r.runtime.ffi.PCRERFFI} interfaces.
+ */
+package com.oracle.truffle.r.ffi.impl.interop;
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResult.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..e54b5787ad7be62e23ff9d5f422a873cd5df595c
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResult.java
@@ -0,0 +1,47 @@
+/*
+ * 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.ffi.impl.interop.pcre;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public final class CaptureNamesResult implements RTruffleObject {
+    private final String[] captureNames;
+
+    public CaptureNamesResult(int captureCount) {
+        this.captureNames = new String[captureCount];
+    }
+
+    public void addName(int i, String name) {
+        captureNames[i] = name;
+    }
+
+    public String[] getCaptureNames() {
+        return captureNames;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return CaptureNamesResultMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResultMR.java
similarity index 64%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResultMR.java
index 5063771196f2e8e7d5113cced1325945a591b61e..b836331256e6177b658fbdfa449e6df65398e4aa 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/CaptureNamesImplMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CaptureNamesResultMR.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -20,9 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop.pcre;
 
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
@@ -31,30 +30,39 @@ 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.engine.interop.ffi.nfi.TruffleNFI_PCRE;
 import com.oracle.truffle.r.runtime.RInternalError;
 
-@MessageResolution(receiverType = TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl.class, language = TruffleRLanguage.class)
-public class CaptureNamesImplMR {
+@MessageResolution(receiverType = CaptureNamesResult.class)
+public class CaptureNamesResultMR {
     @CanResolve
-    public abstract static class CaptureNamesImplCheck extends Node {
+    public abstract static class CaptureNamesCallbackCheck extends Node {
 
         protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl;
+            return receiver instanceof CaptureNamesResult;
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class CaptureNamesResultIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") CaptureNamesResult receiver) {
+            return true;
         }
     }
 
     @Resolve(message = "EXECUTE")
-    public abstract static class CaptureNamesImplExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_PCRE.TruffleNFI_GetCaptureNamesNode.CaptureNamesImpl receiver, Object[] arguments) {
+    public abstract static class CaptureNamesCallbackExecute extends Node {
+
+        @Child private Node isNullNode = Message.IS_NULL.createNode();
+        @Child private Node unboxNode = Message.UNBOX.createNode();
+
+        protected Object access(CaptureNamesResult receiver, Object[] arguments) {
             try {
                 Object arg1 = arguments[1];
                 if (arg1 instanceof TruffleObject) {
-                    if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) {
+                    if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) arg1)) {
                         arg1 = null;
                     } else {
-                        arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1);
+                        arg1 = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) arg1);
                     }
                 }
                 receiver.addName((int) arguments[0], (String) arg1);
@@ -64,5 +72,4 @@ public class CaptureNamesImplMR {
             }
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResult.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResult.java
new file mode 100644
index 0000000000000000000000000000000000000000..946d2a8b8d27cd7cd0b8ec6f60938c3828c95060
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResult.java
@@ -0,0 +1,44 @@
+/*
+ * 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.ffi.impl.interop.pcre;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+
+public final class CompileResult implements RTruffleObject {
+    private PCRERFFI.Result result;
+
+    public void set(long pcreResult, String errorMessage, int errOffset) {
+        result = new PCRERFFI.Result(pcreResult, errorMessage, errOffset);
+    }
+
+    public PCRERFFI.Result getResult() {
+        return result;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return CompileResultMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResultMR.java
similarity index 67%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResultMR.java
index 34c97f9c38af9280a2cee84030ce905b28957ae9..76562a7e33a500bff2fe2568dcf7431996048011 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/MakeResultImplMR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pcre/CompileResultMR.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.ffi.impl.interop.pcre;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
@@ -31,38 +31,46 @@ 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.engine.interop.ffi.nfi.TruffleNFI_PCRE;
 import com.oracle.truffle.r.runtime.RInternalError;
 
-@MessageResolution(receiverType = TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl.class, language = TruffleRLanguage.class)
-public class MakeResultImplMR {
+@MessageResolution(receiverType = CompileResult.class)
+public class CompileResultMR {
     @CanResolve
-    public abstract static class MakeResultImplCheck extends Node {
+    public abstract static class ResultCallbackCheck extends Node {
 
         protected static boolean test(TruffleObject receiver) {
-            return receiver instanceof TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl;
+            return receiver instanceof CompileResult;
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class CompileResultIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") CompileResult receiver) {
+            return true;
         }
     }
 
     @Resolve(message = "EXECUTE")
-    public abstract static class MakeResultImplExecute extends Node {
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, TruffleNFI_PCRE.TruffleNFI_CompileNode.MakeResultImpl receiver, Object[] arguments) {
+    public abstract static class ResultCallbackExecute extends Node {
+
+        @Child private Node isNullNode = Message.IS_NULL.createNode();
+        @Child private Node unboxNode = Message.UNBOX.createNode();
+
+        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, CompileResult receiver, Object[] arguments) {
             try {
                 Object arg1 = arguments[1];
                 if (arg1 instanceof TruffleObject) {
-                    if (ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), (TruffleObject) arg1)) {
+                    if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) arg1)) {
                         arg1 = null;
                     } else {
-                        arg1 = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) arg1);
+                        arg1 = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) arg1);
                     }
                 }
-                receiver.makeresult((long) arguments[0], (String) arg1, (int) arguments[2]);
+                receiver.set((long) arguments[0], (String) arg1, (int) arguments[2]);
                 return receiver;
             } catch (InteropException e) {
                 throw RInternalError.shouldNotReachHere(e);
             }
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/ForceSymbolsCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/ForceSymbolsCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..74aed4bcdfe4f80dafadc052da0e8607e1d382f6
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/ForceSymbolsCall.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.common.PkgInitUpCalls;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class ForceSymbolsCall implements RTruffleObject {
+    public final PkgInitUpCalls pkgInitUpCalls;
+
+    public ForceSymbolsCall(PkgInitUpCalls pkgInitUpCalls) {
+        this.pkgInitUpCalls = pkgInitUpCalls;
+    }
+
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof ForceSymbolsCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return ForceSymbolsCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/ForceSymbolsCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/ForceSymbolsCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..2aee305534eef04d477d5ecee985a5afb69578d6
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/ForceSymbolsCallMR.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+
+@MessageResolution(receiverType = ForceSymbolsCall.class)
+public class ForceSymbolsCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class ForceSymbolsCallExecute extends Node {
+        protected java.lang.Object access(ForceSymbolsCall receiver, Object[] arguments) {
+            return receiver.pkgInitUpCalls.forceSymbols((DLLInfo) arguments[0], (int) arguments[1]);
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class ForceSymbolsCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") ForceSymbolsCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/GetCCallableCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/GetCCallableCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..591d749dd48329a25804912a6586b8503a3b68c8
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/GetCCallableCall.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.common.PkgInitUpCalls;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class GetCCallableCall implements RTruffleObject {
+    public final PkgInitUpCalls pkgInitUpCalls;
+
+    public GetCCallableCall(PkgInitUpCalls pkgInitUpCalls) {
+        this.pkgInitUpCalls = pkgInitUpCalls;
+    }
+
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof GetCCallableCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return GetCCallableCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/GetCCallableCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/GetCCallableCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..fd4531500b9dfddff51ba8d1233fad051dd5df93
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/GetCCallableCallMR.java
@@ -0,0 +1,44 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+
+@MessageResolution(receiverType = GetCCallableCall.class)
+public class GetCCallableCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class GetCCallableCallExecute extends Node {
+        protected java.lang.Object access(GetCCallableCall receiver, Object[] arguments) {
+            return receiver.pkgInitUpCalls.getCCallable((String) arguments[0], (String) arguments[1]);
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class GetCCallableCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") GetCCallableCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterCCallableCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterCCallableCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..5e820b093337d09416db11fb0442c1ed8a55f319
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterCCallableCall.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.common.PkgInitUpCalls;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class RegisterCCallableCall implements RTruffleObject {
+    public final PkgInitUpCalls pkgInitUpCalls;
+
+    public RegisterCCallableCall(PkgInitUpCalls pkgInitUpCalls) {
+        this.pkgInitUpCalls = pkgInitUpCalls;
+    }
+
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof RegisterCCallableCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return RegisterCCallableCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterCCallableCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterCCallableCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..d80a29b324af729d261254dd538fb32f198ab303
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterCCallableCallMR.java
@@ -0,0 +1,44 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+
+@MessageResolution(receiverType = RegisterCCallableCall.class)
+public class RegisterCCallableCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class RegisterCCallableCallExecute extends Node {
+        protected java.lang.Object access(RegisterCCallableCall receiver, Object[] arguments) {
+            return receiver.pkgInitUpCalls.registerCCallable((String) arguments[0], (String) arguments[1], arguments[2]);
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class RegisterCCallableCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") RegisterCCallableCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterRoutinesCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterRoutinesCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..1d5808a9b90f98661aa44c3f665b53e6cd36517b
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterRoutinesCall.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.common.PkgInitUpCalls;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class RegisterRoutinesCall implements RTruffleObject {
+    public final PkgInitUpCalls pkgInitUpCalls;
+
+    public RegisterRoutinesCall(PkgInitUpCalls pkgInitUpCalls) {
+        this.pkgInitUpCalls = pkgInitUpCalls;
+    }
+
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof RegisterRoutinesCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return RegisterRoutinesCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterRoutinesCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterRoutinesCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..caaf0033264839fae802b15eeb18a57f0bdda648
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/RegisterRoutinesCallMR.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+
+@MessageResolution(receiverType = RegisterRoutinesCall.class)
+public class RegisterRoutinesCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class RegisterRoutinesCallExecute extends Node {
+        protected java.lang.Object access(RegisterRoutinesCall receiver, Object[] arguments) {
+            return receiver.pkgInitUpCalls.registerRoutines((DLLInfo) arguments[0], (int) arguments[1], (int) arguments[2], (long) arguments[3]);
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class RegisterRoutinesCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") RegisterRoutinesCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..43ac4c8148971282872d7955826d3a8d255531c9
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCall.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.common.PkgInitUpCalls;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class SetDotSymbolValuesCall implements RTruffleObject {
+    public final PkgInitUpCalls pkgInitUpCalls;
+
+    public SetDotSymbolValuesCall(PkgInitUpCalls pkgInitUpCalls) {
+        this.pkgInitUpCalls = pkgInitUpCalls;
+    }
+
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof SetDotSymbolValuesCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return SetDotSymbolValuesCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6ee9008c16eae9a81e4704f44217ed89ed3ed3f
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/SetDotSymbolValuesCallMR.java
@@ -0,0 +1,48 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.common.UpCallUnwrap;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+
+@MessageResolution(receiverType = SetDotSymbolValuesCall.class)
+public class SetDotSymbolValuesCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class SetDotSymbolValuesCallExecute extends Node {
+        @Child private UpCallUnwrap unwrap = new UpCallUnwrap();
+
+        protected java.lang.Object access(SetDotSymbolValuesCall receiver, Object[] arguments) {
+            return receiver.pkgInitUpCalls.setDotSymbolValues((DLLInfo) arguments[0], (String) unwrap.unwrap(arguments[1]), arguments[2], (int) arguments[3]);
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class SetDotSymbolValuesCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") SetDotSymbolValuesCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/UseDynamicSymbolsCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/UseDynamicSymbolsCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..23b2bb055d221cbe7919d5ac95c1e81c64c49020
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/UseDynamicSymbolsCall.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.common.PkgInitUpCalls;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class UseDynamicSymbolsCall implements RTruffleObject {
+    public final PkgInitUpCalls pkgInitUpCalls;
+
+    public UseDynamicSymbolsCall(PkgInitUpCalls pkgInitUpCalls) {
+        this.pkgInitUpCalls = pkgInitUpCalls;
+    }
+
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof UseDynamicSymbolsCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return UseDynamicSymbolsCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/UseDynamicSymbolsCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/UseDynamicSymbolsCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..9c53915f1f1b28bea82f8ee3f6f959b8e66076ca
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/pkginit/UseDynamicSymbolsCallMR.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.interop.pkginit;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+
+@MessageResolution(receiverType = UseDynamicSymbolsCall.class)
+public class UseDynamicSymbolsCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class UseDynamicSymbolsCallExecute extends Node {
+        protected java.lang.Object access(UseDynamicSymbolsCall receiver, Object[] arguments) {
+            return receiver.pkgInitUpCalls.useDynamicSymbols((DLLInfo) arguments[0], (int) arguments[1]);
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class UseDynamicSymbolsCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") UseDynamicSymbolsCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..b9b04811f5e44ec6e160c4b5e0e25a894660a412
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCall.java
@@ -0,0 +1,38 @@
+/*
+ * 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.ffi.impl.interop.tools;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class RConnGetCCall implements RTruffleObject {
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof RConnGetCCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return RConnGetCCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..88b14ea689a4f785c1c381c90ade3f128c24e9f5
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/interop/tools/RConnGetCCallMR.java
@@ -0,0 +1,51 @@
+/*
+ * 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.ffi.impl.interop.tools;
+
+import java.io.IOException;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.conn.RConnection;
+
+@MessageResolution(receiverType = RConnGetCCall.class)
+public class RConnGetCCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class RConnGetCCallExecute extends Node {
+        protected java.lang.Object access(@SuppressWarnings("unused") RConnGetCCall receiver, Object[] arguments) {
+            try {
+                return ((RConnection) arguments[0]).getc();
+            } catch (IOException ex) {
+                return -1;
+            }
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class RConnGetCCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") RConnGetCCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNIUpCallsRFFIImpl.java
similarity index 93%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNIUpCallsRFFIImpl.java
index 233e055e8ed4414f744bc12200c1b25df822a6ae..1c4911f127714501e828f141e9fcc3ad8d9c008c 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNIUpCallsRFFIImpl.java
@@ -20,11 +20,11 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.guaranteeInstanceOf;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.guaranteeInstanceOf;
 
-import com.oracle.truffle.r.nodes.ffi.JavaUpCallsRFFIImpl;
+import com.oracle.truffle.r.ffi.impl.common.JavaUpCallsRFFIImpl;
 import com.oracle.truffle.r.runtime.RErrorHandling;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RVector;
@@ -68,5 +68,4 @@ public class JNIUpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
     public Object R_CHAR(Object x) {
         throw RInternalError.shouldNotReachHere();
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Base.java
similarity index 87%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Base.java
index dac6e7af7654c4458feb204ba68ba39b6c8dd2ae..e45722e0c97dc72648074bfd67fa23564691c2a0 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Base.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Base.java
@@ -20,16 +20,17 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import java.io.IOException;
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 
 public class JNI_Base implements BaseRFFI {
-    public static class JNI_GetpidNode extends GetpidNode {
+    private static class JNI_GetpidNode extends Node implements GetpidNode {
         @TruffleBoundary
         @Override
         public int execute() {
@@ -37,7 +38,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_GetwdNode extends GetwdNode {
+    private static class JNI_GetwdNode extends Node implements GetwdNode {
         @TruffleBoundary
         @Override
         public String execute() {
@@ -55,7 +56,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_SetwdNode extends SetwdNode {
+    private static class JNI_SetwdNode extends Node implements SetwdNode {
         @TruffleBoundary
         @Override
         public int execute(String dir) {
@@ -63,7 +64,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_ReadlinkNode extends ReadlinkNode {
+    private static class JNI_ReadlinkNode extends Node implements ReadlinkNode {
         private static final int EINVAL = 22;
 
         @TruffleBoundary
@@ -83,7 +84,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_MkdtempNode extends MkdtempNode {
+    private static class JNI_MkdtempNode extends Node implements MkdtempNode {
         @TruffleBoundary
         @Override
         public String execute(String template) {
@@ -104,7 +105,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_MkdirNode extends MkdirNode {
+    private static class JNI_MkdirNode extends Node implements MkdirNode {
         @TruffleBoundary
         @Override
         public void execute(String dir, int mode) throws IOException {
@@ -115,7 +116,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_ChmodNode extends ChmodNode {
+    private static class JNI_ChmodNode extends Node implements ChmodNode {
         @TruffleBoundary
         @Override
         public int execute(String path, int mode) {
@@ -123,7 +124,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_StrolNode extends StrolNode {
+    private static class JNI_StrolNode extends Node implements StrolNode {
         @TruffleBoundary
         @Override
         public long execute(String s, int base) throws IllegalArgumentException {
@@ -137,7 +138,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_UnameNode extends UnameNode {
+    private static class JNI_UnameNode extends Node implements UnameNode {
         @TruffleBoundary
         @Override
         public UtsName execute() {
@@ -145,7 +146,7 @@ public class JNI_Base implements BaseRFFI {
         }
     }
 
-    public static class JNI_GlobNode extends GlobNode {
+    private static class JNI_GlobNode extends Node implements GlobNode {
         @TruffleBoundary
         @Override
         public ArrayList<String> glob(String pattern) {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_C.java
similarity index 80%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_C.java
index 93311fa0b1a565cba34338c6cb1d354ed507a210..17325b33650a5e6e338a27d9e0fc71eda1a57871 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_C.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_C.java
@@ -20,17 +20,18 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceEnabled;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
 
 public class JNI_C implements CRFFI {
-    public static class JNI_InvokeCNode extends InvokeCNode {
+    private static class JNI_InvokeCNode extends Node implements InvokeCNode {
         /**
          * This is rather similar to {@link JNI_Call}, except the objects are guaranteed to be
          * native array types, no upcalls are possible, and no result is returned. However, the
@@ -39,17 +40,17 @@ public class JNI_C implements CRFFI {
          */
         @Override
         @TruffleBoundary
-        public void execute(NativeCallInfo nativeCallInfo, Object[] args) {
+        public void execute(NativeCallInfo nativeCallInfo, Object[] args, boolean hasStrings) {
             synchronized (JNI_C.class) {
                 if (traceEnabled()) {
                     traceDownCall(nativeCallInfo.name, args);
                 }
-                c(nativeCallInfo.address.asAddress(), args);
+                c(nativeCallInfo.address.asAddress(), args, hasStrings);
             }
         }
     }
 
-    private static native void c(long address, Object[] args);
+    private static native void c(long address, Object[] args, boolean hasStrings);
 
     @Override
     public InvokeCNode createInvokeCNode() {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Call.java
similarity index 92%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Call.java
index 115c562a7da08795f749b39c9bc216158940bdb1..ee3d5222ab9ef5942554bf0221b1231271614bd5 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Call.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Call.java
@@ -20,19 +20,20 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceDownCallReturn;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceEnabled;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
+import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
 import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 
 /**
  * The only variety in the signatures for {@code .Call} is the number of arguments. GnuR supports a
@@ -46,7 +47,7 @@ import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
  */
 public class JNI_Call implements CallRFFI {
 
-    public static class JNI_InvokeCallNode extends InvokeCallNode {
+    private static class JNI_InvokeCallNode extends Node implements InvokeCallNode {
 
         @Override
         @TruffleBoundary
@@ -103,7 +104,7 @@ public class JNI_Call implements CallRFFI {
         }
     }
 
-    public static class JNI_InvokeVoidCallNode extends InvokeVoidCallNode {
+    private static class JNI_InvokeVoidCallNode extends Node implements InvokeVoidCallNode {
 
         @Override
         @TruffleBoundary
@@ -131,7 +132,6 @@ public class JNI_Call implements CallRFFI {
                 }
             }
         }
-
     }
 
     public JNI_Call() {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_DLL.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_DLL.java
similarity index 89%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_DLL.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_DLL.java
index 697fe085b4f669cb57b35bf0076bd284dc74d25b..08d72f24712217f3f0bfd0088fef79f332ab0b97 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_DLL.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_DLL.java
@@ -20,15 +20,16 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
-import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
 
 public class JNI_DLL implements DLLRFFI {
 
-    public static class JNI_DLOpenNode extends DLOpenNode {
+    private static class JNI_DLOpenNode extends Node implements DLOpenNode {
         @Override
         @TruffleBoundary
         public Object execute(String path, boolean local, boolean now) throws UnsatisfiedLinkError {
@@ -37,7 +38,7 @@ public class JNI_DLL implements DLLRFFI {
         }
     }
 
-    public static class JNI_DLSymNode extends DLSymNode {
+    private static class JNI_DLSymNode extends Node implements DLSymNode {
         @Override
         @TruffleBoundary
         public SymbolHandle execute(Object handle, String symbol) throws UnsatisfiedLinkError {
@@ -47,14 +48,13 @@ public class JNI_DLL implements DLLRFFI {
         }
     }
 
-    public static class JNI_DLCloseNode extends DLCloseNode {
+    private static class JNI_DLCloseNode extends Node implements DLCloseNode {
         @Override
         @TruffleBoundary
         public int execute(Object handle) {
             long nativeHandle = (Long) handle;
             return native_dlclose(nativeHandle);
         }
-
     }
 
     // Checkstyle: stop method name check
@@ -81,5 +81,4 @@ public class JNI_DLL implements DLLRFFI {
     public DLCloseNode createDLCloseNode() {
         return new JNI_DLCloseNode();
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Glob.java
similarity index 96%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Glob.java
index e39000a54913d6e572794bee8792796f7dc01875..a3e344944b5fcb6e7389f1bc279fd1cbce2f56ac 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Glob.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Glob.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import java.util.ArrayList;
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Lapack.java
similarity index 87%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Lapack.java
index 25c8ad506d1ed729b4a48e73f32bd1b2938fd8fd..ac528594c16af414a6d0705f5093bed69452387d 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Lapack.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Lapack.java
@@ -20,13 +20,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
 
 public class JNI_Lapack implements LapackRFFI {
-    private static class JNI_IlaverNode extends IlaverNode {
+    private static class JNI_IlaverNode extends Node implements IlaverNode {
         @Override
         @TruffleBoundary
         public void execute(int[] version) {
@@ -34,7 +35,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DgeevNode extends DgeevNode {
+    private static class JNI_DgeevNode extends Node implements DgeevNode {
         @Override
         @TruffleBoundary
         public int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
@@ -42,7 +43,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_Dgeqp3Node extends Dgeqp3Node {
+    private static class JNI_Dgeqp3Node extends Node implements Dgeqp3Node {
         @Override
         @TruffleBoundary
         public int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
@@ -50,7 +51,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DormqrNode extends DormqrNode {
+    private static class JNI_DormqrNode extends Node implements DormqrNode {
         @Override
         @TruffleBoundary
         public int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
@@ -58,7 +59,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DtrtrsNode extends DtrtrsNode {
+    private static class JNI_DtrtrsNode extends Node implements DtrtrsNode {
         @Override
         @TruffleBoundary
         public int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
@@ -66,7 +67,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DgetrfNode extends DgetrfNode {
+    private static class JNI_DgetrfNode extends Node implements DgetrfNode {
         @Override
         @TruffleBoundary
         public int execute(int m, int n, double[] a, int lda, int[] ipiv) {
@@ -74,7 +75,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DpotrfNode extends DpotrfNode {
+    private static class JNI_DpotrfNode extends Node implements DpotrfNode {
         @Override
         @TruffleBoundary
         public int execute(char uplo, int n, double[] a, int lda) {
@@ -82,7 +83,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DpotriNode extends DpotriNode {
+    private static class JNI_DpotriNode extends Node implements DpotriNode {
         @Override
         @TruffleBoundary
         public int execute(char uplo, int n, double[] a, int lda) {
@@ -90,7 +91,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DpstrfNode extends DpstrfNode {
+    private static class JNI_DpstrfNode extends Node implements DpstrfNode {
         @Override
         @TruffleBoundary
         public int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
@@ -98,7 +99,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DgesvNode extends DgesvNode {
+    private static class JNI_DgesvNode extends Node implements DgesvNode {
         @Override
         @TruffleBoundary
         public int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
@@ -106,7 +107,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DlangeNode extends DlangeNode {
+    private static class JNI_DlangeNode extends Node implements DlangeNode {
         @Override
         @TruffleBoundary
         public double execute(char norm, int m, int n, double[] a, int lda, double[] work) {
@@ -114,7 +115,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DgeconNode extends DgeconNode {
+    private static class JNI_DgeconNode extends Node implements DgeconNode {
         @Override
         @TruffleBoundary
         public int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
@@ -122,7 +123,7 @@ public class JNI_Lapack implements LapackRFFI {
         }
     }
 
-    private static class JNI_DsyevrNode extends DsyevrNode {
+    private static class JNI_DsyevrNode extends Node implements DsyevrNode {
         @Override
         public int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m,
                         double[] w, double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork) {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Misc.java
similarity index 81%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Misc.java
index 1e4ae3a4ac0ed422652785418e429c479ca48bc8..57cc3b98b7fe4d96b83224ef34d09ad7587d949b 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Misc.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Misc.java
@@ -20,17 +20,18 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceDownCallReturn;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceEnabled;
 
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
 
 public class JNI_Misc implements MiscRFFI {
 
-    private static class JNI_ExactSumNode extends ExactSumNode {
+    private static class JNI_ExactSumNode extends Node implements ExactSumNode {
         @Override
         public double execute(double[] values, boolean hasNa, boolean naRm) {
             if (traceEnabled()) {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_PCRE.java
similarity index 86%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_PCRE.java
index 069de23ca3290fa8b497893d6d2083b9b72cc8cf..6a5b359dce6ea904afd999f9d81521bbb4eec5f8 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PCRE.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_PCRE.java
@@ -20,29 +20,30 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 
 public class JNI_PCRE implements PCRERFFI {
-    private static class JNI_MaketablesNode extends MaketablesNode {
+    private static class JNI_MaketablesNode extends Node implements MaketablesNode {
         @Override
         public long execute() {
             return nativeMaketables();
         }
     }
 
-    private static class JNI_CompileNode extends CompileNode {
+    private static class JNI_CompileNode extends Node implements CompileNode {
         @Override
         public Result execute(String pattern, int options, long tables) {
             return nativeCompile(pattern, options, tables);
         }
     }
 
-    private static class JNI_GetCaptureCountNode extends GetCaptureCountNode {
+    private static class JNI_GetCaptureCountNode extends Node implements GetCaptureCountNode {
         @Override
         public int execute(long code, long extra) {
             int res = nativeGetCaptureCount(code, extra);
@@ -54,7 +55,7 @@ public class JNI_PCRE implements PCRERFFI {
         }
     }
 
-    private static class JNI_GetCaptureNamesNode extends GetCaptureNamesNode {
+    private static class JNI_GetCaptureNamesNode extends Node implements GetCaptureNamesNode {
         @Override
         public String[] execute(long code, long extra, int captureCount) {
             String[] ret = new String[captureCount];
@@ -67,14 +68,14 @@ public class JNI_PCRE implements PCRERFFI {
         }
     }
 
-    private static class JNI_StudyNode extends StudyNode {
+    private static class JNI_StudyNode extends Node implements StudyNode {
         @Override
         public Result execute(long code, int options) {
             throw RInternalError.unimplemented("pcre_study");
         }
     }
 
-    private static class JNI_ExecNode extends ExecNode {
+    private static class JNI_ExecNode extends Node implements ExecNode {
         @Override
         public int execute(long code, long extra, String subject, int offset, int options, int[] ovector) {
             return nativeExec(code, extra, subject, offset, options, ovector, ovector.length);
@@ -121,5 +122,4 @@ public class JNI_PCRE implements PCRERFFI {
     public ExecNode createExecNode() {
         return new JNI_ExecNode();
     }
-
 }
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.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_PkgInit.java
similarity index 86%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_PkgInit.java
index 2bd8a296eeb095541668b31897819c0036e5dc28..008a440d29686efb3fad1adea68b1b04ad3c0f4d 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_PkgInit.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -45,12 +45,12 @@ final class JNI_PkgInit {
     }
 
     private static void registerCCallable(String pkgName, String functionName, long address) {
-        DLLInfo lib = safeFindLibrary(pkgName);
+        DLLInfo lib = DLL.safeFindLibrary(pkgName);
         lib.registerCEntry(new CEntry(functionName, new SymbolHandle(address)));
     }
 
     public static long getCCallable(String pkgName, String functionName) {
-        DLLInfo lib = safeFindLibrary(pkgName);
+        DLLInfo lib = DLL.safeFindLibrary(pkgName);
         CEntry result = lib.lookupCEntry(functionName);
         if (result == null) {
             throw RError.error(RError.NO_CALLER, Message.UNKNOWN_OBJECT, functionName);
@@ -83,14 +83,4 @@ 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.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_RAppl.java
similarity index 54%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_RAppl.java
index bf64d0c96dab3d70eb3820c4d6a6c83d7646413f..a641c2d3411846ea7c71444b7a4e4f174cd0bc96 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RAppl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_RAppl.java
@@ -20,13 +20,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
 
 public class JNI_RAppl implements RApplRFFI {
-    private static class JNI_Dqrdc2Node extends Dqrdc2Node {
+    private static class JNI_Dqrdc2Node extends Node implements Dqrdc2Node {
         @Override
         @TruffleBoundary
         public void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
@@ -34,7 +35,7 @@ public class JNI_RAppl implements RApplRFFI {
         }
     }
 
-    private static class JNI_DqrcfNode extends DqrcfNode {
+    private static class JNI_DqrcfNode extends Node implements DqrcfNode {
 
         @Override
         @TruffleBoundary
@@ -43,7 +44,7 @@ public class JNI_RAppl implements RApplRFFI {
         }
     }
 
-    private static class JNI_DqrlsNode extends DqrlsNode {
+    private static class JNI_DqrlsNode extends Node implements DqrlsNode {
         @Override
         @TruffleBoundary
         public void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
@@ -51,6 +52,38 @@ public class JNI_RAppl implements RApplRFFI {
         }
     }
 
+    private static class JNI_DqrqtyNode extends Node implements DqrqtyNode {
+        @Override
+        @TruffleBoundary
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] qty) {
+            native_dqrqty(x, n, k, qraux, y, ny, qty);
+        }
+    }
+
+    private static class JNI_DqrqyNode extends Node implements DqrqyNode {
+        @Override
+        @TruffleBoundary
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] qy) {
+            native_dqrqy(x, n, k, qraux, y, ny, qy);
+        }
+    }
+
+    private static class JNI_DqrrsdNode extends Node implements DqrrsdNode {
+        @Override
+        @TruffleBoundary
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] rsd) {
+            native_dqrrsd(x, n, k, qraux, y, ny, rsd);
+        }
+    }
+
+    private static class JNI_DqrxbNode extends Node implements DqrxbNode {
+        @Override
+        @TruffleBoundary
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] xb) {
+            native_dqrxb(x, n, k, qraux, y, ny, xb);
+        }
+    }
+
     @Override
     public Dqrdc2Node createDqrdc2Node() {
         return new JNI_Dqrdc2Node();
@@ -66,6 +99,26 @@ public class JNI_RAppl implements RApplRFFI {
         return new JNI_DqrlsNode();
     }
 
+    @Override
+    public DqrqtyNode createDqrqtyNode() {
+        return new JNI_DqrqtyNode();
+    }
+
+    @Override
+    public DqrqyNode createDqrqyNode() {
+        return new JNI_DqrqyNode();
+    }
+
+    @Override
+    public DqrrsdNode createDqrrsdNode() {
+        return new JNI_DqrrsdNode();
+    }
+
+    @Override
+    public DqrxbNode createDqrxbNode() {
+        return new JNI_DqrxbNode();
+    }
+
     // Checkstyle: stop method name
 
     private static native void native_dqrdc2(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work);
@@ -74,4 +127,11 @@ public class JNI_RAppl implements RApplRFFI {
 
     private static native void native_dqrls(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work);
 
+    private static native void native_dqrqty(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] qty);
+
+    private static native void native_dqrqy(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] qy);
+
+    private static native void native_dqrrsd(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] rsd);
+
+    private static native void native_dqrxb(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] xb);
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_REmbed.java
similarity index 94%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_REmbed.java
index bf44eeafa0cc61566f58ebb97d8bfb6340bcdc68..2837227abd626d9e932150a91c5e990ef4653669 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_REmbed.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_REmbed.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
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
 
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_RFFIFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_RFFIFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..65b89a043a15c476fe69f3a099a52da511e3cf7e
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_RFFIFactory.java
@@ -0,0 +1,233 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.jni;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.r.ffi.impl.common.Generic_Tools;
+import com.oracle.truffle.r.ffi.impl.common.LibPaths;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+
+/**
+ * JNI-based factory. The majority of the FFI instances are instantiated on demand.
+ */
+public class JNI_RFFIFactory extends RFFIFactory {
+
+    private static class ContextStateImpl implements RContext.ContextState {
+        @Override
+        /**
+         * For the initial context, load the {@code libR} library. N.B. this library defines some
+         * non-JNI global symbols that are referenced by C code in R packages. Unfortunately,
+         * {@link System#load(String)} uses {@code RTLD_LOCAL} with {@code dlopen}, so we have to
+         * load the library manually and set {@code RTLD_GLOBAL}. However, a {@code dlopen} does not
+         * hook the JNI functions into the JVM, so we have to do an additional {@code System.load}
+         * to achieve that.
+         *
+         * Before we do that we must load {@code libjniboot} because the implementation of
+         * {@link DLLRFFI.DLLRFFINode#dlopen} is called by {@link DLL#loadLibR} which uses JNI!
+         */
+        public ContextState initialize(RContext context) {
+            if (context.isInitial()) {
+                String libjnibootPath = LibPaths.getBuiltinLibPath("jniboot");
+                System.load(libjnibootPath);
+
+                String librffiPath = LibPaths.getBuiltinLibPath("R");
+                DLL.loadLibR(librffiPath);
+                System.load(librffiPath);
+            }
+            return this;
+        }
+    }
+
+    @Override
+    public ContextState newContextState() {
+        return new ContextStateImpl();
+    }
+
+    @Override
+    protected RFFI createRFFI() {
+        CompilerAsserts.neverPartOfCompilation();
+        return new RFFI() {
+
+            @CompilationFinal private BaseRFFI baseRFFI;
+
+            @Override
+            public BaseRFFI getBaseRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (baseRFFI == null) {
+                    baseRFFI = new JNI_Base();
+                }
+                return baseRFFI;
+            }
+
+            @CompilationFinal private LapackRFFI lapackRFFI;
+
+            @Override
+            public LapackRFFI getLapackRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (lapackRFFI == null) {
+                    lapackRFFI = new JNI_Lapack();
+                }
+                return lapackRFFI;
+            }
+
+            @CompilationFinal private RApplRFFI rApplRFFI;
+
+            @Override
+            public RApplRFFI getRApplRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (rApplRFFI == null) {
+                    rApplRFFI = new JNI_RAppl();
+                }
+                return rApplRFFI;
+            }
+
+            @CompilationFinal private StatsRFFI statsRFFI;
+
+            @Override
+            public StatsRFFI getStatsRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (statsRFFI == null) {
+                    statsRFFI = new JNI_Stats();
+                }
+                return statsRFFI;
+            }
+
+            @CompilationFinal private ToolsRFFI toolsRFFI;
+
+            @Override
+            public ToolsRFFI getToolsRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (toolsRFFI == null) {
+                    toolsRFFI = new Generic_Tools();
+                }
+                return toolsRFFI;
+            }
+
+            @CompilationFinal private UserRngRFFI userRngRFFI;
+
+            @Override
+            public UserRngRFFI getUserRngRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (userRngRFFI == null) {
+                    userRngRFFI = new JNI_UserRng();
+                }
+                return userRngRFFI;
+            }
+
+            @CompilationFinal private CRFFI cRFFI;
+
+            @Override
+            public CRFFI getCRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (cRFFI == null) {
+                    cRFFI = new JNI_C();
+                }
+                return cRFFI;
+            }
+
+            @CompilationFinal private CallRFFI callRFFI;
+
+            @Override
+            public CallRFFI getCallRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (callRFFI == null) {
+                    callRFFI = new JNI_Call();
+                }
+                return callRFFI;
+            }
+
+            @CompilationFinal private ZipRFFI zipRFFI;
+
+            @Override
+            public ZipRFFI getZipRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (zipRFFI == null) {
+                    zipRFFI = new JNI_Zip();
+                }
+                return zipRFFI;
+            }
+
+            @CompilationFinal private PCRERFFI pcreRFFI;
+
+            @Override
+            public PCRERFFI getPCRERFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (pcreRFFI == null) {
+                    pcreRFFI = new JNI_PCRE();
+                }
+                return pcreRFFI;
+            }
+
+            private DLLRFFI dllRFFI;
+
+            @Override
+            public DLLRFFI getDLLRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (dllRFFI == null) {
+                    dllRFFI = new JNI_DLL();
+                }
+                return dllRFFI;
+            }
+
+            private REmbedRFFI rEmbedRFFI;
+
+            @Override
+            public REmbedRFFI getREmbedRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (rEmbedRFFI == null) {
+                    rEmbedRFFI = new JNI_REmbed();
+                }
+                return rEmbedRFFI;
+            }
+
+            private MiscRFFI miscRFFI;
+
+            @Override
+            public MiscRFFI getMiscRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (miscRFFI == null) {
+                    miscRFFI = new JNI_Misc();
+                }
+                return miscRFFI;
+            }
+        };
+    }
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Stats.java
similarity index 88%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Stats.java
index 49ab14598462af4ad3aa27a9b847d5e78a8cc2ab..b9c0ee7e1d74ff714197b68791a2b4f1a65dcb21 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Stats.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Stats.java
@@ -20,9 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
@@ -33,9 +34,9 @@ import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
 
 public class JNI_Stats implements StatsRFFI {
 
-    public static class JNI_WorkNode extends WorkNode {
+    private static class JNI_WorkNode extends Node implements WorkNode {
         private static final String FFT_WORK = "fft_work";
-        @Child DLLRFFI.DLSymNode dlSymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
+        @Child private DLLRFFI.DLSymNode dlSymNode = RFFIFactory.getDLLRFFI().createDLSymNode();
         private SymbolHandle fftWorkAddress;
 
         @Override
@@ -48,9 +49,9 @@ public class JNI_Stats implements StatsRFFI {
         }
     }
 
-    public static class JNI_FactorNode extends FactorNode {
+    private static class JNI_FactorNode extends Node implements FactorNode {
         private static final String FFT_FACTOR = "fft_factor";
-        @Child DLLRFFI.DLSymNode dlSymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
+        @Child private DLLRFFI.DLSymNode dlSymNode = RFFIFactory.getDLLRFFI().createDLSymNode();
         private SymbolHandle fftFactorAddress;
 
         @Override
@@ -62,7 +63,6 @@ public class JNI_Stats implements StatsRFFI {
             native_fft_factor(fftFactorAddress.asAddress(), n, pmaxf, pmaxp);
 
         }
-
     }
 
     private static SymbolHandle fftAddress(String symbol, DLLRFFI.DLSymNode dlSymNode) {
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_UserRng.java
similarity index 67%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_UserRng.java
index 038ddc5ae739e2ef05ca140f95c14e45d1326f2b..b3ab9dd00af9ffbf479e8b002f09abd18771746d 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UserRng.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_UserRng.java
@@ -20,43 +20,64 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
 import com.oracle.truffle.r.runtime.rng.user.UserRNG.Function;
 
 public class JNI_UserRng implements UserRngRFFI {
-    private static class JNI_UserRngRFFINode extends UserRngRFFINode {
+
+    private static final class JNI_InitNode extends Node implements InitNode {
+
         @Override
-        @TruffleBoundary
-        public void init(int seed) {
+        public void execute(int seed) {
             nativeInit(Function.Init.getSymbolHandle().asAddress(), seed);
-
         }
+    }
+
+    private static final class JNI_RandNode extends Node implements RandNode {
 
         @Override
-        @TruffleBoundary
-        public double rand() {
+        public double execute() {
             return nativeRand(Function.Rand.getSymbolHandle().asAddress());
         }
+    }
+
+    private static final class JNI_NSeedNode extends Node implements NSeedNode {
 
         @Override
-        @TruffleBoundary
-        public int nSeed() {
+        public int execute() {
             return nativeNSeed(Function.NSeed.getSymbolHandle().asAddress());
         }
+    }
+
+    private static final class JNI_SeedsNode extends Node implements SeedsNode {
 
         @Override
-        @TruffleBoundary
-        public void seeds(int[] n) {
+        public void execute(int[] n) {
             nativeSeeds(Function.Seedloc.getSymbolHandle().asAddress(), n);
         }
     }
 
     @Override
-    public UserRngRFFINode createUserRngRFFINode() {
-        return new JNI_UserRngRFFINode();
+    public InitNode createInitNode() {
+        return new JNI_InitNode();
+    }
+
+    @Override
+    public RandNode createRandNode() {
+        return new JNI_RandNode();
+    }
+
+    @Override
+    public NSeedNode createNSeedNode() {
+        return new JNI_NSeedNode();
+    }
+
+    @Override
+    public SeedsNode createSeedsNode() {
+        return new JNI_SeedsNode();
     }
 
     private static native void nativeInit(long address, int seed);
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_UtsName.java
similarity index 94%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_UtsName.java
index 51151f9636943de72ec687c4303790d86b5cbc48..fbdd602e975cd4fefe324562f19a17f91cb0bd2e 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_UtsName.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_UtsName.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
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName;
 
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Zip.java
similarity index 89%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Zip.java
index 7c93d004beeb22c062767dde7627518ee6c517b9..28de1e5ac7129b1064285bdb3dc551b32add060c 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_Zip.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/JNI_Zip.java
@@ -20,9 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.jni;
+package com.oracle.truffle.r.ffi.impl.jni;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
 
 /**
@@ -30,7 +31,7 @@ import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
  */
 public class JNI_Zip implements ZipRFFI {
 
-    public static class JNI_CompressNode extends ZipRFFI.CompressNode {
+    private static class JNI_CompressNode extends Node implements ZipRFFI.CompressNode {
         @Override
         @TruffleBoundary
         public int execute(byte[] dest, byte[] source) {
@@ -39,7 +40,7 @@ public class JNI_Zip implements ZipRFFI {
         }
     }
 
-    public static class JNI_UncompressNode extends ZipRFFI.UncompressNode {
+    private static class JNI_UncompressNode extends Node implements ZipRFFI.UncompressNode {
         @Override
         @TruffleBoundary
         public int execute(byte[] dest, byte[] source) {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..841d7f3c65e351fe4d854743b535af1a758e2e75
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/jni/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/**
+ * The JNI implementation of the {@link com.oracle.truffle.r.runtime.ffi.RFFI} interfaces.
+ */
+package com.oracle.truffle.r.ffi.impl.jni;
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/LLVMFunction.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/LLVMFunction.java
new file mode 100644
index 0000000000000000000000000000000000000000..64a348261062e442a2af2d9eb78b49d6c16596f5
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/LLVMFunction.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.llvm;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.common.NativeFunction;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+
+/**
+ * Enumerates all the C functions that are internal to the implementation and called via Truffle
+ * LLVM. All of the functions are called indirectly via a wrapper, typically to enable a callback
+ * with a complex result or, in the case of Fortran, to handle call by reference conveniently, or to
+ * just have LLVM handle the underlying native call. The wrapper functions names are all of the form
+ * {@code call_xxx_function}, where {@code xxx} is the subsystem.
+ */
+public enum LLVMFunction implements NativeFunction {
+    // base
+    getpid(0, "call_base_"),
+    getwd(2, "call_base_"),
+    setwd(1, "call_base_"),
+    mkdir(2, "call_base_"),
+    readlink(2, "call_base_"),
+    mkdtemp(1, "call_base_"),
+    chmod(2, "call_base_"),
+    strtol(3, "call_base_"),
+    uname(1, "call_base_"),
+    glob(2, "call_base_"),
+    // PCRE
+    maketables(0, "call_pcre_"),
+    compile(4, "call_pcre_"),
+    getcapturecount(2, "call_pcre_"),
+    getcapturenames(3, "call_pcre_"),
+    study(2, "call_pcre_"),
+    exec(8, "call_pcre_"),
+    // RAppl
+    dqrdc2(9, "call_appl_"),
+    dqrcf(8, "call_appl_"),
+    dqrls(13, "call_appl_"),
+    // zip
+    compress(4, "call_zip_"),
+    uncompress(4, "call_zip_"),
+    // lapack
+    ilaver(1, "call_lapack_"),
+    dgeev(13, "call_lapack_"),
+    dgeqp3(8, "call_lapack_"),
+    dormq(12, "call_lapack_"),
+    dtrtrs(9, "call_lapack_"),
+    dgetrf(5, "call_lapack_"),
+    dpotrf(4, "call_lapack_"),
+    dpotri(4, "call_lapack_"),
+    dpstrf(9, "call_lapack_"),
+    dgesv(7, "call_lapack_"),
+    dlange(6, "call_lapack_"),
+    dgecon(8, "call_lapack_"),
+    dsyevr(20, "call_lapack_"),
+    // misc
+    exactSumFunc(4, "");
+
+    private final int argumentCount;
+    private final String callName;
+
+    LLVMFunction(int argCount, String prefix) {
+        this.argumentCount = argCount;
+        this.callName = prefix + name();
+    }
+
+    Node createMessage() {
+        CompilerAsserts.neverPartOfCompilation();
+        return Message.createExecute(argumentCount).createNode();
+    }
+
+    SymbolHandle createSymbol() {
+        return DLL.findSymbol(callName, null);
+    }
+
+    @Override
+    public int getArgumentCount() {
+        return argumentCount;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/truffle/LLVM_IR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/LLVM_IR.java
similarity index 62%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/truffle/LLVM_IR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/LLVM_IR.java
index 89f9b2f3aab13c58e63ddbc6b6add8b7ea37fff6..9d06c1fa54ecc163a3e2e44c121bb31d987bbf6a 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/truffle/LLVM_IR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/LLVM_IR.java
@@ -20,13 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.truffle;
+package com.oracle.truffle.r.ffi.impl.llvm;
 
-import java.io.IOException;
 import java.util.Base64;
 
-import com.oracle.truffle.r.runtime.RInternalError;
-
 public abstract class LLVM_IR {
     public static final int TEXT_CODE = 1;
     public static final int BINARY_CODE = 2;
@@ -35,19 +32,9 @@ public abstract class LLVM_IR {
      * The name of the "module", aka object file, that the IR pertains to.
      */
     public final String name;
-    /**
-     * List of exported symbols.
-     */
-    public final String[] exports;
-    /**
-     * List of imported symbols.
-     */
-    public final String[] imports;
 
-    protected LLVM_IR(String name, String[] exports, String[] imports) {
+    protected LLVM_IR(String name) {
         this.name = name;
-        this.exports = exports;
-        this.imports = imports;
     }
 
     @Override
@@ -61,8 +48,8 @@ public abstract class LLVM_IR {
     public static final class Text extends LLVM_IR {
         public final String text;
 
-        public Text(String name, String text, String[] exports, String[] imports) {
-            super(name, exports, imports);
+        public Text(String name, String text) {
+            super(name);
             this.text = text;
         }
     }
@@ -74,23 +61,10 @@ public abstract class LLVM_IR {
         public final byte[] binary;
         public final String base64;
 
-        public Binary(String name, byte[] binary, String[] exports, String[] imports) {
-            super(name, exports, imports);
+        public Binary(String name, byte[] binary) {
+            super(name);
             this.binary = binary;
             base64 = Base64.getEncoder().encodeToString(binary);
         }
     }
-
-    /**
-     * Return an array of {@link LLVM_IR} instances contained in the library denoted by {@code path}
-     * .
-     */
-    public static LLVM_IR[] getLLVMIR(String path) throws IOException {
-        String os = System.getProperty("os.name");
-        if (os.contains("Mac OS")) {
-            return MachOAccess.getLLVMIR(path);
-        } else {
-            throw RInternalError.unimplemented("LLVM_IR_Access for Linux");
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java
new file mode 100644
index 0000000000000000000000000000000000000000..f5edb934b7590372d586ad7d3c34880daf584761
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Base.java
@@ -0,0 +1,274 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import com.oracle.truffle.r.ffi.impl.interop.NativeCharArray;
+import com.oracle.truffle.r.ffi.impl.interop.base.GlobResult;
+import com.oracle.truffle.r.ffi.impl.interop.base.ReadlinkResult;
+import com.oracle.truffle.r.ffi.impl.interop.base.StrtolResult;
+import com.oracle.truffle.r.ffi.impl.interop.base.UnameResult;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+
+public class TruffleLLVM_Base implements BaseRFFI {
+    private static final class TruffleLLVM_GetpidNode extends TruffleLLVM_DownCallNode implements GetpidNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.getpid;
+        }
+
+        @Override
+        public int execute() {
+            return (int) call();
+        }
+    }
+
+    private static class TruffleLLVM_GetwdNode extends TruffleLLVM_DownCallNode implements GetwdNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.getwd;
+        }
+
+        @Override
+        public String execute() {
+            byte[] buf = new byte[4096];
+            NativeCharArray nativeBuf = new NativeCharArray(buf);
+            int result = (int) call(nativeBuf, buf.length);
+            if (result == 0) {
+                return null;
+            } else {
+                byte[] mbuf = nativeBuf.getValue();
+                int i = 0;
+                while (mbuf[i] != 0 && i < mbuf.length) {
+                    i++;
+                }
+                return new String(mbuf, 0, i);
+            }
+        }
+    }
+
+    private static class TruffleLLVM_SetwdNode extends TruffleLLVM_DownCallNode implements SetwdNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.setwd;
+        }
+
+        @Override
+        public int execute(String dir) {
+            NativeCharArray nativeBuf = new NativeCharArray(dir.getBytes());
+            return (int) call(nativeBuf);
+        }
+    }
+
+    private static class TruffleLLVM_MkdirNode extends TruffleLLVM_DownCallNode implements MkdirNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.mkdir;
+        }
+
+        @Override
+        public void execute(String dir, int mode) throws IOException {
+            NativeCharArray nativeBuf = new NativeCharArray(dir.getBytes());
+            int result = (int) call(nativeBuf, mode);
+            if (result != 0) {
+                throw new IOException("mkdir " + dir + " failed");
+            }
+        }
+    }
+
+    private static class TruffleLLVM_ReadlinkNode extends TruffleLLVM_DownCallNode implements ReadlinkNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.readlink;
+        }
+
+        private static final int EINVAL = 22;
+
+        @Override
+        public String execute(String path) throws IOException {
+            NativeCharArray nativePath = new NativeCharArray(path.getBytes());
+            ReadlinkResult callback = new ReadlinkResult();
+            call(callback, nativePath);
+            String link = callback.getLink();
+            if (link == null) {
+                if (callback.getErrno() == EINVAL) {
+                    return path;
+                } else {
+                    // some other error
+                    throw new IOException("readlink failed: " + callback.getErrno());
+                }
+            }
+            return link;
+        }
+    }
+
+    private static class TruffleLLVM_MkdtempNode extends TruffleLLVM_DownCallNode implements MkdtempNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.mkdtemp;
+        }
+
+        @Override
+        public String execute(String template) {
+            /*
+             * Not only must the (C) string end in XXXXXX it must also be null-terminated. Since it
+             * is modified by mkdtemp we must make a copy.
+             */
+            byte[] bytes = template.getBytes();
+            byte[] ztbytes = new byte[bytes.length + 1];
+            System.arraycopy(bytes, 0, ztbytes, 0, bytes.length);
+            ztbytes[bytes.length] = 0;
+            NativeCharArray nativeZtbytes = new NativeCharArray(ztbytes);
+            int result = (int) call(nativeZtbytes);
+            if (result == 0) {
+                return null;
+            } else {
+                byte[] mztBytes = nativeZtbytes.getValue();
+                return new String(mztBytes, 0, bytes.length);
+            }
+        }
+    }
+
+    private static class TruffleLLVM_ChmodNode extends TruffleLLVM_DownCallNode implements ChmodNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.chmod;
+        }
+
+        @Override
+        public int execute(String path, int mode) {
+            NativeCharArray nativePath = new NativeCharArray(path.getBytes());
+            return (int) call(nativePath, mode);
+        }
+    }
+
+    private static class TruffleLLVM_StrolNode extends TruffleLLVM_DownCallNode implements StrolNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.strtol;
+        }
+
+        @Override
+        public long execute(String s, int base) throws IllegalArgumentException {
+            NativeCharArray nativeString = new NativeCharArray(s.getBytes());
+            StrtolResult callback = new StrtolResult();
+            call(callback, nativeString, base);
+            if (callback.getErrno() != 0) {
+                throw new IllegalArgumentException("strtol failure");
+            } else {
+                return callback.getResult();
+            }
+        }
+    }
+
+    private static class TruffleLLVM_UnameNode extends TruffleLLVM_DownCallNode implements UnameNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.uname;
+        }
+
+        @Override
+        public UtsName execute() {
+            UnameResult baseUnameResultCallback = new UnameResult();
+            call(baseUnameResultCallback);
+            return baseUnameResultCallback;
+        }
+    }
+
+    private static class TruffleLLVM_GlobNode extends TruffleLLVM_DownCallNode implements GlobNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.glob;
+        }
+
+        @Override
+        public ArrayList<String> glob(String pattern) {
+            NativeCharArray nativePattern = new NativeCharArray(pattern.getBytes());
+            GlobResult baseGlobResultCallback = new GlobResult();
+            call(baseGlobResultCallback, nativePattern);
+            return baseGlobResultCallback.getPaths();
+        }
+    }
+
+    @Override
+    public GetpidNode createGetpidNode() {
+        return new TruffleLLVM_GetpidNode();
+    }
+
+    @Override
+    public GetwdNode createGetwdNode() {
+        return new TruffleLLVM_GetwdNode();
+    }
+
+    @Override
+    public SetwdNode createSetwdNode() {
+        return new TruffleLLVM_SetwdNode();
+    }
+
+    @Override
+    public MkdirNode createMkdirNode() {
+        return new TruffleLLVM_MkdirNode();
+    }
+
+    @Override
+    public ReadlinkNode createReadlinkNode() {
+        return new TruffleLLVM_ReadlinkNode();
+    }
+
+    @Override
+    public MkdtempNode createMkdtempNode() {
+        return new TruffleLLVM_MkdtempNode();
+    }
+
+    @Override
+    public ChmodNode createChmodNode() {
+        return new TruffleLLVM_ChmodNode();
+    }
+
+    @Override
+    public StrolNode createStrolNode() {
+        return new TruffleLLVM_StrolNode();
+    }
+
+    @Override
+    public UnameNode createUnameNode() {
+        return new TruffleLLVM_UnameNode();
+    }
+
+    @Override
+    public GlobNode createGlobNode() {
+        return new TruffleLLVM_GlobNode();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_C.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_C.java
similarity index 68%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_C.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_C.java
index 89fb551c08e14b756f3e1b8d847d3093aee06dc7..b6ee57ebda72247b1c49aa79ea353eadfa6abea9 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_C.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_C.java
@@ -20,35 +20,39 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.llvm;
+package com.oracle.truffle.r.ffi.impl.llvm;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.interop.NativeDoubleArray;
-import com.oracle.truffle.r.engine.interop.NativeIntegerArray;
-import com.oracle.truffle.r.engine.interop.NativeRawArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeDoubleArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeIntegerArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeRawArray;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
-import com.oracle.truffle.r.runtime.ffi.jni.JNI_C.JNI_InvokeCNode;
 
 class TruffleLLVM_C implements CRFFI {
-    private static class TruffleLLVM_InvokeCNode extends JNI_InvokeCNode {
+    private static class TruffleLLVM_InvokeCNode extends Node implements InvokeCNode {
+
+        @Child private Node messageNode;
+        private int numArgs;
 
         @Override
-        public synchronized void execute(NativeCallInfo nativeCallInfo, Object[] args) {
-            if (nativeCallInfo.address.value instanceof Long) {
-                super.execute(nativeCallInfo, args);
-            } else {
-                TruffleLLVM_DLL.ensureParsed(nativeCallInfo);
-                Object[] wargs = wrap(args);
-                try {
-                    Node messageNode = Message.createExecute(0).createNode();
-                    ForeignAccess.sendExecute(messageNode, nativeCallInfo.address.asTruffleObject(), wargs);
-                } catch (Throwable t) {
-                    throw RInternalError.shouldNotReachHere(t);
+        public synchronized void execute(NativeCallInfo nativeCallInfo, Object[] args, boolean hasStrings) {
+            Object[] wargs = wrap(args);
+            try {
+                if (messageNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    // TODO: we assume that the number of args doesn't change, is that correct?
+                    messageNode = Message.createExecute(args.length).createNode();
+                    numArgs = args.length;
                 }
+                assert numArgs == args.length;
+                ForeignAccess.sendExecute(messageNode, nativeCallInfo.address.asTruffleObject(), wargs);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere(t);
             }
         }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_CAccess.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_CAccess.java
similarity index 95%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_CAccess.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_CAccess.java
index 16f57a750e1f42de0a24077faf6f9109547ed6ad..50e1d83d9010edbed0b4c509eff6974d1c081ab7 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_CAccess.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_CAccess.java
@@ -20,11 +20,11 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.llvm;
+package com.oracle.truffle.r.ffi.impl.llvm;
 
+import com.oracle.truffle.r.ffi.impl.jni.JNI_DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.jni.JNI_DLL;
 import com.oracle.truffle.r.runtime.rng.user.UserRNG;
 
 /**
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java
new file mode 100644
index 0000000000000000000000000000000000000000..42d3e293c6d2bfacf3ca147241961a59faf19293
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Call.java
@@ -0,0 +1,279 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+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.ImportStatic;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.ExplodeLoop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
+import com.oracle.truffle.r.ffi.impl.common.UpCallUnwrap;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_CallFactory.ToNativeNodeGen;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_CallFactory.TruffleLLVM_InvokeCallNodeGen;
+import com.oracle.truffle.r.ffi.impl.llvm.upcalls.BytesToNativeCharArrayCall;
+import com.oracle.truffle.r.ffi.impl.llvm.upcalls.CharSXPToNativeArrayCall;
+import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks;
+import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RScalar;
+import com.oracle.truffle.r.runtime.data.RVector;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
+
+final class TruffleLLVM_Call implements CallRFFI {
+    private static UpCallsRFFI upCallsRFFI;
+    private static TruffleLLVM_UpCallsRFFIImpl upCallsRFFIImpl;
+
+    TruffleLLVM_Call() {
+        upCallsRFFIImpl = new TruffleLLVM_UpCallsRFFIImpl();
+        upCallsRFFI = RFFIUtils.initialize(upCallsRFFIImpl);
+    }
+
+    static class ContextStateImpl implements RContext.ContextState {
+        private RContext context;
+        private boolean initDone;
+
+        @Override
+        public ContextState initialize(RContext contextA) {
+            this.context = contextA;
+            RFFIFactory.getCallRFFI();
+            if (!initDone) {
+                initVariables(context);
+                initCallbacks(context, upCallsRFFI);
+                initDone = true;
+            }
+            return this;
+        }
+    }
+
+    private enum INIT_VAR_FUN {
+        DOUBLE,
+        INT,
+        OBJ;
+
+        private final String funName;
+        private SymbolHandle symbolHandle;
+
+        INIT_VAR_FUN() {
+            funName = "Call_initvar_" + name().toLowerCase();
+        }
+    }
+
+    private static void initVariables(RContext context) {
+        // must have parsed the variables module in libR
+        for (INIT_VAR_FUN initVarFun : INIT_VAR_FUN.values()) {
+            initVarFun.symbolHandle = new SymbolHandle(context.getEnv().importSymbol("@" + initVarFun.funName));
+        }
+        Node executeNode = Message.createExecute(2).createNode();
+        RFFIVariables[] variables = RFFIVariables.initialize();
+        boolean isNullSetting = RContext.getRForeignAccessFactory().setIsNull(false);
+        try {
+            for (int i = 0; i < variables.length; i++) {
+                RFFIVariables var = variables[i];
+                Object value = var.getValue();
+                if (value == null) {
+                    continue;
+                }
+                try {
+                    if (value instanceof Double) {
+                        ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.DOUBLE.symbolHandle.asTruffleObject(), i, value);
+                    } else if (value instanceof Integer) {
+                        ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.INT.symbolHandle.asTruffleObject(), i, value);
+                    } else if (value instanceof TruffleObject) {
+                        ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.OBJ.symbolHandle.asTruffleObject(), i, value);
+                    }
+                } catch (Throwable t) {
+                    throw RInternalError.shouldNotReachHere(t);
+                }
+            }
+        } finally {
+            RContext.getRForeignAccessFactory().setIsNull(isNullSetting);
+        }
+    }
+
+    private static void initCallbacks(RContext context, UpCallsRFFI upCallsImpl) {
+        Node executeNode = Message.createExecute(2).createNode();
+        SymbolHandle symbolHandle = new SymbolHandle(context.getEnv().importSymbol("@" + "Rinternals_addCallback"));
+
+        try {
+            // standard callbacks
+            Callbacks[] callbacks = Callbacks.values();
+            Callbacks.createCalls(upCallsImpl);
+            for (Callbacks callback : callbacks) {
+                ForeignAccess.sendExecute(executeNode, symbolHandle.asTruffleObject(), callback.ordinal(), callback.call);
+            }
+            // llvm specific callbacks
+            ForeignAccess.sendExecute(executeNode, symbolHandle.asTruffleObject(), callbacks.length, new BytesToNativeCharArrayCall(upCallsRFFIImpl));
+            ForeignAccess.sendExecute(executeNode, symbolHandle.asTruffleObject(), callbacks.length + 1, new CharSXPToNativeArrayCall(upCallsRFFIImpl));
+        } catch (Throwable t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+
+    abstract static class ToNativeNode extends Node {
+
+        public abstract Object execute(Object value);
+
+        @Specialization
+        protected static Object convert(int value) {
+            return RDataFactory.createIntVector(new int[]{value}, RRuntime.isNA(value));
+        }
+
+        @Specialization
+        protected static Object convert(double value) {
+            return RDataFactory.createDoubleVector(new double[]{value}, RRuntime.isNA(value));
+        }
+
+        @Specialization
+        protected static Object convert(RVector<?> value) {
+            return value;
+        }
+
+        @Specialization
+        protected static Object convert(RScalar value) {
+            return value;
+        }
+
+        @Specialization
+        protected static Object convert(byte value) {
+            return RDataFactory.createLogicalVector(new byte[]{value}, RRuntime.isNA(value));
+        }
+
+        @Specialization
+        protected static Object convert(String value) {
+            return RDataFactory.createStringVector(new String[]{value}, RRuntime.isNA(value));
+        }
+
+        @Fallback
+        protected static Object convert(Object value) {
+            return value;
+        }
+    }
+
+    @ImportStatic({Message.class})
+    abstract static class TruffleLLVM_InvokeCallNode extends Node implements InvokeCallNode {
+
+        @Child private UpCallUnwrap unwrap;
+        private final boolean isVoid;
+
+        protected TruffleLLVM_InvokeCallNode(boolean isVoid) {
+            this.isVoid = isVoid;
+            this.unwrap = isVoid ? null : new UpCallUnwrap();
+        }
+
+        protected static ToNativeNode[] createConvertNodes(int length) {
+            ToNativeNode[] result = new ToNativeNode[length];
+            for (int i = 0; i < length; i++) {
+                result[i] = ToNativeNodeGen.create();
+            }
+            return result;
+        }
+
+        @Specialization(guards = {"cachedNativeCallInfo.name.equals(nativeCallInfo.name)", "args.length == cachedArgCount"})
+        protected Object invokeCallCached(NativeCallInfo nativeCallInfo, Object[] args,
+                        @SuppressWarnings("unused") @Cached("nativeCallInfo") NativeCallInfo cachedNativeCallInfo,
+                        @SuppressWarnings("unused") @Cached("argCount(args)") int cachedArgCount,
+                        @Cached("createMessageNode(args)") Node cachedMessageNode,
+                        @Cached("createConvertNodes(cachedArgCount)") ToNativeNode[] convert) {
+            return doInvoke(cachedMessageNode, nativeCallInfo, args, convert);
+        }
+
+        @Specialization(replaces = "invokeCallCached")
+        @TruffleBoundary
+        protected Object invokeCallNormal(NativeCallInfo nativeCallInfo, Object[] args) {
+            return doInvoke(Message.createExecute(args.length).createNode(), nativeCallInfo, args, null);
+        }
+
+        @ExplodeLoop
+        private Object doInvoke(Node messageNode, NativeCallInfo nativeCallInfo, Object[] args, ToNativeNode[] convert) {
+            boolean isNullSetting = RContext.getRForeignAccessFactory().setIsNull(false);
+            try {
+                if (convert != null) {
+                    for (int i = 0; i < convert.length; i++) {
+                        args[i] = convert[i].execute(args[i]);
+                    }
+                }
+                Object result = ForeignAccess.sendExecute(messageNode, nativeCallInfo.address.asTruffleObject(), args);
+                if (!isVoid) {
+                    result = unwrap.unwrap(result);
+                }
+                return result;
+            } catch (InteropException t) {
+                throw RInternalError.shouldNotReachHere(t);
+            } finally {
+                RContext.getRForeignAccessFactory().setIsNull(isNullSetting);
+            }
+        }
+
+        public int argCount(Object[] args) {
+            return args.length;
+        }
+
+        public Node createMessageNode(Object[] args) {
+            return Message.createExecute(args.length).createNode();
+        }
+    }
+
+    private static class TruffleLLVM_InvokeVoidCallNode extends Node implements InvokeVoidCallNode {
+        @Child private TruffleLLVM_InvokeCallNode invokeCallNode = TruffleLLVM_InvokeCallNodeGen.create(true);
+
+        @Override
+        public synchronized void execute(NativeCallInfo nativeCallInfo, Object[] args) {
+            invokeCallNode.execute(nativeCallInfo, args);
+        }
+    }
+
+    /**
+     * Upcalled from Rinternal et al.
+     *
+     * @param function
+     */
+    @SuppressWarnings("static-method")
+    public void unimplemented(String function) {
+        throw RInternalError.unimplemented("RFFI function: '" + function + "' not implemented");
+    }
+
+    @Override
+    public InvokeCallNode createInvokeCallNode() {
+        return TruffleLLVM_InvokeCallNodeGen.create(false);
+    }
+
+    @Override
+    public InvokeVoidCallNode createInvokeVoidCallNode() {
+        return new TruffleLLVM_InvokeVoidCallNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java
new file mode 100644
index 0000000000000000000000000000000000000000..b27c82d307d6bdea341a81802cd04201b9ea3e02
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DLL.java
@@ -0,0 +1,285 @@
+/*
+ * 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.ffi.impl.llvm;
+
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import com.oracle.truffle.api.CallTarget;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+
+/**
+ * The Truffle version of {@link DLLRFFI}. {@code dlopen} expects to find the LLVM IR in a "library"
+ * that is actually a zip file of LLVM bitcode files.
+ *
+ * There is one major difference between native and LLVM libraries. There is a single global
+ * instance of a native library and the symbols are, therefore, accessible from any {@link RContext}
+ * instance . However, the (Truffle) function descriptors for an LLVM library are specific to the
+ * {@link RContext} they are created (parsed) in. This has two important consequences:
+ * <ol>
+ * <li>It is theoretically possible to have different versions of libraries in different contexts.
+ * </li>
+ * <li>The {@code libR} library function descriptors must be made available in every context. At the
+ * present time this can only be done by re-parsing the library contents.</li>
+ * </ol>
+ *
+ */
+public class TruffleLLVM_DLL implements DLLRFFI {
+    static class ContextStateImpl implements RContext.ContextState {
+        /**
+         * When a new {@link RContext} is created we have to re-parse the libR modules,
+         * unfortunately, as there is no way to propagate the LLVM state created in the initial
+         * context. TODO when do we really need to do this? This is certainly too early for contexts
+         * that will not invoke LLVM code (e.g. most unit tests)
+         */
+        @Override
+        public ContextState initialize(RContext context) {
+            if (!context.isInitial()) {
+                for (LLVM_IR ir : truffleDLL.libRModules) {
+                    parseLLVM("libR", ir);
+                }
+            }
+            if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
+                // must propagate all LLVM library exports
+                ArrayList<DLLInfo> loadedDLLs = DLL.getLoadedDLLs();
+                for (DLLInfo dllInfo : loadedDLLs) {
+                    if (dllInfo.handle instanceof LLVM_Handle) {
+                        LLVM_Handle llvmHandle = (LLVM_Handle) dllInfo.handle;
+                        for (LLVM_IR ir : llvmHandle.irs) {
+                            parseLLVM(llvmHandle.libName, ir);
+                        }
+                    }
+                }
+            }
+            return this;
+        }
+    }
+
+    private static TruffleLLVM_DLL truffleDLL;
+
+    TruffleLLVM_DLL() {
+        assert truffleDLL == null;
+        truffleDLL = this;
+    }
+
+    static ContextStateImpl newContextState() {
+        return new ContextStateImpl();
+    }
+
+    static class LLVM_Handle {
+        private final String libName;
+        private final LLVM_IR[] irs;
+
+        LLVM_Handle(String libName, LLVM_IR[] irs) {
+            this.libName = libName;
+            this.irs = irs;
+        }
+    }
+
+    @FunctionalInterface
+    interface ModuleNameMatch {
+        boolean match(String name);
+    }
+
+    public static LLVM_IR[] getZipLLVMIR(String path) {
+        try (ZipInputStream zis = new ZipInputStream(new BufferedInputStream(new FileInputStream(path)))) {
+            ArrayList<LLVM_IR> irList = new ArrayList<>();
+            while (true) {
+                ZipEntry entry = zis.getNextEntry();
+                if (entry == null) {
+                    break;
+                }
+                int size = (int) entry.getSize();
+                byte[] bc = new byte[size];
+                int n;
+                int totalRead = 0;
+                while (totalRead < size && (n = zis.read(bc, totalRead, size - totalRead)) != -1) {
+                    totalRead += n;
+                }
+                Path zipName = Paths.get(entry.getName());
+                String name = zipName.getFileName().toString();
+                int ix = name.indexOf('.');
+                if (ix > 0) {
+                    name = name.substring(0, ix);
+                }
+                LLVM_IR.Binary ir = new LLVM_IR.Binary(name, bc);
+                irList.add(ir);
+                // debugging
+                if (System.getenv("FASTR_LLVM_DEBUG") != null) {
+                    try (FileOutputStream bs = new FileOutputStream(Paths.get("tmpzip", name).toString())) {
+                        bs.write(bc);
+                    }
+                    try (PrintStream bs = new PrintStream(new FileOutputStream(Paths.get("tmpb64", name).toString()))) {
+                        bs.print(ir.base64);
+                    }
+                }
+            }
+            LLVM_IR[] result = new LLVM_IR[irList.size()];
+            irList.toArray(result);
+            return result;
+        } catch (IOException ex) {
+            // not a zip file
+            return null;
+        }
+    }
+
+    private static class TruffleLLVM_DLOpenNode extends Node implements DLOpenNode {
+        @Child private TruffleLLVM_NativeDLL.TruffleLLVM_NativeDLOpen nativeDLLOpenNode;
+
+        /**
+         * If a library is enabled for LLVM, the IR for all the modules is retrieved and analyzed.
+         * Every exported symbol in the module added to the parseStatus map for the current
+         * {@link RContext}. This allows {@code dlsym} to definitively locate any symbol, even if
+         * the IR has not been parsed yet.
+         */
+        @Override
+        public Object execute(String path, boolean local, boolean now) {
+            try {
+                LLVM_IR[] irs = getZipLLVMIR(path);
+                if (irs == null) {
+                    return tryOpenNative(path, local, now);
+                }
+                String libName = getLibName(path);
+                if (libName.equals("libR")) {
+                    // save for new RContexts
+                    truffleDLL.libRModules = irs;
+                }
+                for (LLVM_IR ir : irs) {
+                    parseLLVM(libName, ir);
+                }
+                return new LLVM_Handle(libName, irs);
+            } catch (
+
+            Exception ex) {
+                throw new UnsatisfiedLinkError(ex.getMessage());
+            }
+        }
+
+        private long tryOpenNative(String path, boolean local, boolean now) throws UnsatisfiedLinkError {
+            if (nativeDLLOpenNode == null) {
+                nativeDLLOpenNode = insert(new TruffleLLVM_NativeDLL.TruffleLLVM_NativeDLOpen());
+            }
+            return nativeDLLOpenNode.execute(path, local, now);
+        }
+    }
+
+    private static class TruffleLLVM_DLSymNode extends Node implements DLSymNode {
+        @Override
+        public SymbolHandle execute(Object handle, String symbol) throws UnsatisfiedLinkError {
+            assert handle instanceof LLVM_Handle;
+            Object symValue = RContext.getInstance().getEnv().importSymbol("@" + symbol);
+            if (symValue == null) {
+                throw new UnsatisfiedLinkError();
+            }
+            return new SymbolHandle(symValue);
+        }
+    }
+
+    private static class TruffleLLVM_DLCloseNode extends Node implements DLCloseNode {
+        @Override
+        public int execute(Object handle) {
+            assert handle instanceof LLVM_Handle;
+            return 0;
+        }
+    }
+
+    @Override
+    public DLOpenNode createDLOpenNode() {
+        return new TruffleLLVM_DLOpenNode();
+    }
+
+    @Override
+    public DLSymNode createDLSymNode() {
+        return new TruffleLLVM_DLSymNode();
+    }
+
+    @Override
+    public DLCloseNode createDLCloseNode() {
+        return new TruffleLLVM_DLCloseNode();
+    }
+
+    private static String getLibName(String path) {
+        String fileName = FileSystems.getDefault().getPath(path).getFileName().toString();
+        int ix = fileName.lastIndexOf(".");
+        return fileName.substring(0, ix);
+    }
+
+    /**
+     * Record of the libR modules for subsequent parsing.
+     */
+    private LLVM_IR[] libRModules;
+
+    private static final String[] PARSE_ERRORS = new String[0];
+
+    private static boolean parseFails(String libName, LLVM_IR ir) {
+        for (int i = 0; i < PARSE_ERRORS.length / 2; i++) {
+            String plibName = PARSE_ERRORS[i * 2];
+            String pModule = PARSE_ERRORS[i * 2 + 1];
+            if (libName.equals(plibName) && ir.name.equals(pModule)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private static void parseLLVM(String libName, LLVM_IR ir) {
+        if (ir instanceof LLVM_IR.Binary) {
+            LLVM_IR.Binary bir = (LLVM_IR.Binary) ir;
+            if (!parseFails(libName, ir)) {
+                parseBinary(libName, bir);
+            }
+        } else {
+            throw RInternalError.unimplemented("LLVM text IR");
+        }
+    }
+
+    private static CallTarget parseBinary(String libName, LLVM_IR.Binary ir) {
+        long start = System.nanoTime();
+        RContext context = RContext.getInstance();
+        long nanos = 1000 * 1000 * 1000;
+        Source source = Source.newBuilder(ir.base64).name(ir.name).mimeType("application/x-llvm-ir-bitcode-base64").build();
+        CallTarget result = context.getEnv().parse(source);
+        if (System.getenv("LLVM_PARSE_TIME") != null) {
+            long end = System.nanoTime();
+            System.out.printf("parsed %s:%s in %f secs%n", libName, ir.name, ((double) (end - start)) / (double) nanos);
+        }
+        return result;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc3b81c00cb05b966214040a9ee533152cb87969
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_DownCallNode.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.llvm;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.ExplodeLoop;
+import com.oracle.truffle.r.ffi.impl.common.DownCallNode;
+import com.oracle.truffle.r.ffi.impl.interop.NativeDoubleArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeIntegerArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeNACheck;
+
+public abstract class TruffleLLVM_DownCallNode extends DownCallNode<LLVMFunction> {
+
+    @CompilationFinal private TruffleObject target;
+
+    @Override
+    protected final TruffleObject getTarget() {
+        if (target == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            target = getFunction().createSymbol().asTruffleObject();
+        }
+        return target;
+    }
+
+    @Override
+    @ExplodeLoop
+    protected void wrapArguments(Object[] args) {
+        for (int i = 0; i < args.length; i++) {
+            Object obj = args[i];
+            if (obj instanceof double[]) {
+                args[i] = new NativeDoubleArray((double[]) obj);
+            } else if (obj instanceof int[]) {
+                args[i] = new NativeIntegerArray((int[]) obj);
+            } else if (obj == null) {
+                args[i] = 0;
+            }
+        }
+    }
+
+    @Override
+    @ExplodeLoop
+    protected void finishArguments(Object[] args) {
+        for (Object obj : args) {
+            if (obj instanceof NativeNACheck<?>) {
+                ((NativeNACheck<?>) obj).close();
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java
new file mode 100644
index 0000000000000000000000000000000000000000..0cc25fa7ab99e656715ce48d29a5cf9e8fe87759
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Lapack.java
@@ -0,0 +1,311 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.r.ffi.impl.common.LibPaths;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+
+/**
+ * When the embedded GNU R is built, LLVM is created for the components of the {@code libRblas} and
+ * {@code libRlapack} libraries. In principle we could call the subroutines direct but since,
+ * Fortran passes every argument by reference we would have to create many length 1 arrays to wrap
+ * the scalar arguments. So we call through a thing veneer in {@code lapack_rffi.c} that forwards
+ * the call taking the address of the scalar arguments. We also take the liberty of defining the
+ * {@code info} argument taken my most all if the functions in the veneer, and returning the value
+ * as the result of the call.
+ *
+ * N.B. The usual implicit loading of {@code libRlapack} and {@code libRblas} that we get with
+ * native {@code dlopen} via {@code libR} does not happen with LLVM, so we must force their loading
+ * when this API is requested.
+ *
+ */
+public class TruffleLLVM_Lapack implements LapackRFFI {
+
+    TruffleLLVM_Lapack() {
+        /*
+         * This is a workaround for bad LLVM generated by DragonEgg for (some) of the Lapack
+         * functions; additional spurious arguments. Unfortunately for this to be portable we would
+         * have to load libR natively to get the rpath support. This code is OS X specific and
+         * depends on specific versions.
+         */
+        RootCallTarget callTarget;
+        boolean useLLVM = System.getenv("FASTR_LLVM_LAPACK") != null;
+        if (useLLVM) {
+            callTarget = openLLVMLibraries();
+        } else {
+            callTarget = openNativeLibraries();
+            callTarget.call(LibPaths.getBuiltinLibPath("gcc_s.1"), false, true);
+            callTarget.call(LibPaths.getBuiltinLibPath("quadmath.0"), false, true);
+            callTarget.call(LibPaths.getBuiltinLibPath("gfortran.3"), false, true);
+        }
+        callTarget.call(LibPaths.getBuiltinLibPath("Rblas"), false, true);
+        callTarget.call(LibPaths.getBuiltinLibPath("Rlapack"), false, true);
+    }
+
+    private static RootCallTarget openLLVMLibraries() {
+        return DLLRFFI.DLOpenRootNode.create(RContext.getInstance());
+    }
+
+    private static RootCallTarget openNativeLibraries() {
+        TruffleLLVM_NativeDLL.NativeDLOpenRootNode rootNode = TruffleLLVM_NativeDLL.NativeDLOpenRootNode.create();
+        return rootNode.getCallTarget();
+    }
+
+    private static final class TruffleLLVM_IlaverNode extends TruffleLLVM_DownCallNode implements IlaverNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.ilaver;
+        }
+
+        @Override
+        public void execute(int[] version) {
+            call(version);
+        }
+    }
+
+    private static final class TruffleLLVM_DgeevNode extends TruffleLLVM_DownCallNode implements DgeevNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dgeev;
+        }
+
+        @Override
+        public int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
+            return (int) call(jobVL, jobVR, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork);
+        }
+    }
+
+    private static final class TruffleLLVM_Dgeqp3Node extends TruffleLLVM_DownCallNode implements Dgeqp3Node {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dgeqp3;
+        }
+
+        @Override
+        public int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
+            return (int) call(m, n, a, lda, jpvt, tau, work, lwork);
+        }
+    }
+
+    private static final class TruffleLLVM_DormqrNode extends TruffleLLVM_DownCallNode implements DormqrNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dormq;
+        }
+
+        @Override
+        public int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
+            return (int) call(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork);
+        }
+    }
+
+    private static final class TruffleLLVM_DtrtrsNode extends TruffleLLVM_DownCallNode implements DtrtrsNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dtrtrs;
+        }
+
+        @Override
+        public int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
+            return (int) call(uplo, trans, diag, n, nrhs, a, lda, b, ldb);
+        }
+    }
+
+    private static final class TruffleLLVM_DgetrfNode extends TruffleLLVM_DownCallNode implements DgetrfNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dgetrf;
+        }
+
+        @Override
+        public int execute(int m, int n, double[] a, int lda, int[] ipiv) {
+            return (int) call(m, n, a, lda, ipiv);
+        }
+    }
+
+    private static final class TruffleLLVM_DpotrfNode extends TruffleLLVM_DownCallNode implements DpotrfNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dpotrf;
+        }
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda) {
+            return (int) call(uplo, n, a, lda);
+        }
+    }
+
+    private static final class TruffleLLVM_DpotriNode extends TruffleLLVM_DownCallNode implements DpotriNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dpotri;
+        }
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda) {
+            return (int) call(uplo, n, a, lda);
+        }
+    }
+
+    private static final class TruffleLLVM_DpstrfNode extends TruffleLLVM_DownCallNode implements DpstrfNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dpstrf;
+        }
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
+            return (int) call(uplo, n, a, lda, piv, rank, tol, work);
+        }
+    }
+
+    private static final class TruffleLLVM_DgesvNode extends TruffleLLVM_DownCallNode implements DgesvNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dgesv;
+        }
+
+        @Override
+        public int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
+            return (int) call(n, nrhs, a, lda, ipiv, b, ldb);
+        }
+    }
+
+    private static final class TruffleLLVM_DlangeNode extends TruffleLLVM_DownCallNode implements DlangeNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dlange;
+        }
+
+        @Override
+        public double execute(char norm, int m, int n, double[] a, int lda, double[] work) {
+            return (double) call(norm, m, n, a, lda, work);
+        }
+    }
+
+    private static final class TruffleLLVM_DgeconNode extends TruffleLLVM_DownCallNode implements DgeconNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dgecon;
+        }
+
+        @Override
+        public int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
+            return (int) call(norm, n, a, lda, anorm, rcond, work, iwork);
+        }
+    }
+
+    private static final class TruffleLLVM_DsyevrNode extends TruffleLLVM_DownCallNode implements DsyevrNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dsyevr;
+        }
+
+        @Override
+        public int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, double[] z, int ldz, int[] isuppz,
+                        double[] work, int lwork, int[] iwork, int liwork) {
+            return (int) call(jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, iwork, liwork);
+        }
+    }
+
+    @Override
+    public IlaverNode createIlaverNode() {
+        return new TruffleLLVM_IlaverNode();
+    }
+
+    @Override
+    public DgeevNode createDgeevNode() {
+        return new TruffleLLVM_DgeevNode();
+    }
+
+    @Override
+    public Dgeqp3Node createDgeqp3Node() {
+        return new TruffleLLVM_Dgeqp3Node();
+    }
+
+    @Override
+    public DormqrNode createDormqrNode() {
+        return new TruffleLLVM_DormqrNode();
+    }
+
+    @Override
+    public DtrtrsNode createDtrtrsNode() {
+        return new TruffleLLVM_DtrtrsNode();
+    }
+
+    @Override
+    public DgetrfNode createDgetrfNode() {
+        return new TruffleLLVM_DgetrfNode();
+    }
+
+    @Override
+    public DpotrfNode createDpotrfNode() {
+        return new TruffleLLVM_DpotrfNode();
+    }
+
+    @Override
+    public DpotriNode createDpotriNode() {
+        return new TruffleLLVM_DpotriNode();
+    }
+
+    @Override
+    public DpstrfNode createDpstrfNode() {
+        return new TruffleLLVM_DpstrfNode();
+    }
+
+    @Override
+    public DgesvNode createDgesvNode() {
+        return new TruffleLLVM_DgesvNode();
+    }
+
+    @Override
+    public DlangeNode createDlangeNode() {
+        return new TruffleLLVM_DlangeNode();
+    }
+
+    @Override
+    public DgeconNode createDgeconNode() {
+        return new TruffleLLVM_DgeconNode();
+    }
+
+    @Override
+    public DsyevrNode createDsyevrNode() {
+        return new TruffleLLVM_DsyevrNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Misc.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Misc.java
new file mode 100644
index 0000000000000000000000000000000000000000..40daead3685fb00b54a69b813f3cc2981138bd02
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Misc.java
@@ -0,0 +1,46 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+
+public class TruffleLLVM_Misc implements MiscRFFI {
+
+    private static class TruffleLLVM_ExactSumNode extends TruffleLLVM_DownCallNode implements ExactSumNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.exactSumFunc;
+        }
+
+        @Override
+        public double execute(double[] values, boolean hasNa, boolean naRm) {
+            return (double) call(values, values.length, hasNa ? 1 : 0, naRm ? 1 : 0);
+        }
+    }
+
+    @Override
+    public ExactSumNode createExactSumNode() {
+        return new TruffleLLVM_ExactSumNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_NativeDLL.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_NativeDLL.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1e460a9f2ae75b9a11735307fcc315876f6c7c2
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_NativeDLL.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.llvm;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.Message;
+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.ffi.impl.interop.NativeCharArray;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.RFFIRootNode;
+
+/**
+ * Direct access to native {@code dlopen} for libraries for which no LLVM code is available.
+ */
+class TruffleLLVM_NativeDLL {
+    enum Function {
+        dlopen(3),
+        dlclose(1);
+
+        private final Node executeNode;
+        private final String callName;
+
+        Function(int argCount) {
+            executeNode = Message.createExecute(argCount).createNode();
+            callName = "call_" + name();
+        }
+    }
+
+    public interface ErrorCallback {
+        void setResult(String errorMessage);
+
+    }
+
+    private static class ErrorCallbackImpl implements ErrorCallback, RTruffleObject {
+        private String errorMessage;
+
+        @Override
+        public void setResult(String errorMessage) {
+            this.errorMessage = errorMessage;
+        }
+
+        @Override
+        public ForeignAccess getForeignAccess() {
+            return ErrorCallbackCallbackMRForeign.ACCESS;
+        }
+    }
+
+    @MessageResolution(receiverType = ErrorCallback.class)
+    public static class ErrorCallbackCallbackMR {
+        @CanResolve
+        public abstract static class ErrorCallbackCheckNode extends Node {
+
+            protected static boolean test(TruffleObject receiver) {
+                return receiver instanceof ErrorCallback;
+            }
+        }
+
+        @Resolve(message = "IS_EXECUTABLE")
+        public abstract static class ErrorCallbackIsExecutableNode extends Node {
+            protected Object access(@SuppressWarnings("unused") ErrorCallback receiver) {
+                return true;
+            }
+        }
+
+        @Resolve(message = "EXECUTE")
+        public abstract static class ErrorCallbackExecuteNode extends Node {
+            protected Object access(@SuppressWarnings("unused") VirtualFrame frame, ErrorCallback receiver, Object[] arguments) {
+                receiver.setResult((String) arguments[0]);
+                return receiver;
+            }
+        }
+    }
+
+    static class TruffleLLVM_NativeDLOpen extends Node {
+        @CompilationFinal private SymbolHandle symbolHandle;
+
+        public long execute(String path, boolean local, boolean now) throws UnsatisfiedLinkError {
+            try {
+                if (symbolHandle == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    symbolHandle = DLL.findSymbol(Function.dlopen.callName, null);
+                }
+                ErrorCallbackImpl errorCallbackImpl = new ErrorCallbackImpl();
+                long result = (long) ForeignAccess.sendExecute(Function.dlopen.executeNode, symbolHandle.asTruffleObject(), errorCallbackImpl, new NativeCharArray(path.getBytes()), local ? 1 : 0,
+                                now ? 1 : 0);
+                if (result == 0) {
+                    throw new UnsatisfiedLinkError(errorCallbackImpl.errorMessage);
+                }
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    static class TruffleLLVM_NativeDLClose extends Node {
+        @CompilationFinal private SymbolHandle symbolHandle;
+
+        public int execute(long handle) {
+            try {
+                if (symbolHandle == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    symbolHandle = DLL.findSymbol(Function.dlclose.callName, null);
+                }
+                int result = (int) ForeignAccess.sendExecute(Function.dlclose.executeNode, symbolHandle.asTruffleObject(), handle);
+                return result;
+            } catch (InteropException e) {
+                throw RInternalError.shouldNotReachHere(e);
+            }
+        }
+    }
+
+    public static final class NativeDLOpenRootNode extends RFFIRootNode<TruffleLLVM_NativeDLOpen> {
+        private static NativeDLOpenRootNode nativeDLOpenRootNode;
+
+        private NativeDLOpenRootNode() {
+            super(new TruffleLLVM_NativeDLOpen());
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            Object[] args = frame.getArguments();
+            return rffiNode.execute((String) args[0], (boolean) args[1], (boolean) args[2]);
+        }
+
+        public static NativeDLOpenRootNode create() {
+            if (nativeDLOpenRootNode == null) {
+                nativeDLOpenRootNode = new NativeDLOpenRootNode();
+            }
+            return nativeDLOpenRootNode;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_PCRE.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_PCRE.java
new file mode 100644
index 0000000000000000000000000000000000000000..aad99cf04ad09b15c406f7d8297e4414c6608f9a
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_PCRE.java
@@ -0,0 +1,148 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.common.LibPaths;
+import com.oracle.truffle.r.ffi.impl.interop.NativeCharArray;
+import com.oracle.truffle.r.ffi.impl.interop.pcre.CaptureNamesResult;
+import com.oracle.truffle.r.ffi.impl.interop.pcre.CompileResult;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_Utils.AsPointerNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+
+public class TruffleLLVM_PCRE implements PCRERFFI {
+
+    TruffleLLVM_PCRE() {
+        // Need to ensure that the native pcre library is loaded
+        String pcrePath = LibPaths.getBuiltinLibPath("pcre");
+        TruffleLLVM_NativeDLL.NativeDLOpenRootNode.create().getCallTarget().call(pcrePath, false, true);
+    }
+
+    private static class TruffleLLVM_MaketablesNode extends TruffleLLVM_DownCallNode implements MaketablesNode {
+
+        @Child private AsPointerNode asPointer = new AsPointerNode();
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.maketables;
+        }
+
+        @Override
+        public long execute() {
+            return asPointer.execute((TruffleObject) call());
+        }
+    }
+
+    private static class TruffleLLVM_GetCaptureCountNode extends TruffleLLVM_DownCallNode implements GetCaptureCountNode {
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.getcapturecount;
+        }
+
+        @Override
+        public int execute(long code, long extra) {
+            return (int) call(code, extra);
+        }
+    }
+
+    private static class TruffleLLVM_GetCaptureNamesNode extends TruffleLLVM_DownCallNode implements GetCaptureNamesNode {
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.getcapturenames;
+        }
+
+        @Override
+        public String[] execute(long code, long extra, int captureCount) {
+            CaptureNamesResult captureNamesCallback = new CaptureNamesResult(captureCount);
+            int result = (int) call(captureNamesCallback, code, extra);
+            if (result < 0) {
+                CompilerDirectives.transferToInterpreter();
+                throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, result);
+            } else {
+                return captureNamesCallback.getCaptureNames();
+            }
+        }
+    }
+
+    private static class TruffleLLVM_CompileNode extends TruffleLLVM_DownCallNode implements CompileNode {
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.compile;
+        }
+
+        @Override
+        public Result execute(String pattern, int options, long tables) {
+            NativeCharArray pattenChars = new NativeCharArray(pattern.getBytes());
+            CompileResult data = new CompileResult();
+            call(data, pattenChars, options, tables);
+            return data.getResult();
+        }
+    }
+
+    private static class TruffleLLVM_ExecNode extends TruffleLLVM_DownCallNode implements ExecNode {
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.exec;
+        }
+
+        @Override
+        public int execute(long code, long extra, String subject, int offset, int options, int[] ovector) {
+            byte[] subjectBytes = subject.getBytes();
+            NativeCharArray subjectChars = new NativeCharArray(subjectBytes);
+            return (int) call(code, extra, subjectChars, subjectBytes.length, offset, options, ovector, ovector.length);
+        }
+    }
+
+    @Override
+    public MaketablesNode createMaketablesNode() {
+        return new TruffleLLVM_MaketablesNode();
+    }
+
+    @Override
+    public CompileNode createCompileNode() {
+        return new TruffleLLVM_CompileNode();
+    }
+
+    @Override
+    public GetCaptureCountNode createGetCaptureCountNode() {
+        return new TruffleLLVM_GetCaptureCountNode();
+    }
+
+    @Override
+    public GetCaptureNamesNode createGetCaptureNamesNode() {
+        return new TruffleLLVM_GetCaptureNamesNode();
+    }
+
+    @Override
+    public StudyNode createStudyNode() {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public ExecNode createExecNode() {
+        return new TruffleLLVM_ExecNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_PkgInit.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_PkgInit.java
new file mode 100644
index 0000000000000000000000000000000000000000..62920f9001ae4e3a74df4347c91c0db82ad56419
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_PkgInit.java
@@ -0,0 +1,98 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+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.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.common.PkgInitUpCalls;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.ForceSymbolsCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.GetCCallableCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.RegisterCCallableCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.RegisterRoutinesCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.SetDotSymbolValuesCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.UseDynamicSymbolsCall;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+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.SymbolHandle;
+import com.oracle.truffle.r.ffi.impl.common.Generic_PkgInit;
+
+final class TruffleLLVM_PkgInit extends Generic_PkgInit {
+
+    private static TruffleLLVM_PkgInit trufflePkgInit;
+    private static TruffleObject setSymbolHandle;
+
+    static class ContextStateImpl implements RContext.ContextState {
+        @Override
+        public ContextState initialize(RContext context) {
+            if (context.isInitial()) {
+                TruffleLLVM_PkgInit.initialize(context);
+            }
+            return this;
+        }
+    }
+
+    private static void initialize(RContext context) {
+        trufflePkgInit = new TruffleLLVM_PkgInit();
+        setSymbolHandle = new SymbolHandle(context.getEnv().importSymbol("@" + "Rdynload_setSymbol")).asTruffleObject();
+        Node executeNode = Message.createExecute(2).createNode();
+        TruffleObject callbackSymbol = new SymbolHandle(context.getEnv().importSymbol("@" + "Rdynload_addCallback")).asTruffleObject();
+        try {
+            ForeignAccess.sendExecute(executeNode, callbackSymbol, PkgInitUpCalls.Index.registerRoutines.ordinal(), new RegisterRoutinesCall(trufflePkgInit));
+            ForeignAccess.sendExecute(executeNode, callbackSymbol, PkgInitUpCalls.Index.setDotSymbolValues.ordinal(), new SetDotSymbolValuesCall(trufflePkgInit));
+            ForeignAccess.sendExecute(executeNode, callbackSymbol, PkgInitUpCalls.Index.useDynamicSymbols.ordinal(), new UseDynamicSymbolsCall(trufflePkgInit));
+            ForeignAccess.sendExecute(executeNode, callbackSymbol, PkgInitUpCalls.Index.forceSymbols.ordinal(), new ForceSymbolsCall(trufflePkgInit));
+            ForeignAccess.sendExecute(executeNode, callbackSymbol, PkgInitUpCalls.Index.registerCCallable.ordinal(), new RegisterCCallableCall(trufflePkgInit));
+            ForeignAccess.sendExecute(executeNode, callbackSymbol, PkgInitUpCalls.Index.getCCallable.ordinal(), new GetCCallableCall(trufflePkgInit));
+        } catch (Throwable t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+
+    @Override
+    public Object getCCallable(String pkgName, String functionName) {
+        DLLInfo lib = DLL.safeFindLibrary(pkgName);
+        CEntry result = lib.lookupCEntry(functionName);
+        if (result == null) {
+            throw RError.error(RError.NO_CALLER, RError.Message.UNKNOWN_OBJECT, functionName);
+        }
+        return result.address.asTruffleObject();
+    }
+
+    @Override
+    protected Object setSymbol(DLLInfo dllInfo, int nstOrd, long routines, int index) {
+        Node executeNode = Message.createExecute(4).createNode();
+        try {
+            Object result = ForeignAccess.sendExecute(executeNode, setSymbolHandle, dllInfo, nstOrd, routines, index);
+            return result;
+        } catch (Throwable t) {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RAppl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RAppl.java
new file mode 100644
index 0000000000000000000000000000000000000000..1deb3356d337d22f3a1143dd48ef435486b00022
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RAppl.java
@@ -0,0 +1,106 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+
+/**
+ * See the comments in {@link TruffleLLVM_Lapack} regarding argument passing.
+ */
+public class TruffleLLVM_RAppl implements RApplRFFI {
+
+    private static final class TruffleLLVM_Dqrdc2Node extends TruffleLLVM_DownCallNode implements Dqrdc2Node {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dqrdc2;
+        }
+
+        @Override
+        public void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
+            call(x, ldx, n, p, tol, rank, qraux, pivot, work);
+        }
+    }
+
+    private static final class TruffleLLVM_DqrcfNode extends TruffleLLVM_DownCallNode implements DqrcfNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dqrcf;
+        }
+
+        @Override
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) {
+            call(x, n, k, qraux, y, ny, b, info);
+        }
+    }
+
+    private static final class TruffleLLVM_DqrlsNode extends TruffleLLVM_DownCallNode implements DqrlsNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.dqrls;
+        }
+
+        @Override
+        public void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
+            call(x, n, p, y, ny, tol, b, rsd, qty, k, jpvt, qraux, work);
+        }
+    }
+
+    @Override
+    public Dqrdc2Node createDqrdc2Node() {
+        return new TruffleLLVM_Dqrdc2Node();
+    }
+
+    @Override
+    public DqrcfNode createDqrcfNode() {
+        return new TruffleLLVM_DqrcfNode();
+    }
+
+    @Override
+    public DqrlsNode createDqrlsNode() {
+        return new TruffleLLVM_DqrlsNode();
+    }
+
+    @Override
+    public DqrqtyNode createDqrqtyNode() {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public DqrqyNode createDqrqyNode() {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public DqrrsdNode createDqrrsdNode() {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public DqrxbNode createDqrxbNode() {
+        throw RInternalError.unimplemented();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_REmbed.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_REmbed.java
new file mode 100644
index 0000000000000000000000000000000000000000..d61d63cea40b8cdb9085b835e632ce74b8d7979f
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_REmbed.java
@@ -0,0 +1,54 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+
+public class TruffleLLVM_REmbed implements REmbedRFFI {
+
+    @Override
+    public void suicide(String x) {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public void cleanUp(int type, int x, int y) {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public String readConsole(String prompt) {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public void writeConsole(String x) {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public void writeErrConsole(String x) {
+        throw RInternalError.unimplemented();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_RFFIContextState.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RFFIContextState.java
similarity index 75%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_RFFIContextState.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RFFIContextState.java
index 9caaec171979d011110a3f065fdc896070804d68..bf236d54ecb11df54bbae0c514d70816594e093f 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_RFFIContextState.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RFFIContextState.java
@@ -20,28 +20,26 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.llvm;
+package com.oracle.truffle.r.ffi.impl.llvm;
 
+import com.oracle.truffle.r.ffi.impl.common.LibPaths;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.DLL;
 
 /**
  * A facade for the context state for the Truffle LLVM factory. Delegates to the various
- * module-specific pieces of state. This may get merged into a single instance eventually.
+ * module-specific pieces of state.
  */
 class TruffleLLVM_RFFIContextState implements ContextState {
     TruffleLLVM_DLL.ContextStateImpl dllState;
     TruffleLLVM_PkgInit.ContextStateImpl pkgInitState;
     TruffleLLVM_Call.ContextStateImpl callState;
-    TruffleLLVM_Stats.ContextStateImpl statsState;
-    private final ContextState jniContextState;
 
-    TruffleLLVM_RFFIContextState(ContextState jniContextState) {
-        this.jniContextState = jniContextState;
-        dllState = TruffleLLVM_DLL.newContextState();
-        pkgInitState = TruffleLLVM_PkgInit.newContextState();
-        callState = TruffleLLVM_Call.newContextState();
-        statsState = TruffleLLVM_Stats.newContextState();
+    TruffleLLVM_RFFIContextState() {
+        dllState = new TruffleLLVM_DLL.ContextStateImpl();
+        pkgInitState = new TruffleLLVM_PkgInit.ContextStateImpl();
+        callState = new TruffleLLVM_Call.ContextStateImpl();
     }
 
     static TruffleLLVM_RFFIContextState getContextState() {
@@ -54,11 +52,13 @@ class TruffleLLVM_RFFIContextState implements ContextState {
 
     @Override
     public ContextState initialize(RContext context) {
-        jniContextState.initialize(context);
+        if (context.isInitial()) {
+            String librffiPath = LibPaths.getBuiltinLibPath("R");
+            DLL.loadLibR(librffiPath);
+        }
         dllState.initialize(context);
         pkgInitState.initialize(context);
         callState.initialize(context);
-        statsState.initialize(context);
         return this;
     }
 
@@ -67,6 +67,5 @@ class TruffleLLVM_RFFIContextState implements ContextState {
         dllState.beforeDestroy(context);
         pkgInitState.beforeDestroy(context);
         callState.beforeDestroy(context);
-        statsState.beforeDestroy(context);
     }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RFFIFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RFFIFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..bf6b5230a57161cdddbd2b469f605ff2e8c25877
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_RFFIFactory.java
@@ -0,0 +1,200 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+
+public class TruffleLLVM_RFFIFactory extends RFFIFactory {
+
+    @Override
+    public ContextState newContextState() {
+        return new TruffleLLVM_RFFIContextState();
+    }
+
+    @Override
+    protected RFFI createRFFI() {
+        CompilerAsserts.neverPartOfCompilation();
+        return new RFFI() {
+
+            @CompilationFinal private BaseRFFI baseRFFI;
+
+            @Override
+            public BaseRFFI getBaseRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (baseRFFI == null) {
+                    baseRFFI = new TruffleLLVM_Base();
+                }
+                return baseRFFI;
+            }
+
+            @CompilationFinal private CRFFI cRFFI;
+
+            @Override
+            public CRFFI getCRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (cRFFI == null) {
+                    cRFFI = new TruffleLLVM_C();
+                }
+                return cRFFI;
+            }
+
+            @CompilationFinal private DLLRFFI dllRFFI;
+
+            @Override
+            public DLLRFFI getDLLRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (dllRFFI == null) {
+                    dllRFFI = new TruffleLLVM_DLL();
+                }
+                return dllRFFI;
+            }
+
+            @CompilationFinal private UserRngRFFI truffleUserRngRFFI;
+
+            @Override
+            public UserRngRFFI getUserRngRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (truffleUserRngRFFI == null) {
+                    truffleUserRngRFFI = new TruffleLLVM_UserRng();
+                }
+                return truffleUserRngRFFI;
+            }
+
+            @CompilationFinal private CallRFFI truffleCallRFFI;
+
+            @Override
+            public CallRFFI getCallRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (truffleCallRFFI == null) {
+                    truffleCallRFFI = new TruffleLLVM_Call();
+                }
+                return truffleCallRFFI;
+            }
+
+            @CompilationFinal private StatsRFFI truffleStatsRFFI;
+
+            @Override
+            public StatsRFFI getStatsRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (truffleStatsRFFI == null) {
+                    truffleStatsRFFI = new TruffleLLVM_Stats();
+                }
+                return truffleStatsRFFI;
+            }
+
+            @CompilationFinal private RApplRFFI rApplRFFI;
+
+            @Override
+            public RApplRFFI getRApplRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (rApplRFFI == null) {
+                    rApplRFFI = new TruffleLLVM_RAppl();
+                }
+                return rApplRFFI;
+            }
+
+            @CompilationFinal private LapackRFFI lapackRFFI;
+
+            @Override
+            public LapackRFFI getLapackRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (lapackRFFI == null) {
+                    lapackRFFI = new TruffleLLVM_Lapack();
+                }
+                return lapackRFFI;
+            }
+
+            @CompilationFinal private ToolsRFFI toolsRFFI;
+
+            @Override
+            public ToolsRFFI getToolsRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (toolsRFFI == null) {
+                    toolsRFFI = new TruffleLLVM_Tools();
+                }
+                return toolsRFFI;
+            }
+
+            @CompilationFinal private PCRERFFI pcreRFFI;
+
+            @Override
+            public PCRERFFI getPCRERFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (pcreRFFI == null) {
+                    pcreRFFI = new TruffleLLVM_PCRE();
+                }
+                return pcreRFFI;
+            }
+
+            @CompilationFinal private ZipRFFI zipRFFI;
+
+            @Override
+            public ZipRFFI getZipRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (zipRFFI == null) {
+                    zipRFFI = new TruffleLLVM_Zip();
+                }
+                return zipRFFI;
+            }
+
+            @CompilationFinal private MiscRFFI miscRFFI;
+
+            @Override
+            public MiscRFFI getMiscRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (miscRFFI == null) {
+                    miscRFFI = new TruffleLLVM_Misc();
+                }
+                return miscRFFI;
+            }
+
+            private REmbedRFFI rEmbedRFFI;
+
+            @Override
+            public REmbedRFFI getREmbedRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (rEmbedRFFI == null) {
+                    rEmbedRFFI = new TruffleLLVM_REmbed();
+                }
+                return rEmbedRFFI;
+            }
+        };
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_Stats.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Stats.java
similarity index 69%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_Stats.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Stats.java
index b3e1d89e4f55eb714ccd5b0b8a7abb6e6f046bf8..21a0da11b492b410fbd742947d4235f317118b94 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/llvm/TruffleLLVM_Stats.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Stats.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.llvm;
+package com.oracle.truffle.r.ffi.impl.llvm;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.ImportStatic;
@@ -28,13 +28,12 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.interop.NativeDoubleArray;
-import com.oracle.truffle.r.engine.interop.NativeIntegerArray;
-import com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_StatsFactory.ExecuteFactorNodeGen;
-import com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_StatsFactory.ExecuteWorkNodeGen;
+import com.oracle.truffle.r.ffi.impl.interop.NativeDoubleArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeIntegerArray;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_StatsFactory.ExecuteFactorNodeGen;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_StatsFactory.ExecuteWorkNodeGen;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.ContextState;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
@@ -49,43 +48,8 @@ public class TruffleLLVM_Stats implements StatsRFFI {
         fft_factor;
     }
 
-    static class ContextStateImpl implements RContext.ContextState {
-        @Override
-        public ContextState initialize(RContext context) {
-            /*
-             * In the case of a SHARE_PARENT_RW context, there is no dlopen call for stats, so the
-             * fft_work/fft_factor functions will not be added into the context symbol map, so we do
-             * it here.
-             */
-            if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
-                TruffleLLVM_DLL.ContextStateImpl contextState = TruffleLLVM_RFFIContextState.getContextState().dllState;
-                TruffleLLVM_DLL.ContextStateImpl parentDLLContextState = TruffleLLVM_RFFIContextState.getContextState(context.getParent()).dllState;
-                TruffleLLVM_DLL.ParseStatus parseStatus = null;
-                for (FFT_FUN f : FFT_FUN.values()) {
-                    String funName = f.name();
-                    TruffleLLVM_DLL.ParseStatus parentParseStatus = parentDLLContextState.parseStatusMap.get(funName);
-                    if (parentParseStatus != null) {
-                        if (parseStatus == null) {
-                            parseStatus = new TruffleLLVM_DLL.ParseStatus("stats", parentParseStatus.ir, false);
-                        }
-                        contextState.parseStatusMap.put(f.name(), parseStatus);
-                    }
-                }
-            }
-            return this;
-        }
-
-        @Override
-        public void beforeDestroy(RContext context) {
-        }
-    }
-
-    static ContextStateImpl newContextState() {
-        return new ContextStateImpl();
-    }
-
     public abstract static class LookupAdapter extends Node {
-        @Child DLLRFFI.DLSymNode dllSymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
+        @Child private DLLRFFI.DLSymNode dllSymNode = RFFIFactory.getDLLRFFI().createDLSymNode();
 
         public SymbolHandle lookup(String name) {
             DLLInfo dllInfo = DLL.findLibrary("stats");
@@ -93,8 +57,6 @@ public class TruffleLLVM_Stats implements StatsRFFI {
             // and these symbols are not registered (only fft)
             SymbolHandle result = dllSymNode.execute(dllInfo.handle, name);
             if (result == DLL.SYMBOL_NOT_FOUND) {
-                @SuppressWarnings("unused")
-                TruffleLLVM_RFFIContextState cs = TruffleLLVM_RFFIContextState.getContextState();
                 throw RInternalError.shouldNotReachHere();
             }
             return result;
@@ -119,10 +81,9 @@ public class TruffleLLVM_Stats implements StatsRFFI {
         }
 
         private static int doWork(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork, Node messageNode, SymbolHandle fftWork) {
-            NativeDoubleArray na = new NativeDoubleArray(a);
-            NativeDoubleArray nwork = new NativeDoubleArray(work);
-            NativeIntegerArray niwork = new NativeIntegerArray(iwork);
-            try {
+            try (NativeDoubleArray na = new NativeDoubleArray(a);
+                            NativeDoubleArray nwork = new NativeDoubleArray(work);
+                            NativeIntegerArray niwork = new NativeIntegerArray(iwork)) {
                 return (int) ForeignAccess.sendExecute(messageNode, fftWork.asTruffleObject(), na, nseg, n, nspn, isn, nwork, niwork);
             } catch (Throwable t) {
                 throw RInternalError.shouldNotReachHere(t);
@@ -160,10 +121,8 @@ public class TruffleLLVM_Stats implements StatsRFFI {
         }
 
         private static void doFactor(int n, int[] pmaxf, int[] pmaxp, Node messageNode, SymbolHandle fftFactor) {
-            NativeIntegerArray npmaxf = new NativeIntegerArray(pmaxf);
-            NativeIntegerArray npmaxp = new NativeIntegerArray(pmaxp);
-
-            try {
+            try (NativeIntegerArray npmaxf = new NativeIntegerArray(pmaxf);
+                            NativeIntegerArray npmaxp = new NativeIntegerArray(pmaxp)) {
                 ForeignAccess.sendExecute(messageNode, fftFactor.asTruffleObject(), n, npmaxf, npmaxp);
             } catch (Throwable t) {
                 throw RInternalError.shouldNotReachHere(t);
@@ -183,8 +142,8 @@ public class TruffleLLVM_Stats implements StatsRFFI {
         }
     }
 
-    public static class Truffle_FactorNode extends FactorNode {
-        @Child ExecuteFactor executeFactor = ExecuteFactor.create();
+    private static class Truffle_FactorNode extends Node implements FactorNode {
+        @Child private ExecuteFactor executeFactor = ExecuteFactor.create();
 
         @Override
         public void execute(int n, int[] pmaxf, int[] pmaxp) {
@@ -192,8 +151,8 @@ public class TruffleLLVM_Stats implements StatsRFFI {
         }
     }
 
-    public static class Truffle_WorkNode extends WorkNode {
-        @Child ExecuteWork executeWork = ExecuteWork.create();
+    private static class Truffle_WorkNode extends Node implements WorkNode {
+        @Child private ExecuteWork executeWork = ExecuteWork.create();
 
         @Override
         public int execute(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Tools.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Tools.java
new file mode 100644
index 0000000000000000000000000000000000000000..b04deaa0d01f0fea5a97a92e402b60f37267c9dd
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Tools.java
@@ -0,0 +1,73 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+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.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.common.Generic_Tools;
+import com.oracle.truffle.r.ffi.impl.interop.tools.RConnGetCCall;
+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.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
+
+public class TruffleLLVM_Tools implements ToolsRFFI {
+
+    private static boolean addCallbackDone;
+
+    private static void addCallback() {
+        if (!addCallbackDone) {
+            Node executeNode = Message.createExecute(2).createNode();
+            TruffleObject callbackSymbol = new SymbolHandle(RContext.getInstance().getEnv().importSymbol("@" + "gramRd_addCallback")).asTruffleObject();
+            try {
+                ForeignAccess.sendExecute(executeNode, callbackSymbol, new RConnGetCCall());
+                addCallbackDone = true;
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere(t);
+            }
+        }
+    }
+
+    private static class TruffleLLVM_ToolsRFFINode extends Generic_Tools.Generic_ToolsRFFINode {
+        /**
+         * Invoke C implementation, N.B., code is not thread safe.
+         */
+        @Override
+        public synchronized Object execute(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros,
+                        RLogicalVector warndups) {
+            addCallback();
+            return super.execute(con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups);
+        }
+    }
+
+    @Override
+    public ParseRdNode createParseRdNode() {
+        return new TruffleLLVM_ToolsRFFINode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..bc64dc1163904a85a76a9ab7825252884f976789
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UpCallsRFFIImpl.java
@@ -0,0 +1,139 @@
+/*
+ * 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.ffi.impl.llvm;
+
+import com.oracle.truffle.r.ffi.impl.common.JavaUpCallsRFFIImpl;
+import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
+import com.oracle.truffle.r.ffi.impl.interop.NativeCharArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeDoubleArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeIntegerArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeLogicalArray;
+import com.oracle.truffle.r.ffi.impl.interop.NativeRawArray;
+import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks;
+import com.oracle.truffle.r.runtime.REnvVars;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RDouble;
+import com.oracle.truffle.r.runtime.data.RInteger;
+import com.oracle.truffle.r.runtime.data.RLogical;
+import com.oracle.truffle.r.runtime.data.RScalar;
+import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
+
+/**
+ * (Incomplete) Variant of {@link JavaUpCallsRFFIImpl} for Truffle LLVM.
+ *
+ */
+public class TruffleLLVM_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
+
+    public Object charSXPToNativeCharArray(Object x) {
+        CharSXPWrapper chars = RFFIUtils.guaranteeInstanceOf(x, CharSXPWrapper.class);
+        return new NativeCharArray(chars.getContents().getBytes());
+    }
+
+    public Object bytesToNativeCharArray(byte[] bytes) {
+        Object result = new NativeCharArray(bytes);
+        return result;
+    }
+
+    // Checkstyle: stop method name check
+
+    @Override
+    public Object Rf_mkCharLenCE(Object obj, int len, int encoding) {
+        if (obj instanceof NativeCharArray) {
+            byte[] bytes = ((NativeCharArray) obj).getValue();
+            return super.Rf_mkCharLenCE(bytes, bytes.length, encoding);
+        } else {
+            throw RInternalError.unimplemented();
+        }
+    }
+
+    @Override
+    public Object RAW(Object x) {
+        byte[] value = (byte[]) super.RAW(x);
+
+        // TODO: this will leak memory if the pointer escapes
+        return new NativeRawArray(value);
+    }
+
+    @Override
+    public Object LOGICAL(Object x) {
+        byte[] value = (byte[]) super.LOGICAL(x);
+
+        // TODO: this will leak memory if the pointer escapes
+        return new NativeLogicalArray(x, value);
+    }
+
+    @Override
+    public Object INTEGER(Object x) {
+        int[] value = (int[]) super.INTEGER(x);
+
+        // TODO: this will leak memory if the pointer escapes
+        return new NativeIntegerArray(x, value);
+    }
+
+    @Override
+    public Object REAL(Object x) {
+        // Special handling in Truffle variant
+        double[] value = (double[]) super.REAL(x);
+
+        // TODO: this will leak memory if the pointer escapes
+        return new NativeDoubleArray(x, value);
+    }
+
+    @Override
+    public Object R_Home() {
+        byte[] sbytes = REnvVars.rHome().getBytes();
+        return new NativeCharArray(sbytes);
+    }
+
+    @Override
+    public Object Rf_findVar(Object symbolArg, Object envArg) {
+        Object v = super.Rf_findVar(symbolArg, envArg);
+        if (v instanceof RTypedValue) {
+            return v;
+        } else {
+            return wrapPrimitive(v);
+        }
+    }
+
+    private static RScalar wrapPrimitive(Object x) {
+        if (x instanceof Double) {
+            return RDouble.valueOf((double) x);
+        } else if (x instanceof Integer) {
+            return RInteger.valueOf((int) x);
+        } else if (x instanceof Byte) {
+            return RLogical.valueOf((byte) x);
+        } else {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+
+    @Override
+    public Object R_CHAR(Object x) {
+        throw RInternalError.unimplemented();
+    }
+
+    public Object getCallback(int index) {
+        return Callbacks.values()[index].call;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UserRng.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UserRng.java
new file mode 100644
index 0000000000000000000000000000000000000000..63cdf6286422c023c84116d1a67adc202d697615
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_UserRng.java
@@ -0,0 +1,126 @@
+/*
+ * 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.ffi.impl.llvm;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.rng.user.UserRNG.Function;
+
+public class TruffleLLVM_UserRng implements UserRngRFFI {
+
+    private abstract static class RNGNode extends Node {
+
+        @CompilationFinal protected Node message;
+        @CompilationFinal protected Node readPointerNode = Message.createExecute(1).createNode();
+
+        protected void init(int argumentCount) {
+            if (message == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                message = Message.createExecute(argumentCount).createNode();
+            }
+        }
+    }
+
+    private static final class TruffleLLVMInitNode extends RNGNode implements InitNode {
+
+        @Override
+        public void execute(int seed) {
+            init(1);
+            try {
+                ForeignAccess.sendExecute(message, Function.Init.getSymbolHandle().asTruffleObject(), seed);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static final class TruffleLLVM_RandNode extends RNGNode implements RandNode {
+
+        @Override
+        public double execute() {
+            init(0);
+            try {
+                Object address = ForeignAccess.sendExecute(message, Function.Rand.getSymbolHandle().asTruffleObject());
+                return (double) ForeignAccess.sendExecute(readPointerNode, TruffleLLVM_CAccess.Function.READ_POINTER_DOUBLE.getSymbolHandle().asTruffleObject(), address);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static final class TruffleLLVM_NSeedNode extends RNGNode implements NSeedNode {
+
+        @Override
+        public int execute() {
+            init(0);
+            try {
+                Object address = ForeignAccess.sendExecute(message, Function.NSeed.getSymbolHandle().asTruffleObject());
+                return (int) ForeignAccess.sendExecute(readPointerNode, TruffleLLVM_CAccess.Function.READ_POINTER_INT.getSymbolHandle().asTruffleObject(), address);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static final class TruffleLLVM_SeedsNode extends RNGNode implements SeedsNode {
+
+        @Override
+        public void execute(int[] n) {
+            init(0);
+            try {
+                Object address = ForeignAccess.sendExecute(message, Function.Seedloc.getSymbolHandle().asTruffleObject());
+                for (int i = 0; i < n.length; i++) {
+                    Object seed = ForeignAccess.sendExecute(readPointerNode, TruffleLLVM_CAccess.Function.READ_ARRAY_INT.getSymbolHandle().asTruffleObject(), address, i);
+                    n[i] = (int) seed;
+                }
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Override
+    public InitNode createInitNode() {
+        return new TruffleLLVMInitNode();
+    }
+
+    @Override
+    public RandNode createRandNode() {
+        return new TruffleLLVM_RandNode();
+    }
+
+    @Override
+    public NSeedNode createNSeedNode() {
+        return new TruffleLLVM_NSeedNode();
+    }
+
+    @Override
+    public SeedsNode createSeedsNode() {
+        return new TruffleLLVM_SeedsNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Utils.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Utils.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f1c0237bb0f6ae198d12f35d9c6dde193c231bb
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Utils.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.llvm;
+
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.RFFIRootNode;
+
+public class TruffleLLVM_Utils {
+    public static long getNativeAddress(TruffleObject llvmTruffleAddress) {
+        if (asPointerRootNode == null) {
+            asPointerRootNode = new AsPointerRootNode();
+        }
+        long result = (long) asPointerRootNode.getCallTarget().call(llvmTruffleAddress);
+        return result;
+    }
+
+    static final class AsPointerRootNode extends RFFIRootNode<AsPointerNode> {
+        private AsPointerRootNode() {
+            super(new AsPointerNode());
+        }
+
+        @Override
+        public Object execute(VirtualFrame frame) {
+            Object[] args = frame.getArguments();
+            return rffiNode.execute((TruffleObject) args[0]);
+        }
+    }
+
+    private static AsPointerRootNode asPointerRootNode;
+
+    static final class AsPointerNode extends Node {
+        @Child private Node asPointerMessageNode = Message.AS_POINTER.createNode();
+
+        public long execute(TruffleObject pointer) {
+            try {
+                return ForeignAccess.sendAsPointer(asPointerMessageNode, pointer);
+            } catch (InteropException ex) {
+                throw RInternalError.shouldNotReachHere(ex);
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Zip.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Zip.java
new file mode 100644
index 0000000000000000000000000000000000000000..f414a6233990f7a6581d4acb7365101eb3df822f
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/TruffleLLVM_Zip.java
@@ -0,0 +1,76 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
+
+import com.oracle.truffle.r.ffi.impl.interop.NativeRawArray;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+
+public class TruffleLLVM_Zip implements ZipRFFI {
+    private static class TruffleLLVM_CompressNode extends TruffleLLVM_DownCallNode implements CompressNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.compress;
+        }
+
+        @Override
+        public int execute(byte[] dest, byte[] source) {
+            NativeRawArray nativeDest = new NativeRawArray(dest);
+            NativeRawArray nativeSource = new NativeRawArray(source);
+            try {
+                return (int) call(nativeDest, dest.length, nativeSource, source.length);
+            } finally {
+                nativeDest.getValue();
+            }
+        }
+    }
+
+    private static class TruffleLLVM_UncompressNode extends TruffleLLVM_DownCallNode implements UncompressNode {
+
+        @Override
+        protected LLVMFunction getFunction() {
+            return LLVMFunction.uncompress;
+        }
+
+        @Override
+        public int execute(byte[] dest, byte[] source) {
+            NativeRawArray nativeDest = new NativeRawArray(dest);
+            NativeRawArray nativeSource = new NativeRawArray(source);
+            try {
+                return (int) call(nativeDest, dest.length, nativeSource, source.length);
+            } finally {
+                nativeDest.getValue();
+            }
+        }
+    }
+
+    @Override
+    public CompressNode createCompressNode() {
+        return new TruffleLLVM_CompressNode();
+    }
+
+    @Override
+    public UncompressNode createUncompressNode() {
+        return new TruffleLLVM_UncompressNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..17f566611729730c104aa65a309bca4a894f38ed
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/**
+ * The Truffle LLVM implementation of the {@link com.oracle.truffle.r.runtime.ffi.RFFI} interfaces.
+ */
+package com.oracle.truffle.r.ffi.impl.llvm;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/ShowLLVMIR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java
similarity index 82%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/ShowLLVMIR.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java
index cb525d80dbc464f98c6ded71d488197d086ddaaa..91acc85892f4595697ed8dc15351271b23478039 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/ShowLLVMIR.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/tools/ShowLLVMIR.java
@@ -20,21 +20,21 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.test.tools;
+package com.oracle.truffle.r.ffi.impl.llvm.tools;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 
+import com.oracle.truffle.r.ffi.impl.llvm.LLVM_IR;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_DLL;
 import com.oracle.truffle.r.runtime.ProcessOutputManager;
-import com.oracle.truffle.r.runtime.ffi.truffle.LLVM_IR;
 
 public class ShowLLVMIR {
     public static void main(String[] args) {
         String objPath = null;
         String llpart = null;
         boolean list = false;
-        boolean xxports = false;
         boolean dis = false;
         int i = 0;
         while (i < args.length) {
@@ -53,9 +53,6 @@ public class ShowLLVMIR {
                 case "--list":
                     list = true;
                     break;
-                case "--xxports":
-                    xxports = true;
-                    break;
                 case "--dis":
                     dis = true;
                     break;
@@ -67,7 +64,7 @@ public class ShowLLVMIR {
             usage();
         }
         try {
-            LLVM_IR[] irs = LLVM_IR.getLLVMIR(objPath);
+            LLVM_IR[] irs = TruffleLLVM_DLL.getZipLLVMIR(objPath);
             if (irs == null) {
                 System.out.printf("no llvm ir in %s\n", objPath);
                 System.exit(1);
@@ -78,18 +75,6 @@ public class ShowLLVMIR {
                 } else {
                     if (llpart == null || ir.name.equals(llpart)) {
                         System.out.printf("Module: %s%n", ir.name);
-                        if (xxports) {
-                            System.out.println("Exports");
-                            System.out.println("=======");
-                            for (String export : ir.exports) {
-                                System.out.println(export);
-                            }
-                            System.out.println("Imports");
-                            System.out.println("=======");
-                            for (String importx : ir.imports) {
-                                System.out.println(importx);
-                            }
-                        }
                         if (dis) {
                             String text = null;
                             if (ir instanceof LLVM_IR.Binary) {
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f5756c9f10fbb534e09d5b95e21d29cb8f17dec
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCall.java
@@ -0,0 +1,46 @@
+/*
+ * 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.ffi.impl.llvm.upcalls;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_UpCallsRFFIImpl;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class BytesToNativeCharArrayCall implements RTruffleObject {
+
+    public final TruffleLLVM_UpCallsRFFIImpl upCallsImpl;
+
+    public BytesToNativeCharArrayCall(TruffleLLVM_UpCallsRFFIImpl upCallsImpl) {
+        this.upCallsImpl = upCallsImpl;
+    }
+
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof BytesToNativeCharArrayCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return BytesToNativeCharArrayCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc51516b4fccfc8c95208324e32a5781c659ed12
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/BytesToNativeCharArrayCallMR.java
@@ -0,0 +1,46 @@
+/*
+ * 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.ffi.impl.llvm.upcalls;
+
+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.interop.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+
+@MessageResolution(receiverType = BytesToNativeCharArrayCall.class)
+public class BytesToNativeCharArrayCallMR {
+    @Resolve(message = "EXECUTE")
+    public abstract static class BytesToNativeCharArrayCallExecute extends Node {
+        protected java.lang.Object access(BytesToNativeCharArrayCall receiver, Object[] arguments) {
+            return receiver.upCallsImpl.bytesToNativeCharArray(JavaInterop.asJavaObject(byte[].class, (TruffleObject) arguments[0]));
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class BytesToNativeCharArrayCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") BytesToNativeCharArrayCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/CharSXPToNativeArrayCall.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/CharSXPToNativeArrayCall.java
new file mode 100644
index 0000000000000000000000000000000000000000..769836837ecd7545ac05ec0f3ecdc42f25039662
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/CharSXPToNativeArrayCall.java
@@ -0,0 +1,45 @@
+/*
+ * 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.ffi.impl.llvm.upcalls;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_UpCallsRFFIImpl;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+public class CharSXPToNativeArrayCall implements RTruffleObject {
+    public final TruffleLLVM_UpCallsRFFIImpl upCallsImpl;
+
+    public CharSXPToNativeArrayCall(TruffleLLVM_UpCallsRFFIImpl upCallsImpl) {
+        this.upCallsImpl = upCallsImpl;
+    }
+
+    public static boolean isInstance(TruffleObject value) {
+        return value instanceof CharSXPToNativeArrayCall;
+    }
+
+    @Override
+    public ForeignAccess getForeignAccess() {
+        return CharSXPToNativeArrayCallMRForeign.ACCESS;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/CharSXPToNativeArrayCallMR.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/CharSXPToNativeArrayCallMR.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b29c21a0e27f75eb0598fa8f2938e323ce93dd0
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/llvm/upcalls/CharSXPToNativeArrayCallMR.java
@@ -0,0 +1,46 @@
+/*
+ * 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.ffi.impl.llvm.upcalls;
+
+import com.oracle.truffle.api.interop.MessageResolution;
+import com.oracle.truffle.api.interop.Resolve;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.data.RTruffleObject;
+
+@MessageResolution(receiverType = CharSXPToNativeArrayCall.class)
+public class CharSXPToNativeArrayCallMR implements RTruffleObject {
+
+    @Resolve(message = "EXECUTE")
+    public abstract static class CharSXPToNativeArrayCallExecute extends Node {
+        protected java.lang.Object access(CharSXPToNativeArrayCall receiver, Object[] arguments) {
+            return receiver.upCallsImpl.charSXPToNativeCharArray(arguments[0]);
+        }
+    }
+
+    @Resolve(message = "IS_EXECUTABLE")
+    public abstract static class CharSXPToNativeArrayCallIsExecutable extends Node {
+        protected Object access(@SuppressWarnings("unused") CharSXPToNativeArrayCall receiver) {
+            return true;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/FilesystemUtils.java
similarity index 97%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/FilesystemUtils.java
index ea6d2db107390757d02ebe5e82e258cab7a487f0..5a4a822f7aa4d7e32203f6ae8fcc0afddfdd5683 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/FilesystemUtils.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/FilesystemUtils.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.managed;
+package com.oracle.truffle.r.ffi.impl.managed;
 
 import java.nio.file.attribute.PosixFilePermission;
 import java.util.EnumSet;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java
similarity index 96%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java
index 988632777ab42c6b239cdbc8abcaa70a1c96119f..b9af2ea4969e361ee8bc6a1fd67097ccfab6be6c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_Base.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_Base.java
@@ -20,10 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.managed;
+package com.oracle.truffle.r.ffi.impl.managed;
 
-import static com.oracle.truffle.r.runtime.ffi.managed.FilesystemUtils.permissionsFromMode;
-import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported;
+import static com.oracle.truffle.r.ffi.impl.managed.FilesystemUtils.permissionsFromMode;
+import static com.oracle.truffle.r.ffi.impl.managed.Managed_RFFIFactory.unsupported;
 
 import java.io.IOException;
 import java.nio.file.FileAlreadyExistsException;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_LapackRFFI.java
similarity index 94%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_LapackRFFI.java
index 2b532244fe888586a9194c3d15a61281f6b4c56c..d6254bbab358e2d5ac7215af190a84f276ea3c76 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_LapackRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_LapackRFFI.java
@@ -20,9 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.managed;
+package com.oracle.truffle.r.ffi.impl.managed;
 
-import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported;
+import static com.oracle.truffle.r.ffi.impl.managed.Managed_RFFIFactory.unsupported;
 
 import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_PCRERFFI.java
similarity index 92%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_PCRERFFI.java
index 622b78cc0cdd864ca1bb89675b6b7b85f6c2a8df..7fe533a23ff5cf7b179199facffb450a39ae81ea 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_PCRERFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_PCRERFFI.java
@@ -20,9 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.managed;
+package com.oracle.truffle.r.ffi.impl.managed;
 
-import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported;
+import static com.oracle.truffle.r.ffi.impl.managed.Managed_RFFIFactory.unsupported;
 
 import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_REmbedRFFI.java
similarity index 92%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_REmbedRFFI.java
index 9d0a0a079fe7efb08d4405daf6eb71fa88c85f7a..17295f062ab15b32bdd50d689879c311ec4770b7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_REmbedRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_REmbedRFFI.java
@@ -20,9 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi.managed;
+package com.oracle.truffle.r.ffi.impl.managed;
 
-import static com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory.unsupported;
+import static com.oracle.truffle.r.ffi.impl.managed.Managed_RFFIFactory.unsupported;
 
 import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
 
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_RFFIFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_RFFIFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..7bc9be3b72b1bc2149d3eb8613dc0d20bdf04853
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/Managed_RFFIFactory.java
@@ -0,0 +1,267 @@
+/*
+ * 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.ffi.impl.managed;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+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.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+
+/**
+ * Operations that can be, at least partially, implemented in Java are implemented, other operations
+ * throw {@link RError}.
+ */
+public class Managed_RFFIFactory extends RFFIFactory {
+    @Override
+    protected RFFI createRFFI() {
+        CompilerAsserts.neverPartOfCompilation();
+        return new RFFI() {
+
+            @Override
+            public BaseRFFI getBaseRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new Managed_Base();
+            }
+
+            @Override
+            public LapackRFFI getLapackRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new Managed_LapackRFFI();
+            }
+
+            @Override
+            public RApplRFFI getRApplRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new RApplRFFI() {
+                    @Override
+                    public Dqrdc2Node createDqrdc2Node() {
+                        throw unsupported("dqrdc");
+                    }
+
+                    @Override
+                    public DqrcfNode createDqrcfNode() {
+                        throw unsupported("dqrcf");
+                    }
+
+                    @Override
+                    public DqrlsNode createDqrlsNode() {
+                        throw unsupported("dqrls");
+                    }
+
+                    @Override
+                    public DqrqtyNode createDqrqtyNode() {
+                        throw RInternalError.unimplemented();
+                    }
+
+                    @Override
+                    public DqrqyNode createDqrqyNode() {
+                        throw RInternalError.unimplemented();
+                    }
+
+                    @Override
+                    public DqrrsdNode createDqrrsdNode() {
+                        throw RInternalError.unimplemented();
+                    }
+
+                    @Override
+                    public DqrxbNode createDqrxbNode() {
+                        throw RInternalError.unimplemented();
+                    }
+                };
+            }
+
+            @Override
+            public StatsRFFI getStatsRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new StatsRFFI() {
+                    @Override
+                    public FactorNode createFactorNode() {
+                        throw unsupported("factor");
+                    }
+
+                    @Override
+                    public WorkNode createWorkNode() {
+                        throw unsupported("work");
+                    }
+                };
+            }
+
+            @Override
+            public ToolsRFFI getToolsRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new ToolsRFFI() {
+                    @Override
+                    public ParseRdNode createParseRdNode() {
+                        throw unsupported("parseRD");
+                    }
+                };
+            }
+
+            @Override
+            public CRFFI getCRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new CRFFI() {
+                    @Override
+                    public InvokeCNode createInvokeCNode() {
+                        throw unsupported("invoke");
+                    }
+                };
+            }
+
+            @Override
+            public CallRFFI getCallRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new CallRFFI() {
+                    @Override
+                    public InvokeCallNode createInvokeCallNode() {
+                        throw unsupported("native code invocation");
+                    }
+
+                    @Override
+                    public InvokeVoidCallNode createInvokeVoidCallNode() {
+                        throw unsupported("native code invocation");
+                    }
+                };
+            }
+
+            @Override
+            public UserRngRFFI getUserRngRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new UserRngRFFI() {
+                    @Override
+                    public InitNode createInitNode() {
+                        throw unsupported("user defined RNG");
+                    }
+
+                    @Override
+                    public RandNode createRandNode() {
+                        throw unsupported("user defined RNG");
+                    }
+
+                    @Override
+                    public NSeedNode createNSeedNode() {
+                        throw unsupported("user defined RNG");
+                    }
+
+                    @Override
+                    public SeedsNode createSeedsNode() {
+                        throw unsupported("user defined RNG");
+                    }
+                };
+            }
+
+            @Override
+            public PCRERFFI getPCRERFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new Managed_PCRERFFI();
+            }
+
+            @Override
+            public ZipRFFI getZipRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new ZipRFFI() {
+                    @Override
+                    public CompressNode createCompressNode() {
+                        throw unsupported("zip compression");
+                    }
+
+                    @Override
+                    public UncompressNode createUncompressNode() {
+                        throw unsupported("zip decompression");
+                    }
+                };
+            }
+
+            @Override
+            public DLLRFFI getDLLRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new DLLRFFI() {
+                    @Override
+                    public DLOpenNode createDLOpenNode() {
+                        throw unsupported("DLL open");
+                    }
+
+                    @Override
+                    public DLSymNode createDLSymNode() {
+                        throw unsupported("createDLSym");
+                    }
+
+                    @Override
+                    public DLCloseNode createDLCloseNode() {
+                        throw unsupported("createDLClose");
+                    }
+                };
+            }
+
+            @Override
+            public REmbedRFFI getREmbedRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new Managed_REmbedRFFI();
+            }
+
+            @Override
+            public MiscRFFI getMiscRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                return new MiscRFFI() {
+                    @Override
+                    public ExactSumNode createExactSumNode() {
+                        throw unsupported("exactsum");
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public ContextState newContextState() {
+        return new ContextState() {
+            @Override
+            public ContextState initialize(RContext context) {
+                return this;
+            }
+        };
+    }
+
+    @TruffleBoundary
+    static RError unsupported(String name) {
+        throw RError.error(RError.NO_CALLER, Message.GENERIC, String.format("Feature '%s' is not supported by managed FFI, i.e. it requires running native code.", name));
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..6907d5b19c3448001dcc9a014767323dd0b324f2
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/managed/package-info.java
@@ -0,0 +1,27 @@
+/*
+ * 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.
+ */
+/**
+ * The "Managed", aka no-native code, partial implementation of the
+ * {@link com.oracle.truffle.r.runtime.ffi.RFFI} interfaces.
+ */
+package com.oracle.truffle.r.ffi.impl.managed;
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NFIFunction.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NFIFunction.java
new file mode 100644
index 0000000000000000000000000000000000000000..90562d62fc373cda980e45bbbc08aba20c44768a
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/NFIFunction.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.nfi;
+
+import java.util.function.BiFunction;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.common.NativeFunction;
+
+/**
+ * Enumerates all the C functions that are internal to the implementation and called via Truffle
+ * NFI. Some of the functions are called directly, but most are called via a wrapper, typically to
+ * enable a callback with a complex result or, in the case of Fortran, to handle call by reference
+ * conveniently. The wrapper functions names are all of the form {@code call_xxx_function}, where
+ * {@code xxx} is the subsystem.
+ *
+ */
+enum NFIFunction implements NativeFunction {
+    // base
+    getpid("(): sint32"),
+    getcwd("([uint8], sint32): sint32"),
+    chdir("(string): sint32"),
+    mkdir("(string, sint32): sint32"),
+    readlink("((string, sint32): void, string): void", "call_base_"),
+    mkdtemp("([uint8]): sint32"),
+    chmod("(string, sint32): sint32"),
+    strtol("((sint64, sint32): void, string, sint32): void", "call_base_"),
+    uname("((string, string, string, string, string): void): void", "call_base_"),
+    glob("((string): void, string): void", "call_base_"),
+    // PCRE, N.B. The "pcre_" prefixes are actually direct calls
+    maketables("(): sint64", "pcre_"),
+    compile("((uint64, string, sint32): void, string, sint32, uint64): void", "call_pcre_"),
+    getcapturecount("(uint64, uint64): sint32", "call_pcre_"),
+    getcapturenames("((sint32, string): void, uint64, uint64): sint32", "call_pcre_"),
+    study("(uint64, sint32): void", "call_pcre_"),
+    exec("(uint64, uint64, [uint8], sint32, sint32, sint32, [sint32], sint32): sint32", "pcre_"),
+    // RAppl
+    dqrdc2("([double], sint32, sint32, sint32, double, [sint32], [double], [sint32], [double]): void", "call_appl_"),
+    dqrcf("([double], sint32, sint32, [double], [double], sint32, [double], [sint32]): void", "call_appl_"),
+    dqrls("([double], sint32, sint32, [double], sint32, double, [double], [double], [double], [sint32], [sint32], [double], [double]): void", "call_appl_"),
+    dqrqty("([double], sint32, sint32, [double], [double], sint32, [double]): void", "call_appl_"),
+    dqrqy("([double], sint32, sint32, [double], [double], sint32, [double]): void", "call_appl_"),
+    dqrrsd("([double], sint32, sint32, [double], [double], sint32, [double]): void", "call_appl_"),
+    dqrxb("([double], sint32, sint32, [double], [double], sint32, [double]): void", "call_appl_"),
+    // zip
+    compress("([uint8], [uint64], [uint8], uint64): sint32"),
+    uncompress("([uint8], [uint64], [uint8], uint64): sint32"),
+    // lapack
+    ilaver("([sint32]): void", "call_lapack_"),
+    dgeev("(uint8, uint8, sint32, [double], sint32, [double], [double], [double], sint32, [double], sint32, [double], sint32) : sint32", "call_lapack_"),
+    dgeqp3("(sint32, sint32, [double], sint32, [sint32], [double], [double], sint32) : sint32", "call_lapack_"),
+    dormq("(uint8, uint8, sint32, sint32, sint32, [double], sint32, [double], [double], sint32, [double], sint32) : sint32", "call_lapack_"),
+    dtrtrs("(uint8, uint8, uint8, sint32, sint32, [double], sint32, [double], sint32) : sint32", "call_lapack_"),
+    dgetrf("(sint32, sint32, [double], sint32, [sint32]) : sint32", "call_lapack_"),
+    dpotrf("(uint8, sint32, [double], sint32) : sint32", "call_lapack_"),
+    dpotri("(uint8, sint32, [double], sint32) : sint32", "call_lapack_"),
+    dpstrf("uint8, sint32, [double], sint32, [sint32], [sint32], double, [double]) : sint32", "call_lapack_"),
+    dgesv("(sint32, sint32, [double], sint32, [sint32], [double], sint32) : sint32", "call_lapack_"),
+    dlange("(uint8, sint32, sint32, [double], sint32, [double]) : double", "call_lapack_"),
+    dgecon("(uint8, sint32, [double], sint32, double, [double], [double], [sint32]) : sint32", "call_lapack_"),
+    dsyevr("(uint8, uint8, uint8, sint32, [double], sint32, double, double, sint32, sint32, double, [sint32], [double], [double], sint32, [sint32], [double], sint32, " +
+                    "[sint32], sint32) : sint32", "call_lapack_"),
+    // misc
+    exactSumFunc("([double], sint32, sint32, sint32): double"),
+    // stats
+    fft_factor("(sint32, [sint32], [sint32]): void", TruffleNFI_Utils::lookupAndBindStats),
+    fft_work("([double], sint32, sint32, sint32, sint32, [double], [sint32]): sint32", TruffleNFI_Utils::lookupAndBindStats);
+
+    private final int argumentCount;
+    private final String signature;
+    private final String callName;
+    private final BiFunction<String, String, TruffleObject> lookup;
+    @CompilationFinal private TruffleObject function;
+
+    NFIFunction(String signature) {
+        this.argumentCount = TruffleNFI_Utils.getArgCount(signature);
+        this.signature = signature;
+        this.callName = name();
+        this.lookup = TruffleNFI_Utils::lookupAndBind;
+    }
+
+    NFIFunction(String signature, BiFunction<String, String, TruffleObject> lookup) {
+        this.argumentCount = TruffleNFI_Utils.getArgCount(signature);
+        this.signature = signature;
+        this.callName = name();
+        this.lookup = lookup;
+    }
+
+    NFIFunction(String signature, String prefix) {
+        this.argumentCount = TruffleNFI_Utils.getArgCount(signature);
+        this.signature = signature;
+        this.callName = prefix + name();
+        this.lookup = TruffleNFI_Utils::lookupAndBind;
+    }
+
+    Node createMessage() {
+        CompilerAsserts.neverPartOfCompilation();
+        return Message.createExecute(argumentCount).createNode();
+    }
+
+    TruffleObject getFunction() {
+        if (function == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            function = lookup.apply(callName, signature);
+        }
+        return function;
+    }
+
+    @Override
+    public int getArgumentCount() {
+        return argumentCount;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java
new file mode 100644
index 0000000000000000000000000000000000000000..eb2cb9fa8784114a4243351aaacc16d828c5cfcb
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Base.java
@@ -0,0 +1,265 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.nfi;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.r.ffi.impl.interop.base.GlobResult;
+import com.oracle.truffle.r.ffi.impl.interop.base.ReadlinkResult;
+import com.oracle.truffle.r.ffi.impl.interop.base.StrtolResult;
+import com.oracle.truffle.r.ffi.impl.interop.base.UnameResult;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+
+public class TruffleNFI_Base implements BaseRFFI {
+
+    private static class TruffleNFI_GetpidNode extends TruffleNFI_DownCallNode implements GetpidNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.getpid;
+        }
+
+        @Override
+        public int execute() {
+            return (int) call();
+        }
+    }
+
+    private static final class TruffleNFI_GetwdNode extends TruffleNFI_DownCallNode implements GetwdNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.getcwd;
+        }
+
+        @TruffleBoundary
+        @Override
+        public String execute() {
+            byte[] buf = new byte[4096];
+            int result = (int) call(JavaInterop.asTruffleObject(buf), buf.length);
+            if (result == 0) {
+                return null;
+            } else {
+                int i = 0;
+                while (buf[i] != 0 && i < buf.length) {
+                    i++;
+                }
+                return new String(buf, 0, i);
+            }
+        }
+    }
+
+    private static class TruffleNFI_SetwdNode extends TruffleNFI_DownCallNode implements SetwdNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.chdir;
+        }
+
+        @Override
+        public int execute(String dir) {
+            return (int) call(dir);
+        }
+    }
+
+    private static class TruffleNFI_MkdirNode extends TruffleNFI_DownCallNode implements MkdirNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.mkdir;
+        }
+
+        @Override
+        public void execute(String dir, int mode) throws IOException {
+            if ((int) call(dir, mode) != 0) {
+                throw new IOException("mkdir " + dir + " failed");
+            }
+        }
+    }
+
+    private static class TruffleNFI_ReadlinkNode extends TruffleNFI_DownCallNode implements ReadlinkNode {
+        private static final int EINVAL = 22;
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.readlink;
+        }
+
+        @Override
+        public String execute(String path) throws IOException {
+            ReadlinkResult data = new ReadlinkResult();
+            call(data, path);
+            if (data.getLink() == null) {
+                if (data.getErrno() == EINVAL) {
+                    return path;
+                } else {
+                    // some other error
+                    throw new IOException("readlink failed: " + data.getErrno());
+                }
+            }
+            return data.getLink();
+        }
+    }
+
+    private static class TruffleNFI_MkdtempNode extends TruffleNFI_DownCallNode implements MkdtempNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.mkdtemp;
+        }
+
+        @TruffleBoundary
+        @Override
+        public String execute(String template) {
+            /*
+             * Not only must the (C) string end in XXXXXX it must also be null-terminated. Since it
+             * is modified by mkdtemp we must make a copy.
+             */
+            byte[] bytes = template.getBytes();
+            byte[] ztbytes = new byte[bytes.length + 1];
+            System.arraycopy(bytes, 0, ztbytes, 0, bytes.length);
+            ztbytes[bytes.length] = 0;
+            int result = (int) call(JavaInterop.asTruffleObject(ztbytes));
+            if (result == 0) {
+                return null;
+            } else {
+                return new String(ztbytes, 0, bytes.length);
+            }
+        }
+    }
+
+    private static class TruffleNFI_ChmodNode extends TruffleNFI_DownCallNode implements ChmodNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.chmod;
+        }
+
+        @Override
+        public int execute(String path, int mode) {
+            return (int) call(path, mode);
+        }
+    }
+
+    private static class TruffleNFI_StrolNode extends TruffleNFI_DownCallNode implements StrolNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.strtol;
+        }
+
+        @Override
+        public long execute(String s, int base) throws IllegalArgumentException {
+            StrtolResult data = new StrtolResult();
+            call(data, s, base);
+            if (data.getErrno() != 0) {
+                throw new IllegalArgumentException("strtol failure");
+            } else {
+                return data.getResult();
+            }
+        }
+    }
+
+    private static class TruffleNFI_UnameNode extends TruffleNFI_DownCallNode implements UnameNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.uname;
+        }
+
+        @Override
+        public UtsName execute() {
+            UnameResult data = new UnameResult();
+            call(data);
+            return data;
+        }
+    }
+
+    private static class TruffleNFI_GlobNode extends TruffleNFI_DownCallNode implements GlobNode {
+
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.glob;
+        }
+
+        @Override
+        public ArrayList<String> glob(String pattern) {
+            GlobResult data = new GlobResult();
+            call(data, pattern);
+            return data.getPaths();
+        }
+    }
+
+    @Override
+    public GetpidNode createGetpidNode() {
+        return new TruffleNFI_GetpidNode();
+    }
+
+    @Override
+    public GetwdNode createGetwdNode() {
+        return new TruffleNFI_GetwdNode();
+    }
+
+    @Override
+    public SetwdNode createSetwdNode() {
+        return new TruffleNFI_SetwdNode();
+    }
+
+    @Override
+    public MkdirNode createMkdirNode() {
+        return new TruffleNFI_MkdirNode();
+    }
+
+    @Override
+    public ReadlinkNode createReadlinkNode() {
+        return new TruffleNFI_ReadlinkNode();
+    }
+
+    @Override
+    public MkdtempNode createMkdtempNode() {
+        return new TruffleNFI_MkdtempNode();
+    }
+
+    @Override
+    public ChmodNode createChmodNode() {
+        return new TruffleNFI_ChmodNode();
+    }
+
+    @Override
+    public StrolNode createStrolNode() {
+        return new TruffleNFI_StrolNode();
+    }
+
+    @Override
+    public UnameNode createUnameNode() {
+        return new TruffleNFI_UnameNode();
+    }
+
+    @Override
+    public GlobNode createGlobNode() {
+        return new TruffleNFI_GlobNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_C.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_C.java
new file mode 100644
index 0000000000000000000000000000000000000000..e869188edb5536668845518bb77468b88a57c634
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_C.java
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.nfi;
+
+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.ForeignAccess;
+import com.oracle.truffle.api.interop.InteropException;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_CFactory.TruffleNFI_InvokeCNodeGen;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
+
+public class TruffleNFI_C implements CRFFI {
+    abstract static class TruffleNFI_InvokeCNode extends Node implements InvokeCNode {
+
+        @Child private Node bindNode = Message.createInvoke(1).createNode();
+
+        @Specialization(guards = "args.length == 0")
+        protected void invokeCall0(NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args, @SuppressWarnings("unused") boolean hasStrings,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                try {
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", "(): void");
+                    ForeignAccess.sendExecute(executeNode, callFunction);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 1")
+        protected void invokeCall1(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                try {
+                    Object[] nargs = new Object[args.length];
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs));
+                    ForeignAccess.sendExecute(executeNode, callFunction, nargs[0]);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 2")
+        protected void invokeCall2(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                try {
+                    Object[] nargs = new Object[args.length];
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs));
+                    ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1]);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 3")
+        protected void invokeCall3(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                try {
+                    Object[] nargs = new Object[args.length];
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs));
+                    ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1], nargs[2]);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+            }
+        }
+
+        @Specialization(guards = "args.length == 4")
+        protected void invokeCall4(NativeCallInfo nativeCallInfo, Object[] args, @SuppressWarnings("unused") boolean hasStrings,
+                        @Cached("createExecute(args.length)") Node executeNode) {
+            synchronized (TruffleNFI_Call.class) {
+                try {
+                    Object[] nargs = new Object[args.length];
+                    TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
+                                    nativeCallInfo.address.asTruffleObject(), "bind", getSignature(args, nargs));
+                    ForeignAccess.sendExecute(executeNode, callFunction, nargs[0], nargs[1], nargs[2], nargs[3]);
+                } catch (InteropException ex) {
+                    throw RInternalError.shouldNotReachHere(ex);
+                }
+            }
+        }
+
+        @Fallback
+        protected void invokeCallN(@SuppressWarnings("unused") NativeCallInfo nativeCallInfo, @SuppressWarnings("unused") Object[] args, @SuppressWarnings("unused") boolean hasStrings) {
+            synchronized (TruffleNFI_Call.class) {
+                throw RInternalError.unimplemented(".C (too many args)");
+            }
+        }
+
+        public static Node createExecute(int n) {
+            return Message.createExecute(n).createNode();
+        }
+    }
+
+    private static String getSignature(Object[] args, Object[] nargs) {
+        StringBuilder sb = new StringBuilder();
+        sb.append('(');
+        for (int i = 0; i < args.length; i++) {
+            Object arg = args[i];
+            if (arg instanceof int[]) {
+                sb.append("[sint32]");
+            } else if (arg instanceof double[]) {
+                sb.append("[double]");
+            } else if (arg instanceof byte[]) {
+                sb.append("[uint8]");
+            } else {
+                throw RInternalError.unimplemented(".C type: " + arg.getClass().getSimpleName());
+            }
+            nargs[i] = JavaInterop.asTruffleObject(arg);
+            if (i < args.length - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append("): void");
+        return sb.toString();
+    }
+
+    @Override
+    public InvokeCNode createInvokeCNode() {
+        return TruffleNFI_InvokeCNodeGen.create();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_CAccess.java
similarity index 82%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_CAccess.java
index a01fd2b14c353d479f6fad1ec6682c099694a080..acbc32f9818e8d1bc0100a9bb9b4d24aa994bd45 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_CAccess.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_CAccess.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
+package com.oracle.truffle.r.ffi.impl.nfi;
 
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
@@ -29,12 +29,9 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.DLL;
-import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.LibPaths;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 
 public class TruffleNFI_CAccess {
-    private static TruffleNFI_DLL.NFIHandle handle;
-
     public enum Function {
         READ_POINTER_INT("(pointer): sint32"),
         READ_ARRAY_INT("(pointer, sint64): sint32"),
@@ -46,15 +43,11 @@ public class TruffleNFI_CAccess {
 
         Function(String signature) {
             this.signature = signature;
-
         }
 
         public TruffleObject getSymbolFunction() {
-            if (handle == null) {
-                handle = (TruffleNFI_DLL.NFIHandle) DLLRFFI.DLOpenRootNode.create().getCallTarget().call(LibPaths.getBuiltinLibPath("caccess"), true, true);
-            }
             if (symbolFunction == null) {
-                DLL.SymbolHandle symbolHandle = (DLL.SymbolHandle) DLLRFFI.DLSymRootNode.create().getCallTarget().call(handle, cName());
+                SymbolHandle symbolHandle = DLL.findSymbol(cName(), null);
                 assert symbolHandle != null;
                 Node bind = Message.createInvoke(1).createNode();
                 try {
@@ -62,7 +55,6 @@ public class TruffleNFI_CAccess {
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
                 }
-
             }
             return symbolFunction;
         }
@@ -71,5 +63,4 @@ public class TruffleNFI_CAccess {
             return "caccess_" + name().toLowerCase();
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
similarity index 81%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
index 85f48b8d1d6c152574a5ab756c6fe8e8d6421956..4c1547d092df23ed89a23f5a5ca64df3d0070e19 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Call.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Call.java
@@ -20,11 +20,11 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
+package com.oracle.truffle.r.ffi.impl.nfi;
 
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCall;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceDownCallReturn;
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.traceEnabled;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceDownCall;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceDownCallReturn;
+import static com.oracle.truffle.r.ffi.impl.common.RFFIUtils.traceEnabled;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -34,23 +34,23 @@ import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.interop.RNullMR;
-import com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_CallFactory.TruffleNFI_InvokeCallNodeGen;
-import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
-import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
+import com.oracle.truffle.r.ffi.impl.common.RFFIUtils;
+import com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_CallFactory.TruffleNFI_InvokeCallNodeGen;
+import com.oracle.truffle.r.ffi.impl.upcalls.Callbacks;
+import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
 import com.oracle.truffle.r.runtime.ffi.RFFIVariables;
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 public class TruffleNFI_Call implements CallRFFI {
 
     private enum INIT_VAR_FUN {
-        OBJ("(sint32, object) : void"),
+        OBJ("(env, sint32, object) : void"),
         DOUBLE("(sint32, double): void"),
         STRING("(sint32, string): void"),
         INT("(sint32, sint32) : void");
@@ -86,26 +86,31 @@ public class TruffleNFI_Call implements CallRFFI {
             }
         }
         Node executeNode = Message.createExecute(2).createNode();
-        RFFIVariables[] variables = RFFIVariables.values();
-        for (int i = 0; i < variables.length; i++) {
-            RFFIVariables var = variables[i];
-            Object value = var.getValue();
-            if (value == null) {
-                continue;
-            }
-            try {
-                if (value instanceof Double) {
-                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.DOUBLE.initFunction, i, value);
-                } else if (value instanceof Integer) {
-                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.INT.initFunction, i, value);
-                } else if (value instanceof String) {
-                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.STRING.initFunction, i, value);
-                } else {
-                    ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.OBJ.initFunction, i, value);
+        RFFIVariables[] variables = RFFIVariables.initialize();
+        boolean isNullSetting = RContext.getRForeignAccessFactory().setIsNull(false);
+        try {
+            for (int i = 0; i < variables.length; i++) {
+                RFFIVariables var = variables[i];
+                Object value = var.getValue();
+                if (value == null || var.alwaysUpCall) {
+                    continue;
+                }
+                try {
+                    if (value instanceof Double) {
+                        ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.DOUBLE.initFunction, i, value);
+                    } else if (value instanceof Integer) {
+                        ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.INT.initFunction, i, value);
+                    } else if (value instanceof String) {
+                        ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.STRING.initFunction, i, value);
+                    } else {
+                        ForeignAccess.sendExecute(executeNode, INIT_VAR_FUN.OBJ.initFunction, i, value);
+                    }
+                } catch (Throwable t) {
+                    throw RInternalError.shouldNotReachHere(t);
                 }
-            } catch (Throwable t) {
-                throw RInternalError.shouldNotReachHere(t);
             }
+        } finally {
+            RContext.getRForeignAccessFactory().setIsNull(isNullSetting);
         }
     }
 
@@ -113,14 +118,13 @@ public class TruffleNFI_Call implements CallRFFI {
         Node bind = Message.createInvoke(1).createNode();
         Node executeNode = Message.createExecute(1).createNode();
         SymbolHandle symbolHandle = DLL.findSymbol("Rinternals_addCallback", null);
-        TruffleObject upCallsObject = JavaInterop.asTruffleObject(upCallsImpl);
-        Node readNode = Message.READ.createNode();
+
         try {
-            for (RFFIUpCallMethod upCallMethod : RFFIUpCallMethod.values()) {
-                Object upCallMethodObject = ForeignAccess.sendRead(readNode, upCallsObject, upCallMethod.name());
-                String addCallbackSignature = String.format("(sint32, %s): void", upCallMethod.nfiSignature);
+            Callbacks.createCalls(upCallsImpl);
+            for (Callbacks callback : Callbacks.values()) {
+                String addCallbackSignature = String.format("(env, sint32, %s): void", callback.nfiSignature);
                 TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature);
-                ForeignAccess.sendExecute(executeNode, addCallbackFunction, upCallMethod.ordinal(), upCallMethodObject);
+                ForeignAccess.sendExecute(executeNode, addCallbackFunction, callback.ordinal(), callback.call);
             }
         } catch (Throwable t) {
             throw RInternalError.shouldNotReachHere(t);
@@ -146,7 +150,6 @@ public class TruffleNFI_Call implements CallRFFI {
             this.funName = "return_" + name();
             this.executeNode = Message.createExecute(numArgs).createNode();
         }
-
     }
 
     private static void initReturnArray() {
@@ -217,8 +220,8 @@ public class TruffleNFI_Call implements CallRFFI {
             traceDownCall("initialize");
         }
         try {
-            initVariables();
             initCallbacks(upCallsImpl);
+            initVariables();
             initReturnArray();
         } finally {
             if (traceEnabled()) {
@@ -227,8 +230,8 @@ public class TruffleNFI_Call implements CallRFFI {
         }
     }
 
-    public abstract static class TruffleNFI_InvokeCallNode extends InvokeCallNode {
-        @Child Node bindNode = Message.createInvoke(1).createNode();
+    public abstract static class TruffleNFI_InvokeCallNode extends Node implements InvokeCallNode {
+        @Child private Node bindNode = Message.createInvoke(1).createNode();
 
         @Specialization(guards = "args.length == 0")
         protected Object invokeCall0(NativeCallInfo nativeCallInfo, Object[] args,
@@ -258,7 +261,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object): object");
-                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, args[0]);
                     return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
@@ -277,7 +280,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object): object");
-                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1]);
                     return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
@@ -296,7 +299,7 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object): object");
-                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], args[2]);
                     return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
@@ -315,8 +318,8 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object): object");
-                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]), JavaInterop.asTruffleObject(args[2]),
-                                    JavaInterop.asTruffleObject(args[3]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1], args[2],
+                                    args[3]);
                     return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
@@ -335,8 +338,8 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object): object");
-                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
-                                    JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1],
+                                    args[2], args[3], args[4]);
                     return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
@@ -355,8 +358,8 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object): object");
-                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
-                                    JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1],
+                                    args[2], args[3], args[4], args[5]);
                     return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
@@ -375,9 +378,9 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object): object");
-                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
-                                    JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]),
-                                    JavaInterop.asTruffleObject(args[6]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1],
+                                    args[2], args[3], args[4], args[5],
+                                    args[6]);
                     return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
@@ -396,9 +399,9 @@ public class TruffleNFI_Call implements CallRFFI {
                 try {
                     TruffleObject callFunction = (TruffleObject) ForeignAccess.sendInvoke(bindNode,
                                     nativeCallInfo.address.asTruffleObject(), "bind", "(object, object, object, object, object, object, object, object): object");
-                    result = ForeignAccess.sendExecute(executeNode, callFunction, JavaInterop.asTruffleObject(args[0]), JavaInterop.asTruffleObject(args[1]),
-                                    JavaInterop.asTruffleObject(args[2]), JavaInterop.asTruffleObject(args[3]), JavaInterop.asTruffleObject(args[4]), JavaInterop.asTruffleObject(args[5]),
-                                    JavaInterop.asTruffleObject(args[6]), JavaInterop.asTruffleObject(args[7]));
+                    result = ForeignAccess.sendExecute(executeNode, callFunction, args[0], args[1],
+                                    args[2], args[3], args[4], args[5],
+                                    args[6], args[7]);
                     return result;
                 } catch (InteropException ex) {
                     throw RInternalError.shouldNotReachHere(ex);
@@ -411,15 +414,14 @@ public class TruffleNFI_Call implements CallRFFI {
         public static Node createExecute(int n) {
             return Message.createExecute(n).createNode();
         }
-
     }
 
-    public static class TruffleNFI_InvokeVoidCallNode extends InvokeVoidCallNode {
+    private static class TruffleNFI_InvokeVoidCallNode extends Node implements InvokeVoidCallNode {
         private static final String CallVoid1Sig = "(object): void";
         private static final String CallVoid0Sig = "(): void";
-        @Child Node bindNode = Message.createInvoke(1).createNode();
-        @Child Node execute0Node = Message.createExecute(0).createNode();
-        @Child Node execute1Node = Message.createExecute(1).createNode();
+        @Child private Node bindNode = Message.createInvoke(1).createNode();
+        @Child private Node execute0Node = Message.createExecute(0).createNode();
+        @Child private Node execute1Node = Message.createExecute(1).createNode();
 
         @Override
         public void execute(NativeCallInfo nativeCallInfo, Object[] args) {
@@ -451,7 +453,7 @@ public class TruffleNFI_Call implements CallRFFI {
         if (traceEnabled()) {
             traceDownCall(name, args);
         }
-        boolean isNullSetting = RNullMR.setIsNull(false);
+        boolean isNullSetting = RContext.getRForeignAccessFactory().setIsNull(false);
         TruffleNFI_NativeArray.callEnter(callDepth);
         callDepth++;
         return isNullSetting;
@@ -462,7 +464,7 @@ public class TruffleNFI_Call implements CallRFFI {
             traceDownCallReturn(name, result);
         }
         TruffleNFI_NativeArray.callEnter(callDepth);
-        RNullMR.setIsNull(isNullSetting);
+        RContext.getRForeignAccessFactory().setIsNull(isNullSetting);
         callDepth--;
     }
 
@@ -475,5 +477,4 @@ public class TruffleNFI_Call implements CallRFFI {
     public InvokeVoidCallNode createInvokeVoidCallNode() {
         return new TruffleNFI_InvokeVoidCallNode();
     }
-
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DLL.java
similarity index 90%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DLL.java
index fe390032a4aa5e8877963447e0e3e8a63e3425b8..29acb7dd3326cb9fe09943a379022510621ffafd 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DLL.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
+package com.oracle.truffle.r.ffi.impl.nfi;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.TruffleLanguage.Env;
@@ -49,7 +49,7 @@ public class TruffleNFI_DLL implements DLLRFFI {
         }
     }
 
-    private static class TruffleNFI_DLOpenNode extends DLLRFFI.DLOpenNode {
+    private static class TruffleNFI_DLOpenNode extends Node implements DLLRFFI.DLOpenNode {
 
         @TruffleBoundary
         @Override
@@ -68,13 +68,13 @@ public class TruffleNFI_DLL implements DLLRFFI {
         sb.append(local ? "RTLD_LOCAL" : "RTLD_GLOBAL");
         sb.append('|');
         sb.append(now ? "RTLD_NOW" : "RTLD_LAZY");
-        sb.append(")");
-        sb.append(' ');
+        sb.append(") \"");
         sb.append(path);
+        sb.append('"');
         return sb.toString();
     }
 
-    private static class TruffleNFI_DLSymNode extends DLLRFFI.DLSymNode {
+    private static class TruffleNFI_DLSymNode extends Node implements DLLRFFI.DLSymNode {
 
         @Override
         public SymbolHandle execute(Object handle, String symbol) {
@@ -85,14 +85,14 @@ public class TruffleNFI_DLL implements DLLRFFI {
                 TruffleObject result = (TruffleObject) ForeignAccess.sendRead(lookupSymbol, nfiHandle.libHandle, symbol);
                 return new SymbolHandle(result);
             } catch (UnknownIdentifierException e) {
-                return null;
+                throw new UnsatisfiedLinkError();
             } catch (InteropException e) {
                 throw RInternalError.shouldNotReachHere();
             }
         }
     }
 
-    private static class TruffleNFI_DLCloseNode extends DLLRFFI.DLCloseNode {
+    private static class TruffleNFI_DLCloseNode extends Node implements DLLRFFI.DLCloseNode {
 
         @Override
         public int execute(Object handle) {
@@ -100,7 +100,6 @@ public class TruffleNFI_DLL implements DLLRFFI {
             // TODO
             return 0;
         }
-
     }
 
     @Override
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..49cbaf030ac49313f348b8048431bee700c7f1fa
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_DownCallNode.java
@@ -0,0 +1,61 @@
+/*
+ * 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.ffi.impl.nfi;
+
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.api.nodes.ExplodeLoop;
+import com.oracle.truffle.r.ffi.impl.common.DownCallNode;
+import com.oracle.truffle.r.ffi.impl.interop.NativeNACheck;
+
+public abstract class TruffleNFI_DownCallNode extends DownCallNode<NFIFunction> {
+
+    @Override
+    protected final TruffleObject getTarget() {
+        return getFunction().getFunction();
+    }
+
+    @SuppressWarnings("cast")
+    @Override
+    @ExplodeLoop
+    protected void wrapArguments(Object[] args) {
+        for (int i = 0; i < args.length; i++) {
+            Object obj = args[i];
+            if (obj instanceof double[]) {
+                args[i] = JavaInterop.asTruffleObject((double[]) obj);
+            } else if (obj instanceof int[] || obj == null) {
+                args[i] = JavaInterop.asTruffleObject((int[]) obj);
+            }
+        }
+    }
+
+    @Override
+    @ExplodeLoop
+    protected void finishArguments(Object[] args) {
+        for (Object obj : args) {
+            if (obj instanceof NativeNACheck<?>) {
+                ((NativeNACheck<?>) obj).close();
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Lapack.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Lapack.java
new file mode 100644
index 0000000000000000000000000000000000000000..af4e79315c5192ddc5b84582b02ec928c60052dc
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Lapack.java
@@ -0,0 +1,250 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.nfi;
+
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+
+public class TruffleNFI_Lapack implements LapackRFFI {
+
+    private static class TruffleNFI_IlaverNode extends TruffleNFI_DownCallNode implements IlaverNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.ilaver;
+        }
+
+        @Override
+        public void execute(int[] version) {
+            call(version);
+        }
+    }
+
+    private static class TruffleNFI_DgeevNode extends TruffleNFI_DownCallNode implements DgeevNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dgeev;
+        }
+
+        @Override
+        public int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork) {
+            return (int) call(jobVL, jobVR, n, a, lda, wr, wi, vl, ldvl, vr, ldvr, work, lwork);
+        }
+    }
+
+    private static class TruffleNFI_Dgeqp3Node extends TruffleNFI_DownCallNode implements Dgeqp3Node {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dgeqp3;
+        }
+
+        @Override
+        public int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork) {
+            return (int) call(m, n, a, lda, jpvt, tau, work, lwork);
+        }
+    }
+
+    private static class TruffleNFI_DormqrNode extends TruffleNFI_DownCallNode implements DormqrNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dormq;
+        }
+
+        @Override
+        public int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork) {
+            return (int) call(side, trans, m, n, k, a, lda, tau, c, ldc, work, lwork);
+        }
+    }
+
+    private static class TruffleNFI_DtrtrsNode extends TruffleNFI_DownCallNode implements DtrtrsNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dtrtrs;
+        }
+
+        @Override
+        public int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb) {
+            return (int) call(uplo, trans, diag, n, nrhs, a, lda, b, ldb);
+        }
+    }
+
+    private static class TruffleNFI_DgetrfNode extends TruffleNFI_DownCallNode implements DgetrfNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dgetrf;
+        }
+
+        @Override
+        public int execute(int m, int n, double[] a, int lda, int[] ipiv) {
+            return (int) call(m, n, a, lda, ipiv);
+        }
+    }
+
+    private static class TruffleNFI_DpotrfNode extends TruffleNFI_DownCallNode implements DpotrfNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dpotrf;
+        }
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda) {
+            return (int) call(uplo, n, a, lda);
+        }
+    }
+
+    private static class TruffleNFI_DpotriNode extends TruffleNFI_DownCallNode implements DpotriNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dpotri;
+        }
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda) {
+            return (int) call(uplo, n, a, lda);
+        }
+    }
+
+    private static class TruffleNFI_DpstrfNode extends TruffleNFI_DownCallNode implements DpstrfNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dpstrf;
+        }
+
+        @Override
+        public int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work) {
+            return (int) call(uplo, n, a, lda, piv, rank, tol, work);
+        }
+    }
+
+    private static class TruffleNFI_DgesvNode extends TruffleNFI_DownCallNode implements DgesvNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dgesv;
+        }
+
+        @Override
+        public int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb) {
+            return (int) call(n, nrhs, a, lda, ipiv, b, ldb);
+        }
+    }
+
+    private static class TruffleNFI_DlangeNode extends TruffleNFI_DownCallNode implements DlangeNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dlange;
+        }
+
+        @Override
+        public double execute(char norm, int m, int n, double[] a, int lda, double[] work) {
+            return (double) call(norm, m, n, a, lda, work);
+        }
+    }
+
+    private static class TruffleNFI_DgeconNode extends TruffleNFI_DownCallNode implements DgeconNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dgecon;
+        }
+
+        @Override
+        public int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork) {
+            return (int) call(norm, n, a, lda, anorm, rcond, work, iwork);
+        }
+    }
+
+    private static class TruffleNFI_DsyevrNode extends TruffleNFI_DownCallNode implements DsyevrNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dsyevr;
+        }
+
+        @Override
+        public int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, double[] z, int ldz, int[] isuppz,
+                        double[] work, int lwork, int[] iwork, int liwork) {
+            return (int) call(jobz, range, uplo, n, a, lda, vl, vu, il, iu, abstol, m, w, z, ldz, isuppz, work, lwork, iwork, liwork);
+        }
+    }
+
+    @Override
+    public IlaverNode createIlaverNode() {
+        return new TruffleNFI_IlaverNode();
+    }
+
+    @Override
+    public DgeevNode createDgeevNode() {
+        return new TruffleNFI_DgeevNode();
+    }
+
+    @Override
+    public Dgeqp3Node createDgeqp3Node() {
+        return new TruffleNFI_Dgeqp3Node();
+    }
+
+    @Override
+    public DormqrNode createDormqrNode() {
+        return new TruffleNFI_DormqrNode();
+    }
+
+    @Override
+    public DtrtrsNode createDtrtrsNode() {
+        return new TruffleNFI_DtrtrsNode();
+    }
+
+    @Override
+    public DgetrfNode createDgetrfNode() {
+        return new TruffleNFI_DgetrfNode();
+    }
+
+    @Override
+    public DpotrfNode createDpotrfNode() {
+        return new TruffleNFI_DpotrfNode();
+    }
+
+    @Override
+    public DpotriNode createDpotriNode() {
+        return new TruffleNFI_DpotriNode();
+    }
+
+    @Override
+    public DpstrfNode createDpstrfNode() {
+        return new TruffleNFI_DpstrfNode();
+    }
+
+    @Override
+    public DgesvNode createDgesvNode() {
+        return new TruffleNFI_DgesvNode();
+    }
+
+    @Override
+    public DlangeNode createDlangeNode() {
+        return new TruffleNFI_DlangeNode();
+    }
+
+    @Override
+    public DgeconNode createDgeconNode() {
+        return new TruffleNFI_DgeconNode();
+    }
+
+    @Override
+    public DsyevrNode createDsyevrNode() {
+        return new TruffleNFI_DsyevrNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Misc.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Misc.java
new file mode 100644
index 0000000000000000000000000000000000000000..80503d78cb7dfafeda971a96041f4690fbb6981d
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Misc.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.nfi;
+
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+
+public class TruffleNFI_Misc implements MiscRFFI {
+
+    private static final class TruffleNFI_ExactSumNode extends TruffleNFI_DownCallNode implements ExactSumNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.exactSumFunc;
+        }
+
+        @Override
+        public double execute(double[] values, boolean hasNa, boolean naRm) {
+            return (double) call(values, values.length, hasNa ? 1 : 0, naRm ? 1 : 0);
+        }
+    }
+
+    @Override
+    public ExactSumNode createExactSumNode() {
+        return new TruffleNFI_ExactSumNode();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_NativeArray.java
similarity index 99%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_NativeArray.java
index 8a69a8d47b5accd9cc8c0fd8e45bfaa5538a28ff..b0b4566be2c7b6fb30f7677599e0aa5c07bcae55 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_NativeArray.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_NativeArray.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
+package com.oracle.truffle.r.ffi.impl.nfi;
 
 import java.util.Arrays;
 
@@ -163,5 +163,4 @@ public class TruffleNFI_NativeArray {
         tableHwm++;
         return t.arrayAddress;
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PCRE.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PCRE.java
new file mode 100644
index 0000000000000000000000000000000000000000..8a8326f9d4345d99e5111237c3dbc05eb12f75be
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PCRE.java
@@ -0,0 +1,136 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.nfi;
+
+import java.nio.charset.StandardCharsets;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.r.ffi.impl.interop.pcre.CaptureNamesResult;
+import com.oracle.truffle.r.ffi.impl.interop.pcre.CompileResult;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+
+public class TruffleNFI_PCRE implements PCRERFFI {
+
+    private static class TruffleNFI_MaketablesNode extends TruffleNFI_DownCallNode implements MaketablesNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.maketables;
+        }
+
+        @Override
+        public long execute() {
+            return (long) call();
+        }
+    }
+
+    private static class TruffleNFI_GetCaptureCountNode extends TruffleNFI_DownCallNode implements GetCaptureCountNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.getcapturecount;
+        }
+
+        @Override
+        public int execute(long code, long extra) {
+            return (int) call(code, extra);
+        }
+    }
+
+    private static class TruffleNFI_GetCaptureNamesNode extends TruffleNFI_DownCallNode implements GetCaptureNamesNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.getcapturenames;
+        }
+
+        @Override
+        public String[] execute(long code, long extra, int captureCount) {
+            CaptureNamesResult data = new CaptureNamesResult(captureCount);
+            int result = (int) call(data, code, extra);
+            if (result < 0) {
+                CompilerDirectives.transferToInterpreter();
+                throw RError.error(RError.NO_CALLER, RError.Message.WRONG_PCRE_INFO, result);
+            } else {
+                return data.getCaptureNames();
+            }
+        }
+    }
+
+    private static class TruffleNFI_CompileNode extends TruffleNFI_DownCallNode implements CompileNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.compile;
+        }
+
+        @Override
+        public Result execute(String pattern, int options, long tables) {
+            CompileResult data = new CompileResult();
+            call(data, pattern, options, tables);
+            return data.getResult();
+        }
+    }
+
+    private static class TruffleNFI_ExecNode extends TruffleNFI_DownCallNode implements ExecNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.exec;
+        }
+
+        @Override
+        public int execute(long code, long extra, String subject, int offset, int options, int[] ovector) {
+            byte[] subjectBytes = subject.getBytes(StandardCharsets.UTF_8);
+            return (int) call(code, extra, JavaInterop.asTruffleObject(subjectBytes), subjectBytes.length, offset, options, ovector, ovector.length);
+        }
+    }
+
+    @Override
+    public MaketablesNode createMaketablesNode() {
+        return new TruffleNFI_MaketablesNode();
+    }
+
+    @Override
+    public CompileNode createCompileNode() {
+        return new TruffleNFI_CompileNode();
+    }
+
+    @Override
+    public GetCaptureCountNode createGetCaptureCountNode() {
+        return new TruffleNFI_GetCaptureCountNode();
+    }
+
+    @Override
+    public GetCaptureNamesNode createGetCaptureNamesNode() {
+        return new TruffleNFI_GetCaptureNamesNode();
+    }
+
+    @Override
+    public StudyNode createStudyNode() {
+        throw RInternalError.unimplemented();
+    }
+
+    @Override
+    public ExecNode createExecNode() {
+        return new TruffleNFI_ExecNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PkgInit.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PkgInit.java
new file mode 100644
index 0000000000000000000000000000000000000000..e8dd18db02632ca1d128f6f625d08eaa3a87df76
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_PkgInit.java
@@ -0,0 +1,112 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.nfi;
+
+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.nodes.Node;
+import com.oracle.truffle.r.ffi.impl.common.Generic_PkgInit;
+import com.oracle.truffle.r.ffi.impl.common.PkgInitUpCalls;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.ForceSymbolsCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.GetCCallableCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.RegisterCCallableCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.RegisterRoutinesCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.SetDotSymbolValuesCall;
+import com.oracle.truffle.r.ffi.impl.interop.pkginit.UseDynamicSymbolsCall;
+import com.oracle.truffle.r.runtime.RError;
+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;
+
+public final class TruffleNFI_PkgInit extends Generic_PkgInit {
+
+    private static final String SETSYMBOL_SIGNATURE = "(object, sint32, uint64, sint32): object";
+    private static TruffleObject setSymbolFunction;
+
+    static void initialize() {
+        Node bind = Message.createInvoke(1).createNode();
+        SymbolHandle symbolHandle = DLL.findSymbol("Rdynload_init", null);
+        Node executeNode = Message.createExecute(2).createNode();
+        TruffleNFI_PkgInit trufflePkgInit = new TruffleNFI_PkgInit();
+        try {
+            for (PkgInitUpCalls.Index upCall : PkgInitUpCalls.Index.values()) {
+                String addCallbackSignature = String.format("(env, sint32, %s): void", upCall.signature);
+                TruffleObject addCallbackFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", addCallbackSignature);
+                TruffleObject callbackObject;
+                switch (upCall) {
+                    case registerRoutines:
+                        callbackObject = new RegisterRoutinesCall(trufflePkgInit);
+                        break;
+                    case setDotSymbolValues:
+                        callbackObject = new SetDotSymbolValuesCall(trufflePkgInit);
+                        break;
+
+                    case useDynamicSymbols:
+                        callbackObject = new UseDynamicSymbolsCall(trufflePkgInit);
+                        break;
+                    case forceSymbols:
+                        callbackObject = new ForceSymbolsCall(trufflePkgInit);
+                        break;
+                    case registerCCallable:
+                        callbackObject = new RegisterCCallableCall(trufflePkgInit);
+                        break;
+                    case getCCallable:
+                        callbackObject = new GetCCallableCall(trufflePkgInit);
+                        break;
+                    default:
+                        throw RInternalError.shouldNotReachHere();
+                }
+                ForeignAccess.sendExecute(executeNode, addCallbackFunction, upCall.ordinal(), callbackObject);
+            }
+            symbolHandle = DLL.findSymbol("Rdynload_setSymbol", null);
+            setSymbolFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", SETSYMBOL_SIGNATURE);
+        } catch (Throwable t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+
+    @Override
+    public Object getCCallable(String pkgName, String functionName) {
+        DLLInfo lib = DLL.safeFindLibrary(pkgName);
+        CEntry result = lib.lookupCEntry(functionName);
+        if (result == null) {
+            throw RError.error(RError.NO_CALLER, RError.Message.UNKNOWN_OBJECT, functionName);
+        }
+        return result.address.asAddress();
+    }
+
+    @Override
+    protected Object setSymbol(DLLInfo dllInfo, int nstOrd, long routines, int index) {
+        Node executeNode = Message.createExecute(4).createNode();
+        try {
+            DotSymbol result = (DotSymbol) ForeignAccess.sendExecute(executeNode, setSymbolFunction, dllInfo, nstOrd, routines, index);
+            return result;
+        } catch (Throwable t) {
+            throw RInternalError.shouldNotReachHere(t);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RAppl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RAppl.java
new file mode 100644
index 0000000000000000000000000000000000000000..5210f3ec9d8fbdc869c7fa0d13bc0511e75aa26d
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RAppl.java
@@ -0,0 +1,147 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.nfi;
+
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+
+public class TruffleNFI_RAppl implements RApplRFFI {
+
+    private static class TruffleNFI_Dqrdc2Node extends TruffleNFI_DownCallNode implements Dqrdc2Node {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dqrdc2;
+        }
+
+        @Override
+        public void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work) {
+            call(x, ldx, n, p, tol, rank, qraux, pivot, work);
+        }
+    }
+
+    private static class TruffleNFI_DqrcfNode extends TruffleNFI_DownCallNode implements DqrcfNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dqrcf;
+        }
+
+        @Override
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info) {
+            call(x, n, k, qraux, y, ny, b, info);
+        }
+    }
+
+    private static class TruffleNFI_DqrlsNode extends TruffleNFI_DownCallNode implements DqrlsNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dqrls;
+        }
+
+        @Override
+        public void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work) {
+            call(x, n, p, y, ny, tol, b, rsd, qty, k, jpvt, qraux, work);
+        }
+    }
+
+    private static class TruffleNFI_DqrqtyNode extends TruffleNFI_DownCallNode implements DqrqtyNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dqrqty;
+        }
+
+        @Override
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] qty) {
+            call(x, n, k, qraux, y, ny, qty);
+        }
+    }
+
+    private static class TruffleNFI_DqrqyNode extends TruffleNFI_DownCallNode implements DqrqyNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dqrqy;
+        }
+
+        @Override
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] qy) {
+            call(x, n, k, qraux, y, ny, qy);
+        }
+    }
+
+    private static class TruffleNFI_DqrrsdNode extends TruffleNFI_DownCallNode implements DqrrsdNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dqrrsd;
+        }
+
+        @Override
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] rsd) {
+            call(x, n, k, qraux, y, ny, rsd);
+        }
+    }
+
+    private static class TruffleNFI_DqrxbNode extends TruffleNFI_DownCallNode implements DqrxbNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.dqrxb;
+        }
+
+        @Override
+        public void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] xb) {
+            call(x, n, k, qraux, y, ny, xb);
+        }
+    }
+
+    @Override
+    public Dqrdc2Node createDqrdc2Node() {
+        return new TruffleNFI_Dqrdc2Node();
+    }
+
+    @Override
+    public DqrcfNode createDqrcfNode() {
+        return new TruffleNFI_DqrcfNode();
+    }
+
+    @Override
+    public DqrlsNode createDqrlsNode() {
+        return new TruffleNFI_DqrlsNode();
+    }
+
+    @Override
+    public DqrqtyNode createDqrqtyNode() {
+        return new TruffleNFI_DqrqtyNode();
+    }
+
+    @Override
+    public DqrqyNode createDqrqyNode() {
+        return new TruffleNFI_DqrqyNode();
+    }
+
+    @Override
+    public DqrrsdNode createDqrrsdNode() {
+        return new TruffleNFI_DqrrsdNode();
+    }
+
+    @Override
+    public DqrxbNode createDqrxbNode() {
+        return new TruffleNFI_DqrxbNode();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_REmbed.java
similarity index 96%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_REmbed.java
index 798001ff8989ec95277b675732adea59fc3471a3..fec06c845d5e687a51002a2588e7e6c70aa875c4 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_REmbed.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_REmbed.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
+package com.oracle.truffle.r.ffi.impl.nfi;
 
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
@@ -30,13 +30,11 @@ public class TruffleNFI_REmbed implements REmbedRFFI {
     @Override
     public void suicide(String x) {
         throw RInternalError.unimplemented();
-
     }
 
     @Override
     public void cleanUp(int type, int x, int y) {
         throw RInternalError.unimplemented();
-
     }
 
     @Override
@@ -47,13 +45,10 @@ public class TruffleNFI_REmbed implements REmbedRFFI {
     @Override
     public void writeConsole(String x) {
         throw RInternalError.unimplemented();
-
     }
 
     @Override
     public void writeErrConsole(String x) {
         throw RInternalError.unimplemented();
-
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RFFIFactory.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RFFIFactory.java
new file mode 100644
index 0000000000000000000000000000000000000000..b141f8be4e4a0ea588c41fd4fe527e901e99170f
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_RFFIFactory.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.nfi;
+
+import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.r.ffi.impl.common.LibPaths;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextState;
+import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.CRFFI;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
+import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
+import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
+import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+
+public class TruffleNFI_RFFIFactory extends RFFIFactory {
+
+    private static class ContextStateImpl implements RContext.ContextState {
+        @Override
+        public ContextState initialize(RContext context) {
+            String librffiPath = LibPaths.getBuiltinLibPath("R");
+            if (context.isInitial()) {
+                DLL.loadLibR(librffiPath);
+            } else {
+                // force initialization of NFI
+                DLLRFFI.DLOpenRootNode.create(context).call(librffiPath, false, false);
+            }
+            return this;
+        }
+    }
+
+    @Override
+    public ContextState newContextState() {
+        return new ContextStateImpl();
+    }
+
+    @Override
+    protected RFFI createRFFI() {
+        CompilerAsserts.neverPartOfCompilation();
+        return new RFFI() {
+
+            @CompilationFinal private CRFFI cRFFI;
+
+            @Override
+            public CRFFI getCRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (cRFFI == null) {
+                    cRFFI = new TruffleNFI_C();
+                }
+                return cRFFI;
+            }
+
+            @CompilationFinal private BaseRFFI baseRFFI;
+
+            @Override
+            public BaseRFFI getBaseRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (baseRFFI == null) {
+                    baseRFFI = new TruffleNFI_Base();
+                }
+                return baseRFFI;
+            }
+
+            @CompilationFinal private CallRFFI callRFFI;
+
+            @Override
+            public CallRFFI getCallRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (callRFFI == null) {
+                    callRFFI = new TruffleNFI_Call();
+                }
+                return callRFFI;
+            }
+
+            @CompilationFinal private DLLRFFI dllRFFI;
+
+            @Override
+            public DLLRFFI getDLLRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                CompilerAsserts.neverPartOfCompilation();
+                if (dllRFFI == null) {
+                    dllRFFI = new TruffleNFI_DLL();
+                }
+                return dllRFFI;
+            }
+
+            @CompilationFinal private UserRngRFFI userRngRFFI;
+
+            @Override
+            public UserRngRFFI getUserRngRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (userRngRFFI == null) {
+                    userRngRFFI = new TruffleNFI_UserRng();
+                }
+                return userRngRFFI;
+            }
+
+            @CompilationFinal private ZipRFFI zipRFFI;
+
+            @Override
+            public ZipRFFI getZipRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (zipRFFI == null) {
+                    zipRFFI = new TruffleNFI_Zip();
+                }
+                return zipRFFI;
+            }
+
+            @CompilationFinal private PCRERFFI pcreRFFI;
+
+            @Override
+            public PCRERFFI getPCRERFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (pcreRFFI == null) {
+                    pcreRFFI = new TruffleNFI_PCRE();
+                }
+                return pcreRFFI;
+            }
+
+            @CompilationFinal private LapackRFFI lapackRFFI;
+
+            @Override
+            public LapackRFFI getLapackRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (lapackRFFI == null) {
+                    lapackRFFI = new TruffleNFI_Lapack();
+                }
+                return lapackRFFI;
+            }
+
+            @CompilationFinal private RApplRFFI rApplRFFI;
+
+            @Override
+            public RApplRFFI getRApplRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (rApplRFFI == null) {
+                    rApplRFFI = new TruffleNFI_RAppl();
+                }
+                return rApplRFFI;
+            }
+
+            @CompilationFinal private StatsRFFI statsRFFI;
+
+            @Override
+            public StatsRFFI getStatsRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (statsRFFI == null) {
+                    statsRFFI = new TruffleNFI_Stats();
+                }
+                return statsRFFI;
+            }
+
+            @CompilationFinal private ToolsRFFI toolsRFFI;
+
+            @Override
+            public ToolsRFFI getToolsRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (toolsRFFI == null) {
+                    toolsRFFI = new TruffleNFI_Tools();
+                }
+                return toolsRFFI;
+            }
+
+            private REmbedRFFI rEmbedRFFI;
+
+            @Override
+            public REmbedRFFI getREmbedRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (rEmbedRFFI == null) {
+                    rEmbedRFFI = new TruffleNFI_REmbed();
+                }
+                return rEmbedRFFI;
+            }
+
+            private MiscRFFI miscRFFI;
+
+            @Override
+            public MiscRFFI getMiscRFFI() {
+                CompilerAsserts.neverPartOfCompilation();
+                if (miscRFFI == null) {
+                    miscRFFI = new TruffleNFI_Misc();
+                }
+                return miscRFFI;
+            }
+        };
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Stats.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Stats.java
new file mode 100644
index 0000000000000000000000000000000000000000..217fdeb5304e3057bd3f61462a89a66799c0c2b3
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Stats.java
@@ -0,0 +1,62 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.nfi;
+
+import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
+
+public class TruffleNFI_Stats implements StatsRFFI {
+
+    private static class TruffleNFI_FactorNode extends TruffleNFI_DownCallNode implements FactorNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.fft_factor;
+        }
+
+        @Override
+        public void execute(int n, int[] pmaxf, int[] pmaxp) {
+            call(n, pmaxf, pmaxp);
+        }
+    }
+
+    private static class TruffleNFI_WorkNode extends TruffleNFI_DownCallNode implements WorkNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.fft_work;
+        }
+
+        @Override
+        public int execute(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork) {
+            return (int) call(a, nseg, n, nspn, isn, work, iwork);
+        }
+    }
+
+    @Override
+    public FactorNode createFactorNode() {
+        return new TruffleNFI_FactorNode();
+    }
+
+    @Override
+    public WorkNode createWorkNode() {
+        return new TruffleNFI_WorkNode();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Tools.java
similarity index 77%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Tools.java
index dd72b7e5e0c62a09f94850a41a4c0dcb20711f06..d9fa3345f779223257c442449a99c63ca25c2365 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Tools.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Tools.java
@@ -20,51 +20,29 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
-
-import java.io.IOException;
+package com.oracle.truffle.r.ffi.impl.nfi;
 
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.nodes.ffi.RFFIUtils;
+import com.oracle.truffle.r.ffi.impl.common.Generic_Tools;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.ffi.impl.interop.tools.RConnGetCCall;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.DLL;
-import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.generic.Generic_Tools;
+import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 
 public class TruffleNFI_Tools implements ToolsRFFI {
 
     private static class TruffleNFI_ToolsRFFINode extends Generic_Tools.Generic_ToolsRFFINode {
-        private interface RConnGetC {
-            int getc(RConnection conn);
-        }
-
-        private static class RConnGetCImpl implements RConnGetC, RTruffleObject {
-            @Override
-            public int getc(RConnection conn) {
-                RFFIUtils.traceUpCall("getc");
-                try {
-                    int r = conn.getc();
-                    RFFIUtils.traceUpCallReturn("getc", r);
-                    return r;
-                } catch (IOException ex) {
-                    return -1;
-                }
-            }
-        }
-
         private static boolean initialized;
 
         @Child private DLLRFFI.DLSymNode dysymNode = DLLRFFI.DLSymNode.create();
@@ -76,7 +54,7 @@ public class TruffleNFI_Tools implements ToolsRFFI {
                 initCallback();
                 initialized = true;
             }
-            return super.execute(con, srcfile, verbose, fragment, basename, warningCalls, JavaInterop.asTruffleObject(macros), warndups);
+            return super.execute(con, srcfile, verbose, fragment, basename, warningCalls, macros, warndups);
         }
 
         private void initCallback() {
@@ -87,12 +65,11 @@ public class TruffleNFI_Tools implements ToolsRFFI {
             Node bind = Message.createInvoke(1).createNode();
             Node executeNode = Message.createExecute(1).createNode();
             try {
-                TruffleObject function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", "((object): sint32): void");
-                ForeignAccess.sendExecute(executeNode, function, new RConnGetCImpl());
+                TruffleObject function = (TruffleObject) ForeignAccess.sendInvoke(bind, symbolHandle.asTruffleObject(), "bind", "(env, (object): sint32): void");
+                ForeignAccess.sendExecute(executeNode, function, new RConnGetCCall());
             } catch (InteropException t) {
                 throw RInternalError.shouldNotReachHere(t);
             }
-
         }
     }
 
@@ -100,5 +77,4 @@ public class TruffleNFI_Tools implements ToolsRFFI {
     public ParseRdNode createParseRdNode() {
         return new TruffleNFI_ToolsRFFINode();
     }
-
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UpCallsRFFIImpl.java
similarity index 92%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UpCallsRFFIImpl.java
index e302c637ca4d9da0529b84a931890bfa050a152a..02cf2c4eaaccbb302ba9e42f94a99044703d0108 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_UpCallsRFFIImpl.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UpCallsRFFIImpl.java
@@ -20,16 +20,16 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
+package com.oracle.truffle.r.ffi.impl.nfi;
 
-import com.oracle.truffle.r.nodes.ffi.JavaUpCallsRFFIImpl;
+import com.oracle.truffle.r.ffi.impl.common.JavaUpCallsRFFIImpl;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
     @Override
     public Object Rf_mkCharLenCE(Object bytes, int len, int encoding) {
-        // "bytes" is actually a TruffleObject denoting a native pointer
+        // "bytes" is actually a Long unboxed from a NativePointer
         // TODO: handle encoding properly
         return CharSXPWrapper.create(TruffleNFI_Utils.convertCstring(bytes, len));
     }
@@ -63,7 +63,7 @@ public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
     public Object REAL(Object x) {
         long arrayAddress = TruffleNFI_NativeArray.findArray(x);
         if (arrayAddress == 0) {
-            Object array = super.LOGICAL(x);
+            Object array = super.REAL(x);
             arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.REALSXP);
         } else {
             TruffleNFI_Call.returnArrayExisting(SEXPTYPE.REALSXP, arrayAddress);
@@ -76,7 +76,7 @@ public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
     public Object RAW(Object x) {
         long arrayAddress = TruffleNFI_NativeArray.findArray(x);
         if (arrayAddress == 0) {
-            Object array = super.LOGICAL(x);
+            Object array = super.RAW(x);
             arrayAddress = TruffleNFI_NativeArray.recordArray(x, array, SEXPTYPE.RAWSXP);
         } else {
             TruffleNFI_Call.returnArrayExisting(SEXPTYPE.RAWSXP, arrayAddress);
@@ -96,5 +96,4 @@ public class TruffleNFI_UpCallsRFFIImpl extends JavaUpCallsRFFIImpl {
         }
         return x;
     }
-
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UserRng.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UserRng.java
new file mode 100644
index 0000000000000000000000000000000000000000..e68c870b4a31a4e5e71819cc8f70b037a985727d
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_UserRng.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2017, 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.ffi.impl.nfi;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+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.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.rng.user.UserRNG.Function;
+
+public class TruffleNFI_UserRng implements UserRngRFFI {
+
+    private abstract static class RNGNode extends Node {
+
+        @CompilationFinal protected Node message;
+        @CompilationFinal protected Node readPointerNode = Message.createExecute(1).createNode();
+        @CompilationFinal protected TruffleObject targetFunction;
+
+        protected void init(Function function, String signature) {
+            if (message == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                message = Message.createExecute(TruffleNFI_Utils.getArgCount(signature)).createNode();
+            }
+            if (targetFunction == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                Node bind = Message.createInvoke(1).createNode();
+                try {
+                    targetFunction = (TruffleObject) ForeignAccess.sendInvoke(bind, function.getSymbolHandle().asTruffleObject(), "bind", signature);
+                } catch (Throwable t) {
+                    throw RInternalError.shouldNotReachHere();
+                }
+            }
+        }
+    }
+
+    private static final class TruffleNFI_InitNode extends RNGNode implements InitNode {
+
+        @Override
+        public void execute(int seed) {
+            init(Function.Init, "(sint32): void");
+            try {
+                ForeignAccess.sendExecute(message, targetFunction, seed);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static final class TruffleNFI_RandNode extends RNGNode implements RandNode {
+
+        @Override
+        public double execute() {
+            init(Function.Rand, "(): pointer");
+            try {
+                Object address = ForeignAccess.sendExecute(message, targetFunction);
+                return (double) ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_POINTER_DOUBLE.getSymbolFunction(), address);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static final class TruffleNFI_NSeedNode extends RNGNode implements NSeedNode {
+
+        @Override
+        public int execute() {
+            init(Function.NSeed, "(): pointer");
+            try {
+                Object address = ForeignAccess.sendExecute(message, targetFunction);
+                return (int) ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_POINTER_INT.getSymbolFunction(), address);
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    private static final class TruffleNFI_SeedsNode extends RNGNode implements SeedsNode {
+
+        @Override
+        public void execute(int[] n) {
+            init(Function.Seedloc, "(): pointer");
+            try {
+                Object address = ForeignAccess.sendExecute(message, targetFunction);
+                for (int i = 0; i < n.length; i++) {
+                    n[i] = (int) ForeignAccess.sendExecute(readPointerNode, TruffleNFI_CAccess.Function.READ_ARRAY_INT.getSymbolFunction(), address, i);
+                }
+            } catch (Throwable t) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        }
+    }
+
+    @Override
+    public InitNode createInitNode() {
+        return new TruffleNFI_InitNode();
+    }
+
+    @Override
+    public RandNode createRandNode() {
+        return new TruffleNFI_RandNode();
+    }
+
+    @Override
+    public NSeedNode createNSeedNode() {
+        return new TruffleNFI_NSeedNode();
+    }
+
+    @Override
+    public SeedsNode createSeedsNode() {
+        return new TruffleNFI_SeedsNode();
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Utils.java
similarity index 70%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Utils.java
index 55b6efe6d4374eb9d1da7b142ea7ee09bb5d6601..45fb1fd383423aac2755110063571d7e9d449bc6 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Utils.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop.ffi.nfi;
+package com.oracle.truffle.r.ffi.impl.nfi;
 
 import java.nio.charset.StandardCharsets;
 
@@ -30,12 +30,13 @@ import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.r.engine.interop.UnsafeAdapter;
+import com.oracle.truffle.r.ffi.impl.interop.UnsafeAdapter;
+import com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_DLL.NFIHandle;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.DLL;
+import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 
 public class TruffleNFI_Utils {
 
@@ -48,12 +49,8 @@ public class TruffleNFI_Utils {
     }
 
     static String convertCstring(Object cstring, int len) {
-        try {
-            long address = (long) ForeignAccess.sendUnbox(Message.UNBOX.createNode(), (TruffleObject) cstring);
-            return getString(address, len);
-        } catch (UnsupportedMessageException ex) {
-            throw RInternalError.shouldNotReachHere(ex);
-        }
+        long address = (long) cstring;
+        return getString(address, len);
     }
 
     private static TruffleObject defaultLibrary;
@@ -64,29 +61,37 @@ public class TruffleNFI_Utils {
             Env env = RContext.getInstance().getEnv();
             defaultLibrary = (TruffleObject) env.parse(Source.newBuilder("default").name("(load default)").mimeType("application/x-native").build()).call();
         }
-
     }
 
     /**
-     * Looks up the symbol {@code name} in either the "default" library (e.g. C library symbols) or
-     * in one of the libraries loaded through {@link DLL}, and binds the given NFI signature to the
-     * result, returning the resulting Truffle function object. Failure is fatal.
+     * Looks up the symbol {@code name} in the "default" library and binds the given NFI signature
+     * to the result, returning the resulting Truffle function object. Failure is fatal.
+     *
+     * N.B. The "default" library can resolve a symbol in any of the libraries that are implicitly
+     * referenced from the main executable so, in particular, {@code libR} and any of the libraries
+     * specified as dependencies in {@code libR}, e.g. {@code libpcre}, {@code libz}, etc. All of
+     * the functions searched for by this method fall into that category.
      */
-    static TruffleObject lookupAndBind(String name, boolean inDefaultLibrary, String signature) {
+    static TruffleObject lookupAndBind(String name, String signature) {
         initDefaultLibrary();
         try {
-            TruffleObject symbol;
-            if (inDefaultLibrary) {
-                symbol = ((TruffleObject) ForeignAccess.sendRead(Message.READ.createNode(), defaultLibrary, name));
-            } else {
-                symbol = DLL.findSymbol(name, null).asTruffleObject();
-            }
+            TruffleObject symbol = ((TruffleObject) ForeignAccess.sendRead(Message.READ.createNode(), defaultLibrary, name));
             return (TruffleObject) ForeignAccess.sendInvoke(Message.createInvoke(1).createNode(), symbol, "bind", signature);
         } catch (InteropException e) {
             throw RInternalError.shouldNotReachHere(e);
         }
     }
 
+    static TruffleObject lookupAndBindStats(String name, String signature) {
+        DLLInfo dllInfo = DLL.findLibrary("stats");
+        try {
+            TruffleObject result = (TruffleObject) ForeignAccess.sendRead(Message.READ.createNode(), ((NFIHandle) dllInfo.handle).libHandle, name);
+            return (TruffleObject) ForeignAccess.sendInvoke(Message.createInvoke(1).createNode(), result, "bind", signature);
+        } catch (InteropException e) {
+            throw RInternalError.shouldNotReachHere(e);
+        }
+    }
+
     /**
      * Returns the number of arguments in an NFI signature.
      */
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Zip.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Zip.java
new file mode 100644
index 0000000000000000000000000000000000000000..fe6ff0492cdd9fad6c5a9e3d5cc043105f91be79
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Zip.java
@@ -0,0 +1,67 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.nfi;
+
+import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
+
+public class TruffleNFI_Zip implements ZipRFFI {
+
+    private static class TruffleNFI_CompressNode extends TruffleNFI_DownCallNode implements ZipRFFI.CompressNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.compress;
+        }
+
+        @Override
+        public int execute(byte[] dest, byte[] source) {
+            long[] destlen = new long[]{dest.length};
+            int result = (int) call(JavaInterop.asTruffleObject(dest), JavaInterop.asTruffleObject(destlen), JavaInterop.asTruffleObject(source), source.length);
+            return result;
+        }
+    }
+
+    private static class TruffleNFI_UncompressNode extends TruffleNFI_DownCallNode implements ZipRFFI.UncompressNode {
+        @Override
+        protected NFIFunction getFunction() {
+            return NFIFunction.uncompress;
+        }
+
+        @Override
+        public int execute(byte[] dest, byte[] source) {
+            long[] destlen = new long[]{dest.length};
+            int result = (int) call(JavaInterop.asTruffleObject(dest), JavaInterop.asTruffleObject(destlen), JavaInterop.asTruffleObject(source), source.length);
+            return result;
+        }
+    }
+
+    @Override
+    public CompressNode createCompressNode() {
+        return new TruffleNFI_CompressNode();
+    }
+
+    @Override
+    public UncompressNode createUncompressNode() {
+        return new TruffleNFI_UncompressNode();
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed85483bb788fd1204b21f4e8940cde83910f942
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/**
+ * The Truffle NFI implementation of the {@link com.oracle.truffle.r.runtime.ffi.RFFI} interfaces.
+ */
+package com.oracle.truffle.r.ffi.impl.nfi;
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ATTRIB.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ATTRIB.java
new file mode 100644
index 0000000000000000000000000000000000000000..07d6a98681272787228e27e46d13c0f2a60d901f
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ATTRIB.java
@@ -0,0 +1,53 @@
+/*
+ * 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.ffi.impl.nodes;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.attributes.GetAttributesNode;
+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.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public abstract class ATTRIB extends FFIUpCallNode.Arg1 {
+    @Child private GetAttributesNode getAttributesNode = GetAttributesNode.create();
+
+    @Specialization
+    public Object doAttributable(RAttributable obj) {
+        return getAttributesNode.execute(obj);
+    }
+
+    @Fallback
+    public RNull doOthers(Object obj) {
+        if (obj == RNull.instance || RRuntime.isForeignObject(obj)) {
+            return RNull.instance;
+        } else {
+            CompilerDirectives.transferToInterpreter();
+            String type = obj == null ? "null" : obj.getClass().getSimpleName();
+            throw RError.error(RError.NO_CALLER, Message.GENERIC, "object of type '" + type + "' cannot be attributed");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsCharNode.java
similarity index 98%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsCharNode.java
index 60061c0032607c35d9bb9d413f1f574e08de8534..e015164f75cdff7ecc6f132a7d5ae63a0ac0aecb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsCharNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsCharNode.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.nodes;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsIntegerNode.java
similarity index 98%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsIntegerNode.java
index c37f801fcf001986b9046c2299d893bc25a020ba..584c9986c203ed038a3743eee547f94101f0553d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsIntegerNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsIntegerNode.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.nodes;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsLogicalNode.java
similarity index 98%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsLogicalNode.java
index 423574b4540ba6e6c920d63767f3fc7b3414d942..44db7cbbe30dac8360b010bdd83d0516e743aa6a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsLogicalNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsLogicalNode.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.nodes;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsRealNode.java
similarity index 98%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsRealNode.java
index b0667ef0480ec771cf76443bc0ab1cfb6e139c07..959ab8314206c6765a12e3b649cd046d9ab192c1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsRealNode.java
@@ -10,7 +10,7 @@
  *
  * All rights reserved.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.nodes;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceVectorNode.java
similarity index 91%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceVectorNode.java
index 1d4729c310a374b1cb9fd78bb408e462241dfda2..32da1b5c50147f250972a2dba8c2d3efa6f85a81 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/CoerceVectorNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/CoerceVectorNode.java
@@ -20,9 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
-
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.unimplemented;
+package com.oracle.truffle.r.ffi.impl.nodes;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
@@ -40,6 +38,7 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastSymbolNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
@@ -79,7 +78,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
     @TruffleBoundary
     Object doFallback(Object value, Object mode) {
         String type = value != null ? value.getClass().getSimpleName() : "null";
-        throw unimplemented(String.format("Rf_coerceVector unimplemented for type %s or mode %s.", type, mode));
+        throw RInternalError.unimplemented(String.format("Rf_coerceVector unimplemented for type %s or mode %s.", type, mode));
     }
 
     static boolean isS4Object(Object obj) {
@@ -112,9 +111,9 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
             case NILSXP:
                 return new CastNullNode();
             case LISTSXP:
-                throw unimplemented("Rf_coerceVector called with unimplemented for PairLists.");
+                throw RInternalError.unimplemented("Rf_coerceVector unimplemented for PairLists.");
             case LANGSXP:
-                throw unimplemented("Rf_coerceVector called with unimplemented for RLanguage.");
+                throw RInternalError.unimplemented("Rf_coerceVector unimplemented for RLanguage.");
             case ENVSXP:
                 return new EnvironmentCast();
             case VECSXP:
@@ -134,7 +133,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
             case RAWSXP:
                 return CastRawNode.createForRFFI(true, preserveDims, preserveAttrs);
             default:
-                throw unimplemented(String.format("Rf_coerceVector called with unimplemented mode %d (type %s).", mode, type));
+                throw RInternalError.unimplemented(String.format("Rf_coerceVector called with unimplemented mode %d (type %s).", mode, type));
         }
     }
 
@@ -150,7 +149,7 @@ public abstract class CoerceVectorNode extends FFIUpCallNode.Arg2 {
         }
 
         private static String getTypeName(Object val) {
-            Object value = RRuntime.asAbstractVector(val);
+            Object value = RRuntime.convertScalarVectors(val);
             if (value == null) {
                 return "null";
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java
similarity index 78%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java
index 7cf4549706518f3fc9c496a10f11bcc125c9d9c2..5df825b06b78e80c37dfb663f2f3b2c4c311a156 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallNode.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallNode.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.nodes;
 
 import com.oracle.truffle.api.nodes.Node;
 
@@ -34,7 +34,6 @@ public abstract class FFIUpCallNode extends Node {
         protected int numArgs() {
             return 0;
         }
-
     }
 
     public abstract static class Arg1 extends FFIUpCallNode {
@@ -64,4 +63,21 @@ public abstract class FFIUpCallNode extends Node {
         }
     }
 
+    public abstract static class Arg4 extends FFIUpCallNode {
+        public abstract Object executeObject(Object arg0, Object arg1, Object arg2, Object arg3);
+
+        @Override
+        protected int numArgs() {
+            return 4;
+        }
+    }
+
+    public abstract static class Arg5 extends FFIUpCallNode {
+        public abstract Object executeObject(Object arg0, Object arg1, Object arg2, Object arg3, Object arg4);
+
+        @Override
+        protected int numArgs() {
+            return 5;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallRootNode.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallRootNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..4470a37a76c32fce8da819194007efa910eedea4
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/FFIUpCallRootNode.java
@@ -0,0 +1,118 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.ffi.impl.nodes;
+
+import java.util.function.Supplier;
+
+import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CADDRNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CADRNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CARNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CDDRNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.ListAccessNodesFactory.CDRNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.LENGTHNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoNewObjectNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoSlotAssignNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.MiscNodesFactory.RDoSlotNodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodesFactory.RandFunction2NodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodesFactory.RandFunction3_1NodeGen;
+import com.oracle.truffle.r.ffi.impl.nodes.RandFunctionsNodesFactory.RandFunction3_2NodeGen;
+import com.oracle.truffle.r.ffi.impl.upcalls.RFFIUpCallTable;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.nmath.distr.Unif;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+
+public final class FFIUpCallRootNode extends RootNode {
+    private static final RootCallTarget[] rootCallTargets = new RootCallTarget[RFFIUpCallTable.values().length];
+
+    @Child private FFIUpCallNode theFFIUpCallNode;
+    private final int numArgs;
+
+    private FFIUpCallRootNode(FFIUpCallNode child) {
+        super(RContext.getInstance().getLanguage());
+        theFFIUpCallNode = child;
+        this.numArgs = child.numArgs();
+    }
+
+    @Override
+    public SourceSection getSourceSection() {
+        return RSyntaxNode.INTERNAL;
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        Object[] args = frame.getArguments();
+        switch (numArgs) {
+            case 0:
+                return ((FFIUpCallNode.Arg0) theFFIUpCallNode).executeObject();
+            case 1:
+                return ((FFIUpCallNode.Arg1) theFFIUpCallNode).executeObject(args[0]);
+            case 2:
+                return ((FFIUpCallNode.Arg2) theFFIUpCallNode).executeObject(args[0], args[1]);
+            case 3:
+                return ((FFIUpCallNode.Arg3) theFFIUpCallNode).executeObject(args[0], args[1], args[2]);
+            default:
+                throw RInternalError.shouldNotReachHere();
+        }
+    }
+
+    static void add(RFFIUpCallTable upCallMethod, Supplier<FFIUpCallNode> constructor) {
+
+        FFIUpCallRootNode rootNode = new FFIUpCallRootNode(constructor.get());
+        rootCallTargets[upCallMethod.ordinal()] = Truffle.getRuntime().createCallTarget(rootNode);
+    }
+
+    public static RootCallTarget getCallTarget(RFFIUpCallTable upCallMethod) {
+        RootCallTarget target = rootCallTargets[upCallMethod.ordinal()];
+        assert target != null;
+        return target;
+    }
+
+    public static void register() {
+        FFIUpCallRootNode.add(RFFIUpCallTable.ATTRIB, ATTRIBNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_asReal, AsRealNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_asLogical, AsLogicalNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_asInteger, AsIntegerNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_asChar, AsCharNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_coerceVector, CoerceVectorNode::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.CAR, CARNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.CDR, CDRNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.CADR, CADRNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.CADDR, CADDRNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.CDDR, CDDRNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.LENGTH, LENGTHNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.R_do_new_object, RDoNewObjectNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.R_do_slot, RDoSlotNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.R_do_slot_assign, RDoSlotAssignNodeGen::create);
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_runif, () -> RandFunction2NodeGen.create(new Unif.Runif()));
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_dunif, () -> RandFunction3_1NodeGen.create(new Unif.DUnif()));
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_qunif, () -> RandFunction3_2NodeGen.create(new Unif.QUnif()));
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_punif, () -> RandFunction3_2NodeGen.create(new Unif.PUnif()));
+        FFIUpCallRootNode.add(RFFIUpCallTable.Rf_namesgets, MiscNodesFactory.NamesGetsNodeGen::create);
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java
similarity index 75%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java
index 7dee1d0b06c9de3511c9f3ab681084f7ccc0fc0f..bd0c3374713aabd8bfe24182e7de4ab285183b3c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/ListAccessNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/ListAccessNodes.java
@@ -20,15 +20,17 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
-
-import static com.oracle.truffle.r.nodes.ffi.RFFIUtils.unimplemented;
+package com.oracle.truffle.r.ffi.impl.nodes;
 
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 
 /**
@@ -49,11 +51,25 @@ public final class ListAccessNodes {
             return lang.getDataAtAsObject(0);
         }
 
+        @Specialization
+        protected Object car(RArgsValuesAndNames args) {
+            return args.getArgument(0);
+        }
+
+        @Specialization
+        protected Object car(RSymbol sym) {
+            return sym;
+        }
+
+        @Specialization
+        protected Object car(@SuppressWarnings("unused") RNull nil) {
+            return RNull.instance;
+        }
+
         @Fallback
         protected Object car(@SuppressWarnings("unused") Object obj) {
-            throw unimplemented("CAR only works on pair lists and language objects");
+            throw RInternalError.unimplemented("CAR only works on pair lists and language objects");
         }
-
     }
 
     @TypeSystemReference(RTypes.class)
@@ -69,9 +85,14 @@ public final class ListAccessNodes {
             return l.cdr();
         }
 
+        @Specialization
+        protected Object cdr(RArgsValuesAndNames args) {
+            return args.toPairlist().cdr();
+        }
+
         @Fallback
         protected Object cdr(@SuppressWarnings("unused") Object obj) {
-            throw unimplemented("CDR only works on pair lists and language objects");
+            throw RInternalError.unimplemented("CDR only works on pair lists and language objects");
 
         }
     }
@@ -90,9 +111,8 @@ public final class ListAccessNodes {
 
         @Fallback
         protected Object cadr(@SuppressWarnings("unused") Object obj) {
-            throw unimplemented("CADR only works on pair lists and language objects");
+            throw RInternalError.unimplemented("CADR only works on pair lists and language objects");
         }
-
     }
 
     @TypeSystemReference(RTypes.class)
@@ -109,9 +129,8 @@ public final class ListAccessNodes {
 
         @Fallback
         protected Object caddr(@SuppressWarnings("unused") Object obj) {
-            throw unimplemented("CADDR only works on pair lists and language objects");
+            throw RInternalError.unimplemented("CADDR only works on pair lists and language objects");
         }
-
     }
 
     @TypeSystemReference(RTypes.class)
@@ -129,7 +148,7 @@ public final class ListAccessNodes {
 
         @Fallback
         protected Object cddr(@SuppressWarnings("unused") Object obj) {
-            throw unimplemented("CDDR only works on pair lists and language objects");
+            throw RInternalError.unimplemented("CDDR only works on pair lists and language objects");
 
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java
similarity index 81%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java
index 1391299116903197c9cdc349a57006945a292988..918352aba3a2b7ee6660ef9c5ad7fd41e976f82a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/MiscNodes.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/MiscNodes.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.ffi;
+package com.oracle.truffle.r.ffi.impl.nodes;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Fallback;
@@ -30,13 +30,17 @@ import com.oracle.truffle.r.nodes.access.AccessSlotNode;
 import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen;
 import com.oracle.truffle.r.nodes.access.UpdateSlotNode;
 import com.oracle.truffle.r.nodes.access.UpdateSlotNodeGen;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctionsFactory.SetNamesAttributeNodeGen;
 import com.oracle.truffle.r.nodes.objects.NewObject;
 import com.oracle.truffle.r.nodes.objects.NewObjectNodeGen;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.CharSXPWrapper;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
@@ -81,6 +85,18 @@ public final class MiscNodes {
             return obj.getLength();
         }
 
+        @Specialization
+        protected int length(REnvironment env) {
+            // May seem wasteful of resources, but simple env.getFrame().getDescriptor().getSize()
+            // is not correct!
+            return env.ls(true, null, false).getLength();
+        }
+
+        @Specialization
+        protected int length(RArgsValuesAndNames obj) {
+            return obj.getLength();
+        }
+
         @Fallback
         protected int length(Object obj) {
             CompilerDirectives.transferToInterpreter();
@@ -106,7 +122,6 @@ public final class MiscNodes {
         Object doSlot(@SuppressWarnings("unused") Object o, Object name) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name());
         }
-
     }
 
     @TypeSystemReference(RTypes.class)
@@ -127,7 +142,6 @@ public final class MiscNodes {
         Object doSlot(@SuppressWarnings("unused") Object o, Object name, @SuppressWarnings("unused") Object value) {
             throw RError.error(RError.SHOW_CALLER2, RError.Message.INVALID_ARGUMENT_OF_TYPE, "name", SEXPTYPE.gnuRTypeForObject(name).name());
         }
-
     }
 
     @TypeSystemReference(RTypes.class)
@@ -143,7 +157,22 @@ public final class MiscNodes {
         Object doNewObject(Object classDef) {
             return newObjectNode.execute(classDef);
         }
+    }
+
+    @TypeSystemReference(RTypes.class)
+    abstract static class NamesGetsNode extends FFIUpCallNode.Arg2 {
+
+        @Child private SetNamesAttributeNode setNamesNode;
 
+        NamesGetsNode() {
+            setNamesNode = SetNamesAttributeNodeGen.create();
+        }
+
+        @Specialization
+        Object doNewObject(Object vec, Object val) {
+            setNamesNode.execute(vec, val);
+            return vec;
+        }
     }
 
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java
new file mode 100644
index 0000000000000000000000000000000000000000..f168c1caeda218a4a7589d1e2a6edc979faa8fb8
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/RandFunctionsNodes.java
@@ -0,0 +1,72 @@
+/*
+ * 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.ffi.impl.nodes;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.runtime.nmath.MathFunctions;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandFunction2_Double;
+import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider;
+
+public final class RandFunctionsNodes {
+
+    public abstract static class RandFunction3_2Node extends FFIUpCallNode.Arg5 {
+        private final MathFunctions.Function3_2 inner;
+
+        protected RandFunction3_2Node(MathFunctions.Function3_2 inner) {
+            this.inner = inner;
+        }
+
+        @Specialization
+        protected double evaluate(double a, double b, double c, boolean d, boolean e) {
+            return inner.evaluate(a, b, c, d, e);
+        }
+    }
+
+    public abstract static class RandFunction3_1Node extends FFIUpCallNode.Arg4 {
+        private final MathFunctions.Function3_1 inner;
+
+        protected RandFunction3_1Node(MathFunctions.Function3_1 inner) {
+            this.inner = inner;
+        }
+
+        @Specialization
+        protected double evaluate(double a, double b, double c, boolean d) {
+            return inner.evaluate(a, b, c, d);
+        }
+    }
+
+    public abstract static class RandFunction2Node extends FFIUpCallNode.Arg2 {
+        @Child private RandomFunctions.RandFunction2_Double inner;
+
+        protected RandFunction2Node(RandFunction2_Double inner) {
+            this.inner = inner;
+        }
+
+        @Specialization
+        protected double evaluate(double a, double b) {
+            return inner.execute(a, b, RandomNumberProvider.fromCurrentRNG());
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..4b666daac9fdeb377e18b2523d663b387f049f86
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/package-info.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+/**
+ * Support for implementing certain upcalls as Truffle nodes.
+ */
+package com.oracle.truffle.r.ffi.impl.nodes;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/IDEUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/IDEUpCallsRFFI.java
similarity index 95%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/IDEUpCallsRFFI.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/IDEUpCallsRFFI.java
index 4ba0c703c77784c6108895f7a40f0ea9c0acfd85..5876265a70fa8feeaf329c571e5e77a0fd028619 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/IDEUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/IDEUpCallsRFFI.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.ffi.impl.upcalls;
 
 import com.oracle.truffle.api.frame.Frame;
 
@@ -30,6 +30,8 @@ import com.oracle.truffle.api.frame.Frame;
  */
 public interface IDEUpCallsRFFI {
     // Checkstyle: stop method name check
+    Object R_GlobalContext();
+
     Object R_getGlobalFunctionContext();
 
     Object R_getParentFunctionContext(Object c);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
similarity index 68%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
index 295eaa8c02ee461e643a0532a8707a46c4db8fd1..76c10d6ac9e1285218e7e2774872b3375cc1ac2a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StdUpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/StdUpCallsRFFI.java
@@ -20,14 +20,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.ffi.impl.upcalls;
 
+import com.oracle.truffle.r.ffi.processor.RFFICstring;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
  * This class defines methods that match the functionality of the macro/function definitions in the
@@ -42,7 +42,12 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  *
  * N.B. It is important not to be too specific about types owing the support for Truffle interop
  * implementations. For example, many arguments are "strings" but we do not specify them as
- * {@code String} here.
+ * {@code String} here. In particular do not use array types as these are passed as custom Truffle
+ * objects in some implementations.
+ *
+ * N.B. Although some functions do not return results, the Truffle interop EXECUTE message machinery
+ * does not like {@code void} functions, so we just use {@code int}. Evidently the actual value does
+ * not matter.
  */
 public interface StdUpCallsRFFI {
     // Checkstyle: stop method name check
@@ -69,7 +74,7 @@ public interface StdUpCallsRFFI {
 
     Object Rf_cons(Object car, Object cdr);
 
-    void Rf_defineVar(Object symbolArg, Object value, Object envArg);
+    int /* void */ Rf_defineVar(Object symbolArg, Object value, Object envArg);
 
     Object R_do_MAKE_CLASS(@RFFICstring Object clazz);
 
@@ -84,11 +89,13 @@ public interface StdUpCallsRFFI {
 
     Object Rf_findVarInFrame3(Object envArg, Object symbolArg, int doGet);
 
+    Object ATTRIB(Object obj);
+
     Object Rf_getAttrib(Object obj, Object name);
 
-    void Rf_setAttrib(Object obj, Object name, Object val);
+    int /* void */ Rf_setAttrib(Object obj, Object name, Object val);
 
-    int Rf_inherits(@RFFICstring Object x, Object clazz);
+    int Rf_inherits(Object x, @RFFICstring Object clazz);
 
     Object Rf_install(@RFFICstring Object name);
 
@@ -102,13 +109,15 @@ public interface StdUpCallsRFFI {
 
     Object Rf_PairToVectorList(Object x);
 
-    void Rf_error(@RFFICstring Object msg);
+    int /* void */ Rf_error(@RFFICstring Object msg);
+
+    int /* void */ Rf_warning(@RFFICstring Object msg);
 
-    void Rf_warning(@RFFICstring Object msg);
+    int /* void */ Rf_warningcall(Object call, @RFFICstring Object msg);
 
-    void Rf_warningcall(Object call, @RFFICstring Object msg);
+    int /* void */ Rf_errorcall(Object call, @RFFICstring Object msg);
 
-    Object Rf_allocVector(int mode, int n);
+    Object Rf_allocVector(int mode, long n);
 
     Object Rf_allocArray(int mode, Object dimsObj);
 
@@ -120,9 +129,9 @@ public interface StdUpCallsRFFI {
 
     int LENGTH(Object x);
 
-    void SET_STRING_ELT(Object x, int i, Object v);
+    int /* void */ SET_STRING_ELT(Object x, long i, Object v);
 
-    void SET_VECTOR_ELT(Object x, int i, Object v);
+    int /* void */ SET_VECTOR_ELT(Object x, long i, Object v);
 
     Object RAW(Object x);
 
@@ -132,12 +141,14 @@ public interface StdUpCallsRFFI {
 
     Object REAL(Object x);
 
-    Object STRING_ELT(Object x, int i);
+    Object STRING_ELT(Object x, long i);
 
-    Object VECTOR_ELT(Object x, int i);
+    Object VECTOR_ELT(Object x, long i);
 
     int NAMED(Object x);
 
+    Object SET_NAMED_FASTR(Object x, int v);
+
     Object SET_TYPEOF_FASTR(Object x, int v);
 
     int TYPEOF(Object x);
@@ -146,7 +157,7 @@ public interface StdUpCallsRFFI {
 
     Object Rf_duplicate(Object x, int deep);
 
-    int Rf_any_duplicated(Object x, int fromLast);
+    long Rf_any_duplicated(Object x, int fromLast);
 
     Object PRINTNAME(Object x);
 
@@ -172,7 +183,7 @@ public interface StdUpCallsRFFI {
 
     Object SYMVALUE(Object x);
 
-    void SET_SYMVALUE(Object x, Object v);
+    int /* void */ SET_SYMVALUE(Object x, Object v);
 
     int R_BindingIsLocked(Object sym, Object env);
 
@@ -184,27 +195,27 @@ public interface StdUpCallsRFFI {
 
     Object Rf_GetOption1(Object tag);
 
-    void Rf_gsetVar(Object symbol, Object value, Object rho);
+    int /* void */ Rf_gsetVar(Object symbol, Object value, Object rho);
 
-    void DUPLICATE_ATTRIB(Object to, Object from);
+    int /* void */ DUPLICATE_ATTRIB(Object to, Object from);
 
     int R_compute_identical(Object x, Object y, int flags);
 
-    void Rf_copyListMatrix(Object s, Object t, int byrow);
+    int /* void */ Rf_copyListMatrix(Object s, Object t, int byrow);
 
-    void Rf_copyMatrix(Object s, Object t, int byrow);
+    int /* void */ Rf_copyMatrix(Object s, Object t, int byrow);
 
-    Object R_tryEval(Object expr, Object env, boolean silent);
+    Object R_tryEval(Object expr, Object env, int silent);
 
     Object R_ToplevelExec();
 
     int RDEBUG(Object x);
 
-    void SET_RDEBUG(Object x, int v);
+    int /* void */ SET_RDEBUG(Object x, int v);
 
     int RSTEP(Object x);
 
-    void SET_RSTEP(Object x, int v);
+    int /* void */ SET_RSTEP(Object x, int v);
 
     Object ENCLOS(Object x);
 
@@ -218,15 +229,15 @@ public interface StdUpCallsRFFI {
 
     int IS_S4_OBJECT(Object x);
 
-    void SET_S4_OBJECT(Object x);
+    int /* void */ SET_S4_OBJECT(Object x);
 
-    void UNSET_S4_OBJECT(Object x);
+    int /* void */ UNSET_S4_OBJECT(Object x);
 
-    void Rprintf(@RFFICstring Object message);
+    int /* void */ Rprintf(@RFFICstring Object message);
 
-    void GetRNGstate();
+    int /* void */ GetRNGstate();
 
-    void PutRNGstate();
+    int /* void */ PutRNGstate();
 
     double unif_rand();
 
@@ -240,15 +251,15 @@ public interface StdUpCallsRFFI {
 
     Object R_ExternalPtrProtected(Object x);
 
-    void R_SetExternalPtrAddr(Object x, long addr);
+    int /* void */ R_SetExternalPtrAddr(Object x, long addr);
 
-    void R_SetExternalPtrTag(Object x, Object tag);
+    int /* void */ R_SetExternalPtrTag(Object x, Object tag);
 
-    void R_SetExternalPtrProtected(Object x, Object prot);
+    int /* void */ R_SetExternalPtrProtected(Object x, Object prot);
 
-    void R_CleanUp(int sa, int status, int runlast);
+    int /* void */ R_CleanUp(int sa, int status, int runlast);
 
-    REnvironment R_NewHashedEnv(REnvironment parent, Object initialSize);
+    Object R_NewHashedEnv(Object parent, Object initialSize);
 
     int PRSEEN(Object x);
 
@@ -262,9 +273,9 @@ public interface StdUpCallsRFFI {
 
     Object R_new_custom_connection(@RFFICstring Object description, @RFFICstring Object mode, @RFFICstring Object className, Object readAddr);
 
-    int R_ReadConnection(int fd, byte[] buf);
+    int R_ReadConnection(int fd, Object bufObj);
 
-    int R_WriteConnection(int fd, byte[] buf);
+    int R_WriteConnection(int fd, Object bufObj);
 
     Object R_GetConnection(int fd);
 
@@ -282,4 +293,16 @@ public interface StdUpCallsRFFI {
 
     Object R_MethodsNamespace();
 
+    int Rf_str2type(@RFFICstring Object name);
+
+    double Rf_dunif(double a, double b, double c, int d);
+
+    double Rf_qunif(double a, double b, double c, int d, int e);
+
+    double Rf_punif(double a, double b, double c, int d, int e);
+
+    double Rf_runif(double a, double b);
+
+    Object Rf_namesgets(Object vec, Object val);
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/UpCallsRFFI.java
similarity index 83%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFI.java
rename to com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/UpCallsRFFI.java
index 563e8ca60fb3a7bf122d23cb48fed89fe816f686..9d4718719121f7a4b76df53ef2d685ef73e8c9a8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UpCallsRFFI.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/UpCallsRFFI.java
@@ -20,11 +20,14 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.ffi.impl.upcalls;
+
+import com.oracle.truffle.r.ffi.processor.RFFIUpCallRoot;
 
 /**
  * Aggregation of all the FFI upcall interfaces.
  */
-public interface UpCallsRFFI extends StdUpCallsRFFI, RContextUpCallsRFFI, IDEUpCallsRFFI {
+@RFFIUpCallRoot
+public interface UpCallsRFFI extends StdUpCallsRFFI, IDEUpCallsRFFI, VariableUpCallsRFFI {
 
 }
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/VariableUpCallsRFFI.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/VariableUpCallsRFFI.java
new file mode 100644
index 0000000000000000000000000000000000000000..66e031b6b0a802b9d88abbb0d373150b033dc9f8
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/VariableUpCallsRFFI.java
@@ -0,0 +1,55 @@
+/*
+ * 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.ffi.impl.upcalls;
+
+import com.oracle.truffle.api.interop.TruffleObject;
+
+/**
+ * This exists because {@link TruffleObject} instances may not always be storable in memory, in all
+ * implementations, so upcall to get the values.
+ */
+public interface VariableUpCallsRFFI {
+    // Checkstyle: stop method name check
+
+    // The first five are context dependent and so are always implemented as callbacks.
+
+    Object R_GlobalEnv();
+
+    Object R_BaseEnv();
+
+    Object R_BaseNamespace();
+
+    Object R_NamespaceRegistry();
+
+    int R_Interactive();
+
+    // These may need to be upcalled in some implementations.
+
+    default Object R_Home() {
+        return null;
+    }
+
+    default Object R_TempDir() {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/package-info.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/package-info.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9050396d0b8cadd2e3dad9671f1a38e2753562d
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/upcalls/package-info.java
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+/**
+ * These interfaces define the current set of upcalls. They are factored for convenience into
+ * categories. The main interface is {@link com.oracle.truffle.r.ffi.impl.upcalls.StdUpCallsRFFI}.
+ * The annotation processor {@code com.oracle.truffle.r.ffi.FFIProcessor} drives off these
+ * interfaces and generates a number of additional classes.
+ */
+package com.oracle.truffle.r.ffi.impl.upcalls;
diff --git a/com.oracle.truffle.r.ffi.processor/src/META-INF/services/javax.annotation.processing.Processor b/com.oracle.truffle.r.ffi.processor/src/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 0000000000000000000000000000000000000000..a60490420d43be627dc11c89ce341cff93ddf40e
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.processor/src/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+com.oracle.truffle.r.ffi.processor.FFIProcessor
diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..355660afa1b638fc4c773423a0a20d8d31711a2c
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java
@@ -0,0 +1,388 @@
+/*
+ * 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.ffi.processor;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
+import javax.tools.Diagnostic;
+import javax.tools.Diagnostic.Kind;
+
+import javax.tools.FileObject;
+import javax.tools.JavaFileObject;
+import javax.tools.StandardLocation;
+
+public final class FFIProcessor extends AbstractProcessor {
+
+    @Override
+    public Set<String> getSupportedAnnotationTypes() {
+        Set<String> annotations = new HashSet<>();
+        annotations.add("com.oracle.truffle.r.ffi.processor.RFFIUpCallRoot");
+        return annotations;
+    }
+
+    @Override
+    public SourceVersion getSupportedSourceVersion() {
+        return SourceVersion.latest();
+    }
+
+    @Override
+    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+        if (roundEnv.processingOver()) {
+            return false;
+        }
+        process0(roundEnv);
+        return true;
+    }
+
+    private void process0(RoundEnvironment roundEnv) {
+        for (Element e : roundEnv.getElementsAnnotatedWith(RFFIUpCallRoot.class)) {
+            try {
+                processElement(e);
+            } catch (Throwable ex) {
+                ex.printStackTrace();
+                String message = "Uncaught error in " + this.getClass();
+                processingEnv.getMessager().printMessage(Kind.ERROR, message + ": " + printException(ex), e);
+            }
+        }
+    }
+
+    private void processElement(Element e) throws IOException {
+        if (e.getKind() != ElementKind.INTERFACE) {
+            processingEnv.getMessager().printMessage(Kind.ERROR, "RFFIUpCallRoot must annotate an interface");
+        }
+        Types types = processingEnv.getTypeUtils();
+        TypeElement typeElement = (TypeElement) e;
+        List<? extends TypeMirror> extended = typeElement.getInterfaces();
+        int count = 0;
+        for (TypeMirror tm : extended) {
+            TypeElement x = (TypeElement) types.asElement(tm);
+            List<? extends Element> methods = x.getEnclosedElements();
+            count += methods.size();
+        }
+        ExecutableElement[] methods = new ExecutableElement[count];
+        count = 0;
+        for (TypeMirror tm : extended) {
+            TypeElement x = (TypeElement) types.asElement(tm);
+            List<? extends Element> encMethods = x.getEnclosedElements();
+            for (Element encMethod : encMethods) {
+                methods[count++] = (ExecutableElement) encMethod;
+            }
+        }
+        Arrays.sort(methods, new Comparator<ExecutableElement>() {
+            @Override
+            public int compare(ExecutableElement e1, ExecutableElement e2) {
+                return e1.getSimpleName().toString().compareTo(e2.getSimpleName().toString());
+            }
+        });
+        generateTable(methods);
+        generateMessageClasses(methods);
+        generateCallbacks(methods);
+        generateCallbacksIndexHeader(methods);
+    }
+
+    private void generateTable(ExecutableElement[] methods) throws IOException {
+        JavaFileObject fileObj = processingEnv.getFiler().createSourceFile("com.oracle.truffle.r.ffi.impl.upcalls.RFFIUpCallTable");
+        Writer w = fileObj.openWriter();
+        w.append("// GENERATED; DO NOT EDIT\n");
+        w.append("package com.oracle.truffle.r.ffi.impl.upcalls;\n");
+        w.append("public enum RFFIUpCallTable {\n");
+        for (int i = 0; i < methods.length; i++) {
+            ExecutableElement method = methods[i];
+            w.append("    ").append(method.getSimpleName().toString()).append(i == methods.length - 1 ? ";" : ",").append('\n');
+        }
+
+        w.append("}\n");
+        w.close();
+    }
+
+    private void generateCallbacksIndexHeader(ExecutableElement[] methods) throws IOException {
+        FileObject fileObj = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "com.oracle.truffle.r.ffi.impl.upcalls", "rffi_upcallsindex.h");
+        note("If you edited any UpCallsRFFI interfaces do: cp " + fileObj.toUri().getPath() + " com.oracle.truffle.r.native/fficall/src/common\n");
+        Writer w = fileObj.openWriter();
+        w.append("// GENERATED; DO NOT EDIT\n");
+        w.append("#ifndef RFFI_UPCALLSINDEX_H\n");
+        w.append("#define RFFI_UPCALLSINDEX_H\n");
+        w.append('\n');
+        for (int i = 0; i < methods.length; i++) {
+            ExecutableElement method = methods[i];
+            w.append("#define ").append(method.getSimpleName().toString()).append("_x ").append(Integer.toString(i)).append('\n');
+        }
+        w.append('\n');
+        w.append("#define ").append("UPCALLS_TABLE_SIZE ").append(Integer.toString(methods.length)).append('\n');
+        w.append('\n');
+        w.append("#endif // RFFI_UPCALLSINDEX_H\n");
+        w.close();
+    }
+
+    private void generateMessageClasses(ExecutableElement[] methods) throws IOException {
+        for (int i = 0; i < methods.length; i++) {
+            ExecutableElement m = methods[i];
+            generateCallClass(m);
+            generateMessageClass(m);
+        }
+    }
+
+    private void generateCallClass(ExecutableElement m) throws IOException {
+        String name = m.getSimpleName().toString();
+        String callName = name + "Call";
+        JavaFileObject fileObj = processingEnv.getFiler().createSourceFile("com.oracle.truffle.r.ffi.impl.upcalls." + callName);
+        Writer w = fileObj.openWriter();
+        w.append("// GENERATED; DO NOT EDIT\n");
+        w.append("package ").append("com.oracle.truffle.r.ffi.impl.upcalls").append(";\n\n");
+        w.append("import com.oracle.truffle.api.interop.ForeignAccess;\n");
+        w.append("import com.oracle.truffle.api.interop.TruffleObject;\n");
+        w.append("import com.oracle.truffle.r.runtime.data.RTruffleObject;\n");
+        w.append("// Checkstyle: stop method name check\n\n");
+        w.append("public final class ").append(callName).append(" implements RTruffleObject {\n");
+        w.append('\n');
+        w.append("    public final UpCallsRFFI upCallsImpl;\n");
+        w.append('\n');
+        w.append("    protected ").append(callName).append("(UpCallsRFFI upCallsImpl) {\n");
+        w.append("        this.upCallsImpl = upCallsImpl;\n");
+        w.append("    }\n");
+        w.append('\n');
+        w.append("    public static boolean isInstance(TruffleObject value) {\n");
+        w.append("        return value instanceof ").append(callName).append(";\n");
+        w.append("    }\n");
+        w.append('\n');
+
+        w.append("    @Override\n");
+        w.append("    public ForeignAccess getForeignAccess() {\n");
+        w.append("        return ").append(callName).append("MRForeign.ACCESS;\n");
+        w.append("    }\n");
+        w.append("}\n");
+        w.close();
+    }
+
+    private void generateMessageClass(ExecutableElement m) throws IOException {
+        String name = m.getSimpleName().toString();
+        String callName = name + "Call";
+        String returnType = getTypeName(m.getReturnType());
+        List<? extends VariableElement> params = m.getParameters();
+
+        StringBuilder arguments = new StringBuilder();
+        boolean usesUnwrap = false;
+
+        // process arguments first to see if unwrap is necessary
+        int lparams = params.size();
+        for (int i = 0; i < lparams; i++) {
+            String is = Integer.toString(i);
+            String paramTypeName = getTypeName(params.get(i).asType());
+            boolean isScalar = true;
+            boolean needCast = !paramTypeName.equals("java.lang.Object");
+            if (needCast) {
+                arguments.append('(').append(paramTypeName).append(") ");
+            }
+            if (isScalar) {
+                usesUnwrap = true;
+                arguments.append("unwrap.unwrap(");
+            }
+            arguments.append("arguments[").append(is).append("]");
+            if (isScalar) {
+                arguments.append(')');
+            }
+            if (i != lparams - 1) {
+                arguments.append(", ");
+            }
+        }
+
+        JavaFileObject fileObj = processingEnv.getFiler().createSourceFile("com.oracle.truffle.r.ffi.impl.upcalls." + callName + "MR");
+        Writer w = fileObj.openWriter();
+        w.append("// GENERATED; DO NOT EDIT\n");
+        w.append("package ").append("com.oracle.truffle.r.ffi.impl.upcalls").append(";\n\n");
+        w.append("import com.oracle.truffle.api.interop.MessageResolution;\n");
+        w.append("import com.oracle.truffle.api.interop.Resolve;\n");
+        w.append("import com.oracle.truffle.api.nodes.Node;\n");
+        if (usesUnwrap) {
+            w.append("import com.oracle.truffle.r.ffi.impl.common.UpCallUnwrap;\n");
+        }
+        w.append("// Checkstyle: stop method name check\n\n");
+
+        w.append("@MessageResolution(receiverType = ").append(name).append("Call.class)\n");
+        w.append("public class ").append(callName).append("MR {\n");
+        w.append("    @Resolve(message = \"EXECUTE\")\n");
+        w.append("    public abstract static class ").append(callName).append("Execute extends Node {\n");
+        if (usesUnwrap) {
+            w.append("\n        @Child private UpCallUnwrap unwrap = new UpCallUnwrap();\n\n");
+        }
+        w.append("        protected ").append(returnType).append(" access(").append(callName).append(" receiver, ");
+        if (params.size() == 0) {
+            w.append("@SuppressWarnings(\"unused\") ");
+        }
+        w.append("Object[] arguments) {\n");
+        w.append("            ").append("return").append(" receiver.upCallsImpl.").append(name).append("(");
+
+        w.append(arguments);
+
+        w.append(");\n");
+        w.append("        }\n");
+        w.append("    }\n");
+        w.append("\n");
+
+        w.append("    @Resolve(message = \"IS_EXECUTABLE\")\n");
+        w.append("    public abstract static class ").append(callName).append("IsExecutable extends Node {\n");
+        w.append("        protected Object access(@SuppressWarnings(\"unused\") ").append(callName).append(" receiver) {\n");
+        w.append("            return true;\n");
+        w.append("        }\n");
+        w.append("    }\n");
+        w.append("}\n");
+        w.close();
+
+    }
+
+    private void generateCallbacks(ExecutableElement[] methods) throws IOException {
+        JavaFileObject fileObj = processingEnv.getFiler().createSourceFile("com.oracle.truffle.r.ffi.impl.upcalls.Callbacks");
+        Writer w = fileObj.openWriter();
+        w.append("// GENERATED; DO NOT EDIT\n");
+        w.append("package ").append("com.oracle.truffle.r.ffi.impl.upcalls").append(";\n\n");
+        w.append("import com.oracle.truffle.api.interop.TruffleObject;\n");
+        w.append("import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;\n");
+        w.append("import com.oracle.truffle.r.ffi.impl.upcalls.UpCallsRFFI;\n\n");
+        w.append("public enum Callbacks {\n");
+        for (int i = 0; i < methods.length; i++) {
+            ExecutableElement m = methods[i];
+            String sig = getNFISignature(m);
+            w.append("    ").append(m.getSimpleName().toString()).append('(').append('"').append(sig).append('"').append(')');
+            w.append(i == methods.length - 1 ? ';' : ',');
+            w.append("\n");
+        }
+        w.append('\n');
+        w.append("    public final String nfiSignature;\n");
+        w.append("    @CompilationFinal public TruffleObject call;\n\n");
+        w.append("    Callbacks(String signature) {\n");
+        w.append("        this.nfiSignature = signature;\n");
+        w.append("    }\n\n");
+
+        w.append("    public static void createCalls(UpCallsRFFI upCallsRFFIImpl) {\n");
+        w.append("        for (Callbacks callback : values()) {\n");
+        w.append("            switch (callback) {\n");
+        for (int i = 0; i < methods.length; i++) {
+            ExecutableElement m = methods[i];
+            String callName = m.getSimpleName().toString() + "Call";
+            w.append("                case ").append(m.getSimpleName().toString()).append(":\n");
+            w.append("                    callback.call = new ").append(callName).append("(upCallsRFFIImpl);\n");
+            w.append("                    break;\n\n");
+        }
+        w.append("            }\n");
+        w.append("        }\n");
+        w.append("    }\n");
+        w.append("}\n");
+        w.close();
+    }
+
+    private String getNFISignature(ExecutableElement m) {
+        List<? extends VariableElement> params = m.getParameters();
+        int lparams = params.size();
+        StringBuilder sb = new StringBuilder();
+        sb.append('(');
+        for (int i = 0; i < lparams; i++) {
+            VariableElement param = params.get(i);
+            RFFICstring[] annotations = param.getAnnotationsByType(RFFICstring.class);
+            String nfiParam = nfiParamName(getTypeName(param.asType()), annotations.length == 0 ? null : annotations[0]);
+            sb.append(nfiParam);
+            if (i != lparams - 1) {
+                sb.append(", ");
+            }
+        }
+        sb.append(')');
+        sb.append(" : ");
+        sb.append(nfiParamName(getTypeName(m.getReturnType()), null));
+        return sb.toString();
+    }
+
+    private static String nfiParamName(String paramType, RFFICstring rffiCstring) {
+        switch (paramType) {
+            case "java.lang.Object":
+                if (rffiCstring == null) {
+                    return "object";
+                } else {
+                    return rffiCstring.convert() ? "string" : "pointer";
+                }
+            case "char":
+                return "uint8";
+            case "int":
+                return "sint32";
+            case "long":
+                return "sint64";
+            case "double":
+                return "double";
+            case "void":
+                return "void";
+            case "int[]":
+                return "[sint32]";
+            case "long[]":
+                return "[sint64]";
+            case "double[]":
+                return "[double]";
+            case "byte[]":
+                return "[uint8]";
+            default:
+                return "object";
+        }
+    }
+
+    private String getTypeName(TypeMirror type) {
+        Types types = processingEnv.getTypeUtils();
+        TypeKind kind = type.getKind();
+        String returnType;
+        if (kind.isPrimitive()) {
+            returnType = kind.name().toLowerCase();
+        } else {
+            Element rt = types.asElement(type);
+            returnType = rt.toString();
+        }
+        return returnType;
+    }
+
+    private void note(String msg) {
+        processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
+    }
+
+    private static String printException(Throwable e) {
+        StringWriter string = new StringWriter();
+        PrintWriter writer = new PrintWriter(string);
+        e.printStackTrace(writer);
+        writer.flush();
+        string.flush();
+        return e.getMessage() + "\r\n" + string.toString();
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFICstring.java
similarity index 97%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java
rename to com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFICstring.java
index 5d50ed6f2cca867aa9ec80826bf7746e350cf17c..77a73ec9f9540902be359ac27c6bebd59b8e33a1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFICstring.java
+++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFICstring.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+package com.oracle.truffle.r.ffi.processor;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallRoot.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallRoot.java
new file mode 100644
index 0000000000000000000000000000000000000000..b0aae620e4a6921d13ac80d08ca03b208cacba49
--- /dev/null
+++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/RFFIUpCallRoot.java
@@ -0,0 +1,34 @@
+/*
+ * 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.ffi.processor;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Tags the root interface for RFFI upcalls, for the annotation processor.
+ */
+@Target({ElementType.TYPE})
+public @interface RFFIUpCallRoot {
+
+}
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/ConsoleHandler.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/ConsoleHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..f83c933b57f2d639383f736449e25ef3c6b50023
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/ConsoleHandler.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.launcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.graalvm.polyglot.Context;
+
+/**
+ * The interface to a source of input/output for the context, which may have different
+ * implementations for different contexts.
+ */
+public abstract class ConsoleHandler {
+
+    /**
+     * Read a line of input, newline is <b>NOT</b> included in result.
+     */
+    public abstract String readLine();
+
+    /**
+     * Set the R prompt.
+     */
+    public abstract void setPrompt(String prompt);
+
+    public void setContext(@SuppressWarnings("unused") Context context) {
+        // ignore by default
+    }
+
+    public InputStream createInputStream() {
+        return new InputStream() {
+            byte[] buffer = null;
+            int pos = -1;
+
+            @Override
+            public int read() throws IOException {
+                if (buffer == null) {
+                    pos = 0;
+                    String line = readLine();
+                    if (line == null) {
+                        return -1;
+                    }
+                    buffer = line.getBytes(StandardCharsets.UTF_8);
+                }
+                if (pos == buffer.length) {
+                    buffer = null;
+                    return '\n';
+                } else {
+                    return buffer[pos++];
+                }
+            }
+        };
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/DefaultConsoleHandler.java
similarity index 75%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/DefaultConsoleHandler.java
index 3bb4b182ccaf24cfbba29e1930d0fa3308614bf5..f5f1e0cd9b5ca3d6aafc7e16004cdd3045505e9e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/DefaultConsoleHandler.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/DefaultConsoleHandler.java
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.context;
+package com.oracle.truffle.r.launcher;
 
 import java.io.BufferedReader;
 import java.io.IOException;
@@ -40,26 +40,6 @@ public class DefaultConsoleHandler extends ConsoleHandler {
         this.out = new PrintStream(out);
     }
 
-    @Override
-    public void println(String s) {
-        out.println(s);
-    }
-
-    @Override
-    public void print(String s) {
-        out.print(s);
-    }
-
-    @Override
-    public void printErrorln(String s) {
-        out.println(s);
-    }
-
-    @Override
-    public void printError(String s) {
-        out.print(s);
-    }
-
     @Override
     public String readLine() {
         try {
@@ -72,23 +52,8 @@ public class DefaultConsoleHandler extends ConsoleHandler {
         }
     }
 
-    @Override
-    public boolean isInteractive() {
-        return true;
-    }
-
-    @Override
-    public String getPrompt() {
-        return prompt;
-    }
-
     @Override
     public void setPrompt(String prompt) {
         this.prompt = prompt;
     }
-
-    @Override
-    public String getInputDescription() {
-        return "<PolyglotEngine env input>";
-    }
 }
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc79ee71d212978d766ecfdf60de89138cac0f99
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java
@@ -0,0 +1,136 @@
+/*
+ * 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.launcher;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.graalvm.polyglot.Context;
+import org.graalvm.polyglot.Source;
+import org.graalvm.polyglot.Value;
+
+import jline.console.completer.Completer;
+
+public class JLineConsoleCompleter implements Completer {
+
+    private static boolean isTesting = false;
+    private final Context context;
+
+    public static void testingMode() {
+        isTesting = true;
+    }
+
+    public JLineConsoleCompleter(Context context) {
+        this.context = context;
+    }
+
+    @Override
+    public int complete(String buffer, int cursor, List<CharSequence> candidates) {
+        try {
+            return completeImpl(buffer, cursor, candidates);
+        } catch (Throwable e) {
+            if (isTesting) {
+                throw e;
+            }
+            throw RCommand.fatal(e, "error while determining completion");
+        }
+    }
+
+    private static final Source GET_COMPLETION_FUNCTION = Source.newBuilder("R", "utils:::.completeToken", "<completion>").internal(true).buildLiteral();
+    private static final Source GET_COMPLETION_ENV = Source.newBuilder("R", "utils:::.CompletionEnv", "<completion>").internal(true).buildLiteral();
+    private static final Source SET_FUNCTION = Source.newBuilder("R", "`$<-`", "<completion>").internal(true).buildLiteral();
+
+    private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
+        if (buffer.isEmpty()) {
+            return cursor;
+        }
+        Value completionFunction = context.eval(GET_COMPLETION_FUNCTION);
+        Value completionEnv = context.eval(GET_COMPLETION_ENV);
+        Value setFunction = context.eval(SET_FUNCTION);
+
+        int start = getStart(buffer, completionEnv, cursor);
+        setFunction.execute(completionEnv, "start", start);
+        setFunction.execute(completionEnv, "end", cursor);
+        setFunction.execute(completionEnv, "linebuffer", buffer);
+        setFunction.execute(completionEnv, "token", buffer.substring(start, cursor));
+
+        completionFunction.execute();
+
+        if (completionEnv.hasMember("comps")) {
+            Value completions = completionEnv.getMember("comps");
+            if (completions.isString()) {
+                candidates.add(completions.asString());
+                return start;
+            } else if (completions.hasArrayElements()) {
+                long length = completions.getArraySize();
+                List<String> result = new ArrayList<>((int) length);
+                for (int i = 0; i < length; i++) {
+                    result.add(completions.getArrayElement(i).asString());
+                }
+                Collections.sort(result, String.CASE_INSENSITIVE_ORDER);
+                candidates.addAll(result);
+                return start;
+            }
+        }
+        return cursor;
+    }
+
+    private static int getStart(String buffer, Value env, int cursor) {
+        int start = 0;
+        Value opt = env.getMember("options");
+        if (opt.hasMembers()) {
+            start = lastIdxOf(buffer, opt, "funarg.suffix", start, cursor);
+            start = lastIdxOf(buffer, opt, "function.suffix", start, cursor);
+        }
+        start = lastIdxOf(buffer, "\"", start, cursor);
+        start = lastIdxOf(buffer, "'", start, cursor);
+        return start;
+    }
+
+    private static int lastIdxOf(String buffer, Value opt, String key, int start, int cursor) {
+        if (opt.hasMember(key)) {
+            Value member = opt.getMember(key);
+            if (member.isString()) {
+                return lastIdxOf(buffer, member.asString(), start, cursor);
+            } else if (member.hasArrayElements() && member.getArraySize() > 0 && member.getArrayElement(0).isString()) {
+                return lastIdxOf(buffer, member.getArrayElement(0).asString(), start, cursor);
+            }
+        }
+        return start;
+    }
+
+    private static int lastIdxOf(String buffer, String subs, int start, int cursor) {
+        if (!subs.isEmpty()) {
+            int idx = buffer.lastIndexOf(subs, cursor);
+            if (idx == cursor) {
+                idx = buffer.lastIndexOf(subs, cursor - 1);
+            }
+            if (idx > -1) {
+                idx += subs.length();
+                return idx > start ? idx : start;
+            }
+        }
+        return start;
+    }
+}
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleHandler.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..e3c4cee27ef1c5139af1cdfa22552b540f4cf8ff
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleHandler.java
@@ -0,0 +1,97 @@
+/*
+ * 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
+ * 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.launcher;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.graalvm.polyglot.Context;
+
+import jline.console.ConsoleReader;
+import jline.console.UserInterruptException;
+import jline.console.completer.CandidateListCompletionHandler;
+import jline.console.completer.CompletionHandler;
+import jline.console.history.MemoryHistory;
+
+public class JLineConsoleHandler extends ConsoleHandler {
+    private final ConsoleReader console;
+    private final MemoryHistory history;
+    private final boolean noPrompt;
+
+    public JLineConsoleHandler(InputStream inStream, OutputStream outStream, boolean noPrompt) {
+        this.noPrompt = noPrompt;
+        try {
+            console = new ConsoleReader(inStream, outStream);
+            history = new MemoryHistory();
+            console.setHistory(history);
+            console.setHandleUserInterrupt(true);
+            console.setExpandEvents(false);
+        } catch (IOException ex) {
+            throw RCommand.fatal(ex, "unexpected error opening console reader");
+        }
+    }
+
+    @Override
+    public void setContext(Context context) {
+        console.addCompleter(new JLineConsoleCompleter(context));
+        CompletionHandler completionHandler = console.getCompletionHandler();
+        if (completionHandler instanceof CandidateListCompletionHandler) {
+            ((CandidateListCompletionHandler) completionHandler).setPrintSpaceAfterFullCompletion(false);
+        }
+    }
+
+    @Override
+    public String readLine() {
+        try {
+            console.getTerminal().init();
+            return console.readLine();
+        } catch (UserInterruptException e) {
+            // interrupted by ctrl-c
+            return "";
+        } catch (Exception ex) {
+            throw new RuntimeException(ex);
+        }
+    }
+
+    @Override
+    public void setPrompt(String prompt) {
+        console.setPrompt(noPrompt ? "" : prompt != null ? prompt : "");
+    }
+
+    public void clearHistory() {
+        history.clear();
+    }
+
+    public void addToHistory(String input) {
+        history.add(input);
+    }
+
+    public String[] getHistory() {
+        String[] result = new String[history.size()];
+        for (int i = 0; i < history.size(); i++) {
+            result[i] = history.get(i).toString();
+        }
+        return result;
+    }
+}
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/Launcher.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/Launcher.java
new file mode 100644
index 0000000000000000000000000000000000000000..15052181a450fae471c3ac50c498bf859acb2d82
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/Launcher.java
@@ -0,0 +1,501 @@
+/*
+ * Copyright (c) 2017, 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.launcher;
+
+import static java.lang.Integer.max;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.graalvm.options.OptionCategory;
+import org.graalvm.options.OptionDescriptor;
+import org.graalvm.options.OptionDescriptors;
+import org.graalvm.polyglot.Engine;
+import org.graalvm.polyglot.Instrument;
+import org.graalvm.polyglot.Language;
+
+public abstract class Launcher {
+    private static final boolean STATIC_VERBOSE = Boolean.getBoolean("org.graalvm.launcher.verbose");
+
+    private Engine tempEngine;
+
+    private final boolean verbose;
+
+    private boolean help;
+    private boolean helpDebug;
+    private boolean helpExpert;
+    private boolean helpTools;
+    private boolean helpLanguages;
+
+    private OptionCategory helpCategory;
+    private VersionAction versionAction = VersionAction.None;
+
+    protected enum VersionAction {
+        None,
+        PrintAndExit,
+        PrintAndContinue
+    }
+
+    public Launcher() {
+        verbose = STATIC_VERBOSE || Boolean.valueOf(System.getenv("VERBOSE_GRAALVM_LAUNCHERS"));
+    }
+
+    private Engine getTempEngine() {
+        if (tempEngine == null) {
+            tempEngine = Engine.create();
+        }
+        return tempEngine;
+    }
+
+    void setHelpCategory(OptionCategory helpCategory) {
+        this.helpCategory = helpCategory;
+    }
+
+    protected void setVersionAction(VersionAction versionAction) {
+        this.versionAction = versionAction;
+    }
+
+    private static class AbortException extends RuntimeException {
+        static final long serialVersionUID = 4681646279864737876L;
+
+        AbortException(String message) {
+            super(message, null);
+        }
+
+        @SuppressWarnings("sync-override")
+        @Override
+        public final Throwable fillInStackTrace() {
+            return null;
+        }
+    }
+
+    protected AbortException exit() {
+        return abort(null, 0);
+    }
+
+    protected AbortException abort(String message) {
+        return abort(message, 1);
+    }
+
+    protected AbortException abort(String message, int exitCode) {
+        if (message != null) {
+            System.err.println("ERROR: " + message);
+        }
+        System.exit(exitCode);
+        throw new AbortException(message);
+    }
+
+    protected abstract void printHelp(OptionCategory maxCategory);
+
+    protected abstract void printVersion();
+
+    protected abstract void collectArguments(Set<String> options);
+
+    protected static void printPolyglotVersions() {
+        Engine engine = Engine.create();
+        System.out.println("GraalVM Polyglot Engine Version " + engine.getVersion());
+        printLanguages(engine, true);
+        printInstruments(engine, true);
+    }
+
+    protected boolean isVerbose() {
+        return verbose;
+    }
+
+    final boolean runPolyglotAction() {
+        OptionCategory maxCategory = helpDebug ? OptionCategory.DEBUG : (helpExpert ? OptionCategory.EXPERT : (helpCategory != null ? helpCategory : OptionCategory.USER));
+
+        switch (versionAction) {
+            case PrintAndContinue:
+                printVersion();
+                return false;
+            case PrintAndExit:
+                printVersion();
+                return true;
+            case None:
+                break;
+        }
+        boolean printDefaultHelp = helpCategory != null || help || ((helpExpert || helpDebug) && !helpTools && !helpLanguages);
+        Engine tmpEngine = null;
+        if (printDefaultHelp) {
+            printHelp(maxCategory);
+            // @formatter:off
+            System.out.println();
+            System.out.println("Runtime Options:");
+            printOption("--polyglot",                   "Run with all other guest languages accessible.");
+            printOption("--native",                     "Run using the native launcher with limited Java access (default).");
+            printOption("--native.[option]",            "Pass options to the native image; for example, '--native.Xmx1G'. To see available options, use '--native.help'.");
+            printOption("--jvm",                        "Run on the Java Virtual Machine with Java access.");
+            printOption("--jvm.[option]",               "Pass options to the JVM; for example, '--jvm.classpath=myapp.jar'. To see available options. use '--jvm.help'.");
+            printOption("--help",                       "Print this help message.");
+            printOption("--help:languages",             "Print options for all installed languages.");
+            printOption("--help:tools",                 "Print options for all installed tools.");
+            printOption("--help:expert",                "Print additional engine options for experts.");
+            if (helpExpert || helpDebug) {
+                printOption("--help:debug",             "Print additional engine options for debugging.");
+            }
+            printOption("--version",                    "Print version information and exit.");
+            printOption("--show-version",               "Print version information and continue execution.");
+            // @formatter:on
+            if (tmpEngine == null) {
+                tmpEngine = Engine.create();
+            }
+            List<PrintableOption> engineOptions = new ArrayList<>();
+            for (OptionDescriptor descriptor : tmpEngine.getOptions()) {
+                if (!descriptor.getName().startsWith("engine.") && !descriptor.getName().startsWith("compiler.")) {
+                    continue;
+                }
+                if (descriptor.getCategory().ordinal() <= maxCategory.ordinal()) {
+                    engineOptions.add(asPrintableOption(descriptor));
+                }
+            }
+            if (!engineOptions.isEmpty()) {
+                printOptions(engineOptions, "Engine options:", 2);
+            }
+        }
+
+        if (helpLanguages) {
+            if (tmpEngine == null) {
+                tmpEngine = Engine.create();
+            }
+            printLanguageOptions(tmpEngine, maxCategory);
+        }
+
+        if (helpTools) {
+            if (tmpEngine == null) {
+                tmpEngine = Engine.create();
+            }
+            printInstrumentOptions(tmpEngine, maxCategory);
+        }
+
+        if (printDefaultHelp || helpLanguages || helpTools) {
+            System.out.println("\nSee http://www.oracle.com/technetwork/oracle-labs/program-languages/overview/index.html for more information.");
+            return true;
+        }
+
+        return false;
+    }
+
+    private static void printInstrumentOptions(Engine engine, OptionCategory maxCategory) {
+        Map<Instrument, List<PrintableOption>> instrumentsOptions = new HashMap<>();
+        List<Instrument> instruments = sortedInstruments(engine);
+        for (Instrument instrument : instruments) {
+            List<PrintableOption> options = new ArrayList<>();
+            for (OptionDescriptor descriptor : instrument.getOptions()) {
+                if (descriptor.getCategory().ordinal() <= maxCategory.ordinal()) {
+                    options.add(asPrintableOption(descriptor));
+                }
+            }
+            if (!options.isEmpty()) {
+                instrumentsOptions.put(instrument, options);
+            }
+        }
+        if (!instrumentsOptions.isEmpty()) {
+            System.out.println();
+            System.out.println("Tool options:");
+            for (Instrument instrument : instruments) {
+                List<PrintableOption> options = instrumentsOptions.get(instrument);
+                if (options != null) {
+                    printOptions(options, "  " + instrument.getName() + ":", 4);
+                }
+            }
+        }
+    }
+
+    private static void printLanguageOptions(Engine engine, OptionCategory maxCategory) {
+        Map<Language, List<PrintableOption>> languagesOptions = new HashMap<>();
+        List<Language> languages = sortedLanguages(engine);
+        for (Language language : languages) {
+            List<PrintableOption> options = new ArrayList<>();
+            for (OptionDescriptor descriptor : language.getOptions()) {
+                if (descriptor.getCategory().ordinal() <= maxCategory.ordinal()) {
+                    options.add(asPrintableOption(descriptor));
+                }
+            }
+            if (!options.isEmpty()) {
+                languagesOptions.put(language, options);
+            }
+        }
+        if (!languagesOptions.isEmpty()) {
+            System.out.println();
+            System.out.println("Language Options:");
+            for (Language language : languages) {
+                List<PrintableOption> options = languagesOptions.get(language);
+                if (options != null) {
+                    printOptions(options, "  " + language.getName() + ":", 4);
+                }
+            }
+        }
+    }
+
+    protected boolean parsePolyglotOption(String defaultOptionPrefix, Map<String, String> options, String arg) {
+        switch (arg) {
+            case "--help":
+                help = true;
+                return true;
+            case "--help:debug":
+                helpDebug = true;
+                return true;
+            case "--help:expert":
+                helpExpert = true;
+                return true;
+            case "--help:tools":
+                helpTools = true;
+                return true;
+            case "--help:languages":
+                helpLanguages = true;
+                return true;
+            case "--version":
+                versionAction = VersionAction.PrintAndExit;
+                return true;
+            case "--show-version":
+                versionAction = VersionAction.PrintAndContinue;
+                return true;
+            case "--polyglot":
+            case "--jvm":
+            case "--native":
+                return false;
+            default:
+                // getLanguageId() or null?
+                if (arg.length() <= 2 || !arg.startsWith("--")) {
+                    return false;
+                }
+                int eqIdx = arg.indexOf('=');
+                String key;
+                String value;
+                if (eqIdx < 0) {
+                    key = arg.substring(2);
+                    value = null;
+                } else {
+                    key = arg.substring(2, eqIdx);
+                    value = arg.substring(eqIdx + 1);
+                }
+
+                if (value == null) {
+                    value = "true";
+                }
+                int index = key.indexOf('.');
+                String group = key;
+                if (index >= 0) {
+                    group = group.substring(0, index);
+                }
+                OptionDescriptor descriptor = findPolyglotOptionDescriptor(group, key);
+                if (descriptor == null) {
+                    if (defaultOptionPrefix != null) {
+                        descriptor = findPolyglotOptionDescriptor(defaultOptionPrefix, defaultOptionPrefix + "." + key);
+                    }
+                    if (descriptor == null) {
+                        return false;
+                    }
+                }
+                try {
+                    descriptor.getKey().getType().convert(value);
+                } catch (IllegalArgumentException e) {
+                    throw abort(String.format("Invalid argument %s specified. %s'", arg, e.getMessage()));
+                }
+                options.put(key, value);
+                return true;
+        }
+    }
+
+    private OptionDescriptor findPolyglotOptionDescriptor(String group, String key) {
+        OptionDescriptors descriptors = null;
+        switch (group) {
+            case "compiler":
+            case "engine":
+                descriptors = getTempEngine().getOptions();
+                break;
+            default:
+                Engine engine = getTempEngine();
+                if (engine.getLanguages().containsKey(group)) {
+                    descriptors = engine.getLanguages().get(group).getOptions();
+                } else if (engine.getInstruments().containsKey(group)) {
+                    descriptors = engine.getInstruments().get(group).getOptions();
+                }
+                break;
+        }
+        if (descriptors == null) {
+            return null;
+        }
+        return descriptors.get(key);
+    }
+
+    protected static List<Language> sortedLanguages(Engine engine) {
+        List<Language> languages = new ArrayList<>(engine.getLanguages().values());
+        languages.sort(Comparator.comparing(Language::getId));
+        return languages;
+    }
+
+    protected static List<Instrument> sortedInstruments(Engine engine) {
+        List<Instrument> instruments = new ArrayList<>(engine.getInstruments().values());
+        instruments.sort(Comparator.comparing(Instrument::getId));
+        return instruments;
+    }
+
+    protected static void printOption(OptionCategory maxCategory, OptionDescriptor descriptor) {
+        if (descriptor.getCategory().ordinal() <= maxCategory.ordinal()) {
+            printOption(asPrintableOption(descriptor));
+        }
+    }
+
+    protected static PrintableOption asPrintableOption(OptionDescriptor descriptor) {
+        StringBuilder key = new StringBuilder("--");
+        key.append(descriptor.getName());
+        Object defaultValue = descriptor.getKey().getDefaultValue();
+        if (defaultValue instanceof Boolean && defaultValue == Boolean.FALSE) {
+            // nothing to print
+        } else {
+            key.append("=<");
+            key.append(descriptor.getKey().getType().getName());
+            key.append(">");
+        }
+        return new PrintableOption(key.toString(), descriptor.getHelp());
+    }
+
+    protected static void printOption(String option, String description) {
+        printOption(option, description, 2);
+    }
+
+    protected static void printOption(String option, String description, int indentation) {
+        StringBuilder indent = new StringBuilder(indentation);
+        for (int i = 0; i < indentation; i++) {
+            indent.append(' ');
+        }
+        String desc = description != null ? description : "";
+        if (option.length() >= 45 && description != null) {
+            System.out.println(String.format("%s%s%n%s%-45s%s", indent, option, indent, "", desc));
+        } else {
+            System.out.println(String.format("%s%-45s%s", indent, option, desc));
+        }
+    }
+
+    protected static void printOption(PrintableOption option) {
+        printOption(option, 2);
+    }
+
+    protected static void printOption(PrintableOption option, int indentation) {
+        printOption(option.option, option.description, indentation);
+    }
+
+    private static final class PrintableOption implements Comparable<PrintableOption> {
+        final String option;
+        final String description;
+
+        private PrintableOption(String option, String description) {
+            this.option = option;
+            this.description = description;
+        }
+
+        @Override
+        public int compareTo(PrintableOption o) {
+            return this.option.compareTo(o.option);
+        }
+    }
+
+    private static void printOptions(List<PrintableOption> options, String title, int indentation) {
+        Collections.sort(options);
+        System.out.println(title);
+        for (PrintableOption option : options) {
+            printOption(option, indentation);
+        }
+    }
+
+    protected enum OS {
+        Darwin,
+        Linux,
+        Solaris;
+
+        private static OS findCurrent() {
+            final String name = System.getProperty("os.name");
+            if (name.equals("Linux")) {
+                return Linux;
+            }
+            if (name.equals("SunOS")) {
+                return Solaris;
+            }
+            if (name.equals("Mac OS X") || name.equals("Darwin")) {
+                return Darwin;
+            }
+            throw new IllegalArgumentException("unknown OS: " + name);
+        }
+
+        private static final OS current = findCurrent();
+
+        public static OS getCurrent() {
+            return current;
+        }
+    }
+
+    protected static void printLanguages(Engine engine, boolean printWhenEmpty) {
+        if (engine.getLanguages().isEmpty()) {
+            if (printWhenEmpty) {
+                System.out.println("  Installed Languages: none");
+            }
+        } else {
+            System.out.println("  Installed Languages:");
+            List<Language> languages = new ArrayList<>(engine.getLanguages().size());
+            int nameLength = 0;
+            for (Language language : engine.getLanguages().values()) {
+                languages.add(language);
+                nameLength = max(nameLength, language.getName().length());
+            }
+            languages.sort(Comparator.comparing(Language::getId));
+            String langFormat = "    %-" + nameLength + "s%s version %s%n";
+            for (Language language : languages) {
+                String version = language.getVersion();
+                if (version == null || version.length() == 0) {
+                    version = "";
+                }
+                System.out.printf(langFormat, language.getName().isEmpty() ? "Unnamed" : language.getName(), version);
+            }
+        }
+    }
+
+    protected static void printInstruments(Engine engine, boolean printWhenEmpty) {
+        if (engine.getInstruments().isEmpty()) {
+            if (printWhenEmpty) {
+                System.out.println("  Installed Tools: none");
+            }
+        } else {
+            System.out.println("  Installed Tools:");
+            List<Instrument> instruments = sortedInstruments(engine);
+            int nameLength = 0;
+            for (Instrument instrument : instruments) {
+                nameLength = max(nameLength, instrument.getName().length());
+            }
+            String instrumentFormat = "    %-" + nameLength + "s version %s%n";
+            for (Instrument instrument : instruments) {
+                String version = instrument.getVersion();
+                if (version == null || version.length() == 0) {
+                    version = "";
+                }
+                System.out.printf(instrumentFormat, instrument.getName().isEmpty() ? "Unnamed" : instrument.getName(), version);
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCmdOptions.java
similarity index 85%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCmdOptions.java
index 56b321b10bc4e1795db1cf39e613eb82158b6e9e..d21b3d68e3ea54a4145ccc80390df845b07ed980 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCmdOptions.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCmdOptions.java
@@ -20,10 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime;
+package com.oracle.truffle.r.launcher;
 
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.HELP;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VERSION;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.HELP;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.VERSION;
 
 import java.util.ArrayList;
 import java.util.EnumMap;
@@ -53,7 +53,7 @@ public final class RCmdOptions {
         EITHER {
             @Override
             public String usage() {
-                throw Utils.rSuicide("can't call usage() on Client.EITHER");
+                throw RCommand.fatal("can't call usage() on Client.EITHER");
             }
         };
 
@@ -97,11 +97,11 @@ public final class RCmdOptions {
         // Whether this option is actually implemented in FastR
         private final boolean implemented;
         // The short option name prefixed by {@code -} or {@code null} if no {@code -} form.
-        private final String shortName;
+        final String shortName;
         // The option name prefixed by {@code --} or {@code null} if no {@code --} form.
         private final String name;
         // The plain option name as passed to the constructor.
-        public final String plainName;
+        final String plainName;
         // The '=' separated suffix, e.g. {@code --file=FILE}.
         private final String suffix;
         // The space separated suffix, e.g. {@code -g TYPE}.
@@ -131,7 +131,7 @@ public final class RCmdOptions {
                 this.suffix = eqx > 0 ? name.substring(eqx) : null;
             }
             this.defaultValue = defaultValue;
-            this.help = help.replace("\n", "\n                          ");
+            this.help = help;
         }
 
         RCmdOption(RCmdOptionType type, boolean implemented, String shortName, String name, Object defaultValue, String help) {
@@ -142,16 +142,6 @@ public final class RCmdOptions {
             this(type, Client.EITHER, implemented, null, name, defaultValue, help);
         }
 
-        private boolean matches(String arg) {
-            if (shortName != null && arg.equals(shortName)) {
-                return true;
-            }
-            if (name != null && arg.equals(name)) {
-                return true;
-            }
-            return false;
-        }
-
         private String getHelpName() {
             String result = "";
             if (shortName != null) {
@@ -247,18 +237,22 @@ public final class RCmdOptions {
 
     private static MatchResult matchOption(String arg) {
         for (RCmdOption option : RCmdOption.values()) {
-            if (option.type == RCmdOptionType.BOOLEAN) {
-                // these must match exactly
-                if (option.matches(arg)) {
-                    return new MatchResult(option, false);
-                }
-            } else if (option.type == RCmdOptionType.STRING || option.type == RCmdOptionType.REPEATED_STRING) {
-                // short forms must match exactly (and consume next argument)
-                if (option.shortName != null && option.shortName.equals(arg)) {
-                    return new MatchResult(option, true);
-                } else if (arg.indexOf('=') > 0 && option.name != null && arg.startsWith(option.name)) {
-                    return new MatchResult(option, false);
-                }
+            switch (option.type) {
+                case BOOLEAN:
+                    // these must match exactly
+                    if (option.shortName != null && arg.equals(option.shortName) || option.name != null && arg.equals(option.name)) {
+                        return new MatchResult(option, false);
+                    }
+                    break;
+                case STRING:
+                case REPEATED_STRING:
+                    // short forms must match exactly (and consume next argument)
+                    if (option.shortName != null && option.shortName.equals(arg)) {
+                        return new MatchResult(option, true);
+                    } else if (arg.indexOf('=') > 0 && option.name != null && arg.startsWith(option.name)) {
+                        return new MatchResult(option, false);
+                    }
+                    break;
             }
         }
         return null;
@@ -276,9 +270,9 @@ public final class RCmdOptions {
      * reasons) so we use "FastR". However, embedded mode does pass the executable in
      * {@code args[0]} and we do not want to parse that!
      */
-    public static RCmdOptions parseArguments(Client client, String[] args, boolean embedded) {
+    public static RCmdOptions parseArguments(Client client, String[] args, boolean reparse) {
         EnumMap<RCmdOption, Object> options = new EnumMap<>(RCmdOption.class);
-        int i = embedded ? 1 : 0;
+        int i = 1; // skip the first argument (the command)
         int firstNonOptionArgIndex = args.length;
         while (i < args.length) {
             final String arg = args[i];
@@ -289,8 +283,10 @@ public final class RCmdOptions {
                     firstNonOptionArgIndex = i;
                     break;
                 }
-                // GnuR does not abort, simply issues a warning
-                System.out.printf("WARNING: unknown option '%s'%n", arg);
+                if (!reparse) {
+                    // GnuR does not abort, simply issues a warning
+                    System.out.printf("WARNING: unknown option '%s'%n", arg);
+                }
                 i++;
                 continue;
             } else {
@@ -302,7 +298,9 @@ public final class RCmdOptions {
                 }
                 // check implemented
                 if (!option.implemented) {
-                    System.out.println("WARNING: option: " + arg + " is not implemented");
+                    if (!reparse) {
+                        System.out.println("WARNING: option: " + arg + " is not implemented");
+                    }
                 }
                 if (result.matchedShort) {
                     i++;
@@ -323,17 +321,8 @@ public final class RCmdOptions {
                 }
             }
         }
-        String[] xargs;
-        if (embedded) {
-            xargs = args;
-        } else {
-            xargs = new String[args.length + 1];
-            xargs[0] = "FastR";
-            System.arraycopy(args, 0, xargs, 1, args.length);
-        }
-
         // adjust for inserted executable name
-        return new RCmdOptions(options, xargs, firstNonOptionArgIndex + 1);
+        return new RCmdOptions(options, args, firstNonOptionArgIndex);
     }
 
     public String[] getArguments() {
@@ -348,32 +337,38 @@ public final class RCmdOptions {
         this.arguments = arguments;
     }
 
-    public void printHelpAndVersion() {
+    void printHelpAndVersion() {
         if (getBoolean(HELP)) {
-            printHelpAndExit(RCmdOptions.Client.R);
+            throw printHelpAndExit(RCmdOptions.Client.R);
         } else if (getBoolean(VERSION)) {
-            printVersionAndExit();
+            throw printVersionAndExit();
         }
     }
 
-    private static void printHelp(Client client) {
+    static void printHelp(Client client) {
         System.out.println(client.usage());
         System.out.println("Options:");
         for (RCmdOption option : RCmdOption.values()) {
-            System.out.printf("  %-22s  %s%n", option.getHelpName(), option.help);
+            System.out.printf("  %-22s  %s%n", option.getHelpName(), option.help.replace("\n", "\n                          "));
         }
         System.out.println("\nFILE may contain spaces but not shell metacharacters.\n");
     }
 
-    public static void printHelpAndExit(Client client) {
+    private static RuntimeException printHelpAndExit(Client client) {
         printHelp(client);
-        throw new ExitException(0);
+        System.exit(0);
+        throw RCommand.fatal("should not reach here");
     }
 
-    private static void printVersionAndExit() {
+    static void printVersion() {
         System.out.print("FastR version ");
         System.out.println(RVersionNumber.FULL);
-        System.out.println(RRuntime.LICENSE);
+        System.out.println(RVersionNumber.LICENSE);
+    }
+
+    private static RuntimeException printVersionAndExit() {
+        printVersion();
         System.exit(0);
+        throw RCommand.fatal("should not reach here");
     }
 }
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..dc891a94003a5e84a79b27dc8077cea4b4fbacb4
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.launcher;
+
+import java.io.EOFException;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.graalvm.options.OptionCategory;
+import org.graalvm.polyglot.Context;
+import org.graalvm.polyglot.PolyglotException;
+import org.graalvm.polyglot.Source;
+
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption;
+
+import jline.console.UserInterruptException;
+
+class RLauncher extends Launcher {
+
+    private final Client client;
+
+    RLauncher(Client client) {
+        this.client = client;
+    }
+
+    @Override
+    protected void printHelp(OptionCategory maxCategory) {
+        RCmdOptions.printHelp(client);
+    }
+
+    @Override
+    protected void printVersion() {
+        RCmdOptions.printVersion();
+    }
+
+    @Override
+    protected void collectArguments(Set<String> options) {
+        for (RCmdOption option : RCmdOption.values()) {
+            if (option.shortName != null) {
+                options.add(option.shortName);
+            }
+            if (option.plainName != null) {
+                options.add(option.plainName);
+            }
+        }
+    }
+}
+
+/*
+ * TODO:
+ *
+ * - create a replacement for "executor"
+ *
+ * - fatal needs to be handled more carefully in nested/spawned contexts
+ */
+
+/**
+ * Emulates the (Gnu)R command as precisely as possible.
+ */
+public class RCommand {
+
+    // CheckStyle: stop system..print check
+    public static RuntimeException fatal(String message, Object... args) {
+        System.out.println("FATAL: " + String.format(message, args));
+        System.exit(-1);
+        return null;
+    }
+
+    public static RuntimeException fatal(Throwable t, String message, Object... args) {
+        t.printStackTrace();
+        System.out.println("FATAL: " + String.format(message, args));
+        System.exit(-1);
+        return null;
+    }
+
+    public static void main(String[] args) {
+        try {
+            System.exit(doMain(prependCommand(args), null, System.in, System.out, System.err));
+            // never returns
+            throw fatal("main should never return");
+        } catch (Throwable t) {
+            throw fatal(t, "error during REPL execution");
+        }
+    }
+
+    static String[] prependCommand(String[] args) {
+        String[] result = new String[args.length + 1];
+        result[0] = "R";
+        System.arraycopy(args, 0, result, 1, args.length);
+        return result;
+    }
+
+    public static int doMain(String[] args, String[] env, InputStream inStream, OutputStream outStream, OutputStream errStream) {
+        StartupTiming.timestamp("Main Entered");
+        ArrayList<String> argsList = new ArrayList<>(Arrays.asList(args));
+        if (System.console() != null) {
+            // add "--interactive" to force interactive mode
+            boolean addArg = true;
+            for (String arg : args) {
+                if ("--interactive".equals(arg)) {
+                    addArg = false;
+                    break;
+                }
+            }
+            if (addArg) {
+                if (argsList.size() == 0) {
+                    argsList.add("--interactive");
+                } else {
+                    argsList.add(1, "--interactive");
+                }
+            }
+        }
+
+        RLauncher launcher = new RLauncher(Client.R);
+        Map<String, String> polyglotOptions = new HashMap<>();
+        for (int i = 1; i < argsList.size(); i++) {
+            String arg = argsList.get(i);
+            if (launcher.parsePolyglotOption("R", polyglotOptions, arg)) {
+                argsList.remove(i);
+            }
+        }
+        if (launcher.runPolyglotAction()) {
+            return 0;
+        }
+        RCmdOptions options = RCmdOptions.parseArguments(Client.R, argsList.toArray(new String[argsList.size()]), false);
+        assert env == null || env.length == 0 : "re-enable setting environments";
+        ConsoleHandler consoleHandler = createConsoleHandler(options, false, inStream, outStream);
+        try (Context context = Context.newBuilder().options(polyglotOptions).arguments("R", options.getArguments()).in(consoleHandler.createInputStream()).out(outStream).err(errStream).build()) {
+            consoleHandler.setContext(context);
+            StartupTiming.timestamp("VM Created");
+            StartupTiming.printSummary();
+            return readEvalPrint(context, consoleHandler);
+        }
+    }
+
+    public static ConsoleHandler createConsoleHandler(RCmdOptions options, boolean embedded, InputStream inStream, OutputStream outStream) {
+        /*
+         * Whether the input is from stdin, a file (-f), or an expression on the command line (-e)
+         * it goes through the console. N.B. -f and -e can't be used together and this is already
+         * checked.
+         */
+        RStartParams rsp = new RStartParams(options, false);
+        String fileArgument = rsp.getFileArgument();
+        if (fileArgument != null) {
+            List<String> lines;
+            try {
+                /*
+                 * If initial==false, ~ expansion will not have been done and the open will fail.
+                 * It's harmless to always do it.
+                 */
+                File file = fileArgument.startsWith("~") ? new File(System.getProperty("user.home") + fileArgument.substring(1)) : new File(fileArgument);
+                lines = Files.readAllLines(file.toPath());
+            } catch (IOException e) {
+                throw fatal("cannot open file '%s': No such file or directory", fileArgument);
+            }
+            return new StringConsoleHandler(lines, outStream);
+        } else if (options.getStringList(RCmdOption.EXPR) != null) {
+            List<String> exprs = options.getStringList(RCmdOption.EXPR);
+            for (int i = 0; i < exprs.size(); i++) {
+                exprs.set(i, unescapeSpace(exprs.get(i)));
+            }
+            return new StringConsoleHandler(exprs, outStream);
+        } else {
+            boolean isInteractive = options.getBoolean(RCmdOption.INTERACTIVE);
+            if (!isInteractive && rsp.askForSave()) {
+                fatal("you must specify '--save', '--no-save' or '--vanilla'");
+            }
+            if (embedded) {
+                /*
+                 * If we are in embedded mode, the creation of ConsoleReader and the ConsoleHandler
+                 * should be lazy, as these may not be necessary and can cause hangs if stdin has
+                 * been redirected.
+                 */
+                throw fatal("embedded mode disabled");
+                // consoleHandler = new EmbeddedConsoleHandler(rsp, engine);
+            } else {
+                boolean useReadLine = !rsp.noReadline();
+                if (useReadLine) {
+                    return new JLineConsoleHandler(inStream, outStream, rsp.isSlave());
+                } else {
+                    return new DefaultConsoleHandler(inStream, outStream);
+                }
+            }
+        }
+    }
+
+    /**
+     * The standard R script escapes spaces to "~+~" in "-e" and "-f" commands.
+     */
+    static String unescapeSpace(String input) {
+        return input.replace("~+~", " ");
+    }
+
+    private static final Source GET_ECHO = Source.newBuilder("R", ".Internal(getOption('echo'))", "<echo>").internal(true).buildLiteral();
+    private static final Source QUIT_EOF = Source.newBuilder("R", ".Internal(quit('default', 0L, TRUE))", "<quit-on-eof>").internal(true).buildLiteral();
+    private static final Source GET_PROMPT = Source.newBuilder("R", ".Internal(getOption('prompt'))", "<prompt>").internal(true).buildLiteral();
+    private static final Source GET_CONTINUE_PROMPT = Source.newBuilder("R", ".Internal(getOption('continue'))", "<continue-prompt>").internal(true).buildLiteral();
+
+    /**
+     * The read-eval-print loop, which can take input from a console, command line expression or a
+     * file. There are two ways the repl can terminate:
+     * <ol>
+     * <li>A {@code quit} command is executed successfully.</li>
+     * <li>EOF on the input.</li>
+     * </ol>
+     * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before
+     * exiting. So,in either case, we never return.
+     */
+    public static int readEvalPrint(Context context, ConsoleHandler consoleHandler) {
+        int lastStatus = 0;
+        try {
+            while (true) { // processing inputs
+                boolean doEcho = doEcho(context);
+                consoleHandler.setPrompt(doEcho ? getPrompt(context) : null);
+                try {
+                    String input = consoleHandler.readLine();
+                    if (input == null) {
+                        throw new EOFException();
+                    }
+                    String trInput = input.trim();
+                    if (trInput.equals("") || trInput.charAt(0) == '#') {
+                        // nothing to parse
+                        continue;
+                    }
+
+                    String continuePrompt = null;
+                    StringBuilder sb = new StringBuilder(input);
+                    while (true) { // processing subsequent lines while input is incomplete
+                        lastStatus = 0;
+                        try {
+                            context.eval(Source.newBuilder("R", sb.toString(), "<REPL>").interactive(true).buildLiteral());
+                        } catch (PolyglotException e) {
+                            if (continuePrompt == null) {
+                                continuePrompt = doEcho ? getContinuePrompt(context) : null;
+                            }
+                            if (e.isIncompleteSource()) {
+                                // read another line of input
+                                consoleHandler.setPrompt(continuePrompt);
+                                String additionalInput = consoleHandler.readLine();
+                                if (additionalInput == null) {
+                                    throw new EOFException();
+                                }
+                                sb.append('\n');
+                                sb.append(additionalInput);
+                                // The only continuation in the while loop
+                                continue;
+                            } else if (e.isExit()) {
+                                // usually from quit
+                                throw new ExitException(e.getExitStatus());
+                            } else if (e.isHostException() || e.isInternalError()) {
+                                // we continue the repl even though the system may be broken
+                                lastStatus = 1;
+                            } else if (e.isGuestException()) {
+                                // drop through to continue REPL and remember last eval was an error
+                                lastStatus = 1;
+                            }
+                        }
+                        break;
+                    }
+                } catch (UserInterruptException e) {
+                    // interrupted by ctrl-c
+                }
+            }
+        } catch (EOFException e) {
+            try {
+                context.eval(QUIT_EOF);
+            } catch (PolyglotException e2) {
+                if (e2.isExit()) {
+                    return e2.getExitStatus();
+                }
+                throw fatal(e, "error while calling quit");
+            }
+        } catch (ExitException e) {
+            return e.code;
+        }
+        return lastStatus;
+    }
+
+    @SuppressWarnings("serial")
+    private static final class ExitException extends RuntimeException {
+        private final int code;
+
+        ExitException(int code) {
+            this.code = code;
+        }
+    }
+
+    private static boolean doEcho(Context context) {
+        try {
+            return context.eval(GET_ECHO).asBoolean();
+        } catch (PolyglotException e) {
+            if (e.isExit()) {
+                throw new ExitException(e.getExitStatus());
+            }
+            throw fatal(e, "error while retrieving echo");
+        }
+    }
+
+    private static String getPrompt(Context context) {
+        try {
+            return context.eval(GET_PROMPT).asString();
+        } catch (PolyglotException e) {
+            if (e.isExit()) {
+                throw new ExitException(e.getExitStatus());
+            }
+            throw fatal(e, "error while retrieving prompt");
+        }
+    }
+
+    private static String getContinuePrompt(Context context) {
+        try {
+            return context.eval(GET_CONTINUE_PROMPT).asString();
+        } catch (PolyglotException e) {
+            if (e.isExit()) {
+                throw new ExitException(e.getExitStatus());
+            }
+            throw fatal(e, "error while retrieving continue prompt");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RStartParams.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RStartParams.java
new file mode 100644
index 0000000000000000000000000000000000000000..82de6f3fab306976005bcf555c90b25fc76ceec2
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RStartParams.java
@@ -0,0 +1,207 @@
+/*
+ * 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.launcher;
+
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.EXPR;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.FILE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.INTERACTIVE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_ENVIRON;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_INIT_FILE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_READLINE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_RESTORE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_RESTORE_DATA;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_SAVE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.NO_SITE_FILE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.QUIET;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.RESTORE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.SAVE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.SILENT;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.SLAVE;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.VANILLA;
+import static com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption.VERBOSE;
+
+import java.util.List;
+
+/**
+ * Defines startup parameters (that can be customized by embedding apps).
+ */
+public class RStartParams {
+
+    private final boolean quiet;
+    private final boolean slave;
+
+    /**
+     * The setting of this value in GNU R is unusual and not simply based on the value of the
+     * --interactive option, so we do not check the option in
+     * {@link #RStartParams(RCmdOptions, boolean)}, but later in {@code RCommand}.
+     */
+    private final boolean interactive;
+    private final boolean verbose;
+    private final boolean loadSiteFile;
+    private final boolean loadInitFile;
+    private final boolean debugInitFile;
+    private final boolean restoreAction;
+    private final boolean askForSave;
+    private final boolean save;
+    private final boolean noRenviron;
+
+    /**
+     * This is not a configurable option, but it is set on the command line and needs to be stored
+     * somewhere.
+     */
+    private final boolean noReadline;
+
+    /**
+     * Indicates that FastR is running embedded.
+     */
+    private final boolean embedded;
+    private final String fileArgument;
+
+    public RStartParams(RCmdOptions options, boolean embedded) {
+        this.embedded = embedded;
+        this.verbose = options.getBoolean(VERBOSE);
+        this.quiet = options.getBoolean(QUIET) || options.getBoolean(SILENT) || options.getBoolean(SLAVE);
+        this.loadSiteFile = options.getBoolean(NO_SITE_FILE);
+        this.loadInitFile = !embedded && options.getBoolean(NO_INIT_FILE) && !options.getBoolean(VANILLA);
+        this.noRenviron = embedded || options.getBoolean(NO_ENVIRON) || options.getBoolean(VANILLA);
+        this.restoreAction = options.getBoolean(RESTORE) && !(options.getBoolean(NO_RESTORE) || options.getBoolean(NO_RESTORE_DATA) || options.getBoolean(VANILLA));
+        this.noReadline = options.getBoolean(NO_READLINE);
+        this.slave = options.getBoolean(SLAVE);
+
+        /*
+         * GnuR behavior differs from the manual entry for {@code interactive} in that {@code
+         * --interactive} never applies to {@code -e/-f}, only to console input that has been
+         * redirected from a pipe/file etc.
+         */
+        String file = options.getString(FILE);
+        List<String> expressions = options.getStringList(EXPR);
+        if (file != null) {
+            if (expressions != null) {
+                throw RCommand.fatal("cannot use -e with -f or --file");
+            }
+            this.askForSave = false;
+            this.save = false;
+            if (file.equals("-")) {
+                // means stdin, but still implies NO_SAVE
+                file = null;
+            } else {
+                file = RCommand.unescapeSpace(file);
+            }
+            this.interactive = false;
+        } else if (expressions != null) {
+            this.interactive = false;
+            this.askForSave = false;
+            this.save = false;
+        } else {
+            this.interactive = options.getBoolean(INTERACTIVE);
+            if (slave || options.getBoolean(NO_SAVE) || options.getBoolean(VANILLA)) {
+                this.askForSave = false;
+                this.save = false;
+            } else if (options.getBoolean(SAVE)) {
+                this.askForSave = false;
+                this.save = true;
+            } else {
+                this.askForSave = true;
+                this.save = false;
+            }
+        }
+        this.fileArgument = file;
+        this.debugInitFile = false;
+    }
+
+    /**
+     * Only upcalled from native code.
+     */
+    @SuppressWarnings("unused")
+    public static void setParams(boolean quietA, boolean slaveA, boolean interactiveA, boolean verboseA, boolean loadSiteFileA,
+                    boolean loadInitFileA, boolean debugInitFileA, int restoreActionA, int saveActionA, boolean noRenvironA) {
+        assert false : "re-enable setParams";
+        // RStartParams params = RContext.getInstance().getStartParams();
+        // params.setQuiet(quietA);
+        // params.setSlave(slaveA);
+        // params.setInteractive(interactiveA);
+        // params.setVerbose(verboseA);
+        // params.setLoadSiteFile(loadSiteFileA);
+        // params.setLoadInitFile(loadInitFileA);
+        // params.setDebugInitFile(debugInitFileA);
+        // params.setSaveAction(SA_TYPE.values()[saveActionA]);
+        // params.setRestoreAction(SA_TYPE.values()[restoreActionA]);
+        // params.setNoRenviron(noRenvironA);
+    }
+
+    public boolean isQuiet() {
+        return this.quiet;
+    }
+
+    public boolean isSlave() {
+        return slave;
+    }
+
+    public boolean isInteractive() {
+        return this.interactive;
+    }
+
+    public boolean isVerbose() {
+        return this.verbose;
+    }
+
+    public boolean getLoadSiteFile() {
+        return this.loadSiteFile;
+    }
+
+    public boolean loadInitFile() {
+        return this.loadInitFile;
+    }
+
+    public boolean debugInitFile() {
+        return this.debugInitFile;
+    }
+
+    public boolean restore() {
+        return this.restoreAction;
+    }
+
+    public boolean save() {
+        return this.save;
+    }
+
+    public boolean askForSave() {
+        return this.askForSave;
+    }
+
+    public boolean noRenviron() {
+        return this.noRenviron;
+    }
+
+    public boolean noReadline() {
+        return this.noReadline;
+    }
+
+    public boolean isEmbedded() {
+        return embedded;
+    }
+
+    public String getFileArgument() {
+        return fileArgument;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionNumber.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RVersionNumber.java
similarity index 78%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionNumber.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RVersionNumber.java
index 4dcd65278766088267f90a7368a449b0761ec549..936a3ee33e0826fc7d9ef1fb0125f07600bdac6c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionNumber.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RVersionNumber.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
@@ -20,10 +20,10 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime;
+package com.oracle.truffle.r.launcher;
 
 /**
- * Defines the R version number and it's release date. Separate from {@link RVersionInfo} to allow
+ * Defines the R version number and it's release date. Separate from {code RVersionInfo} to allow
  * use in {@code static final} fields and to finesse the fact that such fields cannot precede the
  * {@code enum} elements.
  *
@@ -51,4 +51,11 @@ public class RVersionNumber {
     public static void main(String[] args) {
         System.out.printf("R version %s", FULL);
     }
+
+    public static final String LICENSE = "This software is distributed under the terms of the GNU General Public License\n" +
+                    "Version 2, June 1991. The terms of the license are in a file called COPYING\n" +
+                    "which you should have received with this software. A copy of the license can be\n" +
+                    "found at http://www.gnu.org/licenses/gpl-2.0.html.\n" +
+                    "\n" +
+                    "'Share and Enjoy.'";
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RscriptCommand.java
similarity index 52%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RscriptCommand.java
index 8e2be1e76aed3fc5cbcf73cf771740305479cf3e..1fecdef2659b15cf69373baa44e05bb88007925f 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RscriptCommand.java
@@ -20,24 +20,20 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.shell;
-
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.DEFAULT_PACKAGES;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.EXPR;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.FILE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.HELP;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_RESTORE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SLAVE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VERSION;
+package com.oracle.truffle.r.launcher;
 
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.graalvm.options.OptionCategory;
+import org.graalvm.polyglot.Context;
 
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RVersionNumber;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption;
 
 /**
  * Emulates the (Gnu)Rscript command as precisely as possible. in GnuR, Rscript is a genuine wrapper
@@ -46,44 +42,42 @@ import com.oracle.truffle.r.runtime.context.ContextInfo;
  *
  */
 public class RscriptCommand {
+
     // CheckStyle: stop system..print check
 
-    private static void preprocessRScriptOptions(RCmdOptions options) {
+    private static void preprocessRScriptOptions(RLauncher launcher, RCmdOptions options) {
         String[] arguments = options.getArguments();
         int resultArgsLength = arguments.length;
         int firstNonOptionArgIndex = options.getFirstNonOptionArgIndex();
-        if (options.getBoolean(HELP)) {
-            RCmdOptions.printHelpAndExit(RCmdOptions.Client.RSCRIPT);
-        } else if (options.getBoolean(VERSION)) {
-            printVersionAndExit();
-        }
         // Now reformat the args, setting --slave and --no-restore as per the spec
         ArrayList<String> adjArgs = new ArrayList<>(resultArgsLength + 1);
         adjArgs.add(arguments[0]);
         adjArgs.add("--slave");
-        options.setValue(SLAVE, true);
+        options.setValue(RCmdOption.SLAVE, true);
         adjArgs.add("--no-restore");
-        options.setValue(NO_RESTORE, true);
+        options.setValue(RCmdOption.NO_RESTORE, true);
         // Either -e options are set or first non-option arg is a file
-        if (options.getStringList(EXPR) == null) {
+        if (options.getStringList(RCmdOption.EXPR) == null) {
             if (firstNonOptionArgIndex == resultArgsLength) {
+                launcher.setHelpCategory(OptionCategory.USER);
                 // does not return
-                RCmdOptions.printHelpAndExit(RCmdOptions.Client.RSCRIPT);
+                if (launcher.runPolyglotAction()) {
+                    System.exit(1);
+                }
             } else {
                 if (arguments[firstNonOptionArgIndex].startsWith("-")) {
-                    System.out.println("file name is missing");
-                    System.exit(1);
+                    throw RCommand.fatal("file name is missing");
                 }
-                options.setValue(FILE, arguments[firstNonOptionArgIndex]);
+                options.setValue(RCmdOption.FILE, arguments[firstNonOptionArgIndex]);
             }
         }
-        String defaultPackagesArg = options.getString(DEFAULT_PACKAGES);
+        String defaultPackagesArg = options.getString(RCmdOption.DEFAULT_PACKAGES);
         String defaultPackagesEnv = System.getenv("R_DEFAULT_PACKAGES");
         if (defaultPackagesArg == null && defaultPackagesEnv == null) {
             defaultPackagesArg = "datasets,utils,grDevices,graphics,stats";
         }
         if (defaultPackagesEnv == null) {
-            options.setValue(DEFAULT_PACKAGES, defaultPackagesArg);
+            options.setValue(RCmdOption.DEFAULT_PACKAGES, defaultPackagesArg);
         }
         // copy up to non-option args
         int rx = 1;
@@ -91,8 +85,8 @@ public class RscriptCommand {
             adjArgs.add(arguments[rx]);
             rx++;
         }
-        if (options.getString(FILE) != null) {
-            adjArgs.add("--file=" + options.getString(FILE));
+        if (options.getString(RCmdOption.FILE) != null) {
+            adjArgs.add("--file=" + options.getString(RCmdOption.FILE));
             rx++; // skip over file arg
             firstNonOptionArgIndex++;
         }
@@ -107,25 +101,38 @@ public class RscriptCommand {
     }
 
     public static void main(String[] args) {
-        doMain(args, null, true, System.in, System.out);
-        // never returns
-        throw RInternalError.shouldNotReachHere();
+        System.exit(doMain(RCommand.prependCommand(args), null, System.in, System.out, System.err));
+        throw RCommand.fatal("should not reach here");
     }
 
-    public static int doMain(String[] args, String[] env, boolean initial, InputStream inStream, OutputStream outStream) {
-        // Since many of the options are shared parse them from an RSCRIPT perspective.
-        // Handle --help and --version specially, as they exit.
-        RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.RSCRIPT, args, false);
-        preprocessRScriptOptions(options);
-        ContextInfo info = RCommand.createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env);
-        return RCommand.readEvalPrint(info.createVM(), info);
+    public static int doMain(String[] args, String[] env, InputStream inStream, OutputStream outStream, OutputStream errStream) {
+        assert env == null : "re-enble environment variables";
 
-    }
+        ArrayList<String> argsList = new ArrayList<>(Arrays.asList(args));
+        RLauncher launcher = new RLauncher(Client.RSCRIPT) {
+            @Override
+            protected void printVersion() {
+                System.out.print("R scripting front-end version ");
+                System.out.println(RVersionNumber.FULL);
+            }
+        };
+        Map<String, String> polyglotOptions = new HashMap<>();
+        for (int i = 1; i < argsList.size(); i++) {
+            String arg = argsList.get(i);
+            if (launcher.parsePolyglotOption("R", polyglotOptions, arg)) {
+                argsList.remove(i);
+            }
+        }
+        if (launcher.runPolyglotAction()) {
+            return 0;
+        }
+        RCmdOptions options = RCmdOptions.parseArguments(Client.RSCRIPT, argsList.toArray(new String[argsList.size()]), false);
+        preprocessRScriptOptions(launcher, options);
 
-    private static void printVersionAndExit() {
-        // TODO Not ok in nested context
-        System.out.print("R scripting front-end version ");
-        System.out.println(RVersionNumber.FULL);
-        System.exit(0);
+        ConsoleHandler consoleHandler = RCommand.createConsoleHandler(options, false, inStream, outStream);
+        try (Context context = Context.newBuilder().options(polyglotOptions).arguments("R", options.getArguments()).in(consoleHandler.createInputStream()).out(outStream).err(errStream).build()) {
+            consoleHandler.setContext(context);
+            return RCommand.readEvalPrint(context, consoleHandler);
+        }
     }
 }
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StartupTiming.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StartupTiming.java
new file mode 100644
index 0000000000000000000000000000000000000000..866f24988a04696d71228ab86c5d7385222b2f1f
--- /dev/null
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StartupTiming.java
@@ -0,0 +1,110 @@
+/*
+ * 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.launcher;
+
+import java.io.PrintStream;
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentLinkedDeque;
+
+public final class StartupTiming {
+    public static final boolean ENABLED = "true".equals(System.getProperty("StartupTiming"));
+
+    private static volatile StartupTiming INSTANCE = null;
+
+    private final long startTime;
+    private final ConcurrentLinkedDeque<Timestamp> timestamps = new ConcurrentLinkedDeque<>();
+
+    private StartupTiming() {
+        RuntimeMXBean runtimeMXBean;
+        long st = 0L;
+        try {
+            runtimeMXBean = ManagementFactory.getRuntimeMXBean();
+            if (runtimeMXBean == null) {
+                st = System.currentTimeMillis();
+            } else {
+                st = runtimeMXBean.getStartTime();
+            }
+        } catch (Throwable t) {
+            st = System.currentTimeMillis();
+        }
+        startTime = st;
+    }
+
+    private static synchronized void init() {
+        if (INSTANCE == null) {
+            INSTANCE = new StartupTiming();
+        }
+    }
+
+    public static void timestamp(String name) {
+        if (ENABLED) {
+            init();
+            INSTANCE.putTimestamp(name);
+        }
+    }
+
+    public static void printSummary() {
+        if (ENABLED) {
+            init();
+            INSTANCE.summary(System.out);
+        }
+    }
+
+    private void putTimestamp(String tsName) {
+        timestamps.add(new Timestamp(System.currentTimeMillis(), tsName));
+    }
+
+    private void summary(PrintStream out) {
+        out.println("Startup timing table:");
+        out.println("<Timestamp>\t<FromStart>\t<FromPrev>");
+
+        TreeSet<Timestamp> sorted = new TreeSet<>(timestamps);
+        long prevTs = startTime;
+        for (Timestamp ts : sorted) {
+            long relTs = ts.timestamp - startTime;
+            long delta = ts.timestamp - prevTs;
+            String msg = ts.name;
+
+            out.printf("%s:\t%s ms\t(%s ms)\n", msg, relTs, delta);
+
+            prevTs = ts.timestamp;
+        }
+    }
+
+    private static final class Timestamp implements Comparable<Timestamp> {
+        private final long timestamp;
+        private final String name;
+
+        Timestamp(long ts, String name) {
+            this.timestamp = ts;
+            this.name = name;
+        }
+
+        @Override
+        public int compareTo(Timestamp other) {
+            return this.timestamp == other.timestamp ? 0 : (this.timestamp < other.timestamp ? -1 : 1);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StringConsoleHandler.java
similarity index 59%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
rename to com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StringConsoleHandler.java
index 271b69345df92e9297e4d81391d5fece14eff410..1327a8162997473ccaa032d9b4f27886e83d5f18 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/StringConsoleHandler.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/StringConsoleHandler.java
@@ -20,46 +20,24 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.shell;
+package com.oracle.truffle.r.launcher;
 
 import java.io.OutputStream;
 import java.io.PrintStream;
 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 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) {
+    StringConsoleHandler(List<String> lines, OutputStream output) {
         this.lines = lines;
         this.output = output instanceof PrintStream ? (PrintStream) output : new PrintStream(output);
-        this.inputDescription = inputDescription;
-    }
-
-    @Override
-    @TruffleBoundary
-    public void println(String s) {
-        output.println(s);
-        output.flush();
-    }
-
-    @Override
-    @TruffleBoundary
-    public void print(String s) {
-        output.print(s);
-        output.flush();
     }
 
     @Override
-    @TruffleBoundary
     public String readLine() {
         if (currentLine < lines.size()) {
             if (prompt != null) {
@@ -73,46 +51,7 @@ class StringConsoleHandler extends ConsoleHandler {
     }
 
     @Override
-    public boolean isInteractive() {
-        return false;
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printErrorln(String s) {
-        println(s);
-    }
-
-    @Override
-    @TruffleBoundary
-    public void printError(String s) {
-        print(s);
-    }
-
-    @Override
-    @TruffleBoundary
-    public String getPrompt() {
-        return prompt;
-    }
-
-    @Override
-    @TruffleBoundary
     public void setPrompt(String prompt) {
         this.prompt = prompt;
     }
-
-    @Override
-    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/DisplayList.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java
index 06f33e2aa39c73c53d369278b7485a04ef376a1d..89834ac50af2d878927acccc056c2165cae43537 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DisplayList.java
@@ -103,6 +103,5 @@ public class DisplayList {
             initDisplayList(gridState);
             return RNull.instance;
         }
-
     }
 }
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 016b8d9e98c8d7a83c1ede405b736cd431eb03d5..75d9d6ee5c0736b70933c19c375dcf9ca5eb5f1a 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
@@ -81,6 +81,8 @@ public final class FastRGridExternalLookup {
                 return CPalette.create();
             case "palette2":
                 return CPalette2.create();
+            case "devAskNewPage":
+                return new IgnoredGridExternal(RRuntime.LOGICAL_FALSE);
             default:
                 return null;
         }
@@ -132,6 +134,8 @@ public final class FastRGridExternalLookup {
                 return LCircle.create();
             case "L_points":
                 return LPoints.create();
+            case "L_raster":
+                return LRaster.create();
 
             // Bounds primitive:
             case "L_rectBounds":
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 48e5ca2d58fcd3da897908e0acc74003041ee96d..adba03004cfa945ccba56231ed7b4f4140995caa 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,7 +18,6 @@ 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;
@@ -26,7 +25,6 @@ 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;
@@ -267,21 +265,7 @@ public final class GPar {
 
         private GridColor getGridColor(int listIndex) {
             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);
+            GridColor color = GridColorUtils.getColor(value, index);
             double alpha = asDouble(data[GP_ALPHA], index);
             if (alpha != 1.) {
                 int newAlpha = Math.min(255, (int) (alpha * ((color.getAlpha() / 255.0) * 255)));
@@ -291,44 +275,6 @@ 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 1ec25bf728686609acfa0232c2515f4f09818363..c751e57f43cddaab2e1f1f8cf82918e246fffff6 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
@@ -18,6 +18,10 @@ 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;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public final class GridColorUtils {
 
@@ -27,6 +31,28 @@ public final class GridColorUtils {
         // only static members
     }
 
+    /**
+     * Converts given object into {@link GridColor}. The object may be a vector, in which case the
+     * index modulo its size is used to select element of that vector.
+     */
+    public static GridColor getColor(Object value, int index) {
+        GridColor color = GridColorUtils.getPaletteColor(value, index);
+        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;
+        }
+
+        return gridColorFromString(strValue);
+    }
+
     public static GridPalette getDefaultPalette() {
         if (defaultPalette == null) {
             // Note: default palette copied from GNU R
@@ -105,6 +131,44 @@ public final class GridColorUtils {
         return isNormalized ? synonym : synonym.replace(" ", "").toLowerCase(Locale.ROOT);
     }
 
+    private static GridColor getPaletteColor(Object colorIdIn, int index) {
+        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 static int paletteIdxFromString(String colorId) {
+        try {
+            return Integer.parseInt(colorId, 10);
+        } catch (NumberFormatException ex) {
+            return RRuntime.INT_NA;
+        }
+    }
+
     private static final class NamesHolder {
         private static final HashMap<String, Object> NAMES = new HashMap<>(700);
 
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
index efd87be667163e281801070eb5c2804b37d73378..688c3aa6344d79d994cf23b3fb4546485e4fe627 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridContext.java
@@ -28,14 +28,20 @@ import java.util.ArrayList;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.library.fastrGrid.GridState.GridDeviceState;
+import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
+import com.oracle.truffle.r.library.fastrGrid.device.SVGDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.awt.BufferedImageDevice.NotSupportedImageFormatException;
+import com.oracle.truffle.r.library.fastrGrid.grDevices.FileDevUtils;
 import com.oracle.truffle.r.library.fastrGrid.graphics.RGridGraphicsAdapter;
 import com.oracle.truffle.r.runtime.FastRConfig;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalCode;
+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.env.REnvironment;
@@ -55,7 +61,7 @@ public final class GridContext {
     private int currentDeviceIdx = 0;
 
     private GridContext() {
-        devices.add(new DeviceAndState(null));
+        devices.add(new DeviceAndState(null, null));
     }
 
     public static GridContext getContext() {
@@ -82,10 +88,15 @@ public final class GridContext {
     }
 
     public void setCurrentDevice(String name, GridDevice currentDevice) {
+        assert !(currentDevice instanceof FileGridDevice) : "FileGridDevice must have filenamePattern";
+        setCurrentDevice(name, currentDevice, null);
+    }
+
+    public void setCurrentDevice(String name, GridDevice currentDevice, String filenamePattern) {
         RGridGraphicsAdapter.addDevice(name);
         RGridGraphicsAdapter.setCurrentDevice(name);
         currentDeviceIdx = this.devices.size();
-        this.devices.add(new DeviceAndState(currentDevice));
+        this.devices.add(new DeviceAndState(currentDevice, filenamePattern));
         assert devices.size() == RGridGraphicsAdapter.getDevicesCount();
     }
 
@@ -94,9 +105,18 @@ public final class GridContext {
         if (defaultDev.equals("awt") || defaultDev.startsWith("X11")) {
             if (!FastRConfig.InternalGridAwtSupport) {
                 throw awtNotSupported();
-            } else {
-                setCurrentDevice(defaultDev, WindowDevice.createWindowDevice());
             }
+            setCurrentDevice(defaultDev, WindowDevice.createWindowDevice());
+        } else if (defaultDev.equals("svg")) {
+            String filename = "Rplot%03d.svg";
+            SVGDevice svgDevice = new SVGDevice(FileDevUtils.formatInitialFilename(filename), GridDevice.DEFAULT_WIDTH, GridDevice.DEFAULT_HEIGHT);
+            setCurrentDevice(defaultDev, svgDevice, filename);
+        } else if (defaultDev.equals("png")) {
+            safeOpenImageDev("Rplot%03d.png", "png");
+        } else if (defaultDev.equals("bmp")) {
+            safeOpenImageDev("Rplot%03d.bmp", "bmp");
+        } else if (defaultDev.equals("jpg") || defaultDev.equals("jpeg")) {
+            safeOpenImageDev("Rplot%03d.jpg", "jpeg");
         } else {
             throw RError.error(RError.NO_CALLER, Message.GENERIC, "FastR does not support device '" + defaultDev + "'.");
         }
@@ -132,13 +152,26 @@ public final class GridContext {
         return RContext.getEngine().evalFunction(redrawAll, REnvironment.baseEnv().getFrame(), RCaller.topLevel, true, null, args);
     }
 
+    private void safeOpenImageDev(String filename, String formatName) {
+        if (!FastRConfig.InternalGridAwtSupport) {
+            throw awtNotSupported();
+        }
+        BufferedImageDevice dev = null;
+        try {
+            dev = BufferedImageDevice.open(FileDevUtils.formatInitialFilename(filename), formatName, GridDevice.DEFAULT_WIDTH, GridDevice.DEFAULT_HEIGHT);
+        } catch (NotSupportedImageFormatException e) {
+            throw RInternalError.shouldNotReachHere("Device format " + formatName + " should be supported.");
+        }
+        setCurrentDevice(formatName, dev, filename);
+    }
+
     private static final class DeviceAndState {
         final GridDevice device;
         final GridDeviceState state;
 
-        DeviceAndState(GridDevice device) {
+        DeviceAndState(GridDevice device, String filenamePattern) {
             this.device = device;
-            this.state = new GridDeviceState();
+            this.state = new GridDeviceState(filenamePattern);
         }
     }
 }
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 20027f98003ddadbf07e640aa24cea53f7afe6b0..5579a9051982fdcfa38d77d60f9ddb4a1c316fd8 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
@@ -15,6 +15,7 @@ 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.library.fastrGrid.grDevices.FileDevUtils;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -97,8 +98,8 @@ public final class GridState {
         this.palette = palette;
     }
 
-    public void init(REnvironment gridEnv) {
-        this.gridEnv = gridEnv;
+    public void init(REnvironment newGridEnv) {
+        this.gridEnv = newGridEnv;
         this.currentGrob = RNull.instance;
     }
 
@@ -163,6 +164,10 @@ public final class GridState {
         return devState.scale;
     }
 
+    public String getNextPageFilename() {
+        return FileDevUtils.formatFilename(devState.filenamePattern, devState.pageIndex++);
+    }
+
     public static final class GridPalette {
         public final GridColor[] colors;
         public final String[] colorNames;
@@ -194,5 +199,11 @@ public final class GridState {
         private boolean isDisplayListOn = true;
         private RList displayList;
         private int displayListIndex = 0;
+        private int pageIndex = 2;
+        private String filenamePattern;
+
+        GridDeviceState(String filenamePattern) {
+            this.filenamePattern = filenamePattern;
+        }
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
index 76ccd7660bc91192096e874bdd7b4e111ce98696..342ef042b9a033270a600f1413d87abf583e5d81 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridTextNode.java
@@ -190,7 +190,7 @@ public final class GridTextNode extends RBaseNode {
 
     // transcribed from utils.c
 
-    private EdgeDetection.Rectangle textRect(Point loc, double xadj, double yadj, double rotation, String text, DrawingContext drawingCtx, GridDevice device) {
+    private static EdgeDetection.Rectangle textRect(Point loc, double xadj, double yadj, double rotation, String text, DrawingContext drawingCtx, GridDevice device) {
         // TODO: for expressions the h and w are calculated differently
         double h = device.getStringHeight(drawingCtx, text);
         double w = device.getStringWidth(drawingCtx, text);
@@ -208,7 +208,7 @@ public final class GridTextNode extends RBaseNode {
 
     // transcribed from engine.c
 
-    private void text(double x, double y, String text, double xadjIn, double yadj, double rotationDegrees, DrawingContext drawingCtx, GridDevice device) {
+    private static void text(double x, double y, String text, double xadjIn, double yadj, double rotationDegrees, DrawingContext drawingCtx, GridDevice device) {
         if (!Double.isFinite(yadj)) {
             throw RInternalError.unimplemented("'exact' vertical centering, see engine.c:1700");
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
index a66bbdb689aed171f31a89dc433496f2d1d0aa28..18eb6ca910fc8b64c626e96b27fae262cd2229bd 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java
@@ -103,7 +103,7 @@ public abstract class LConvert extends RExternalBuiltinNode.Arg4 {
         return RDataFactory.createDoubleVector(result, RDataFactory.COMPLETE_VECTOR);
     }
 
-    private double toInches(RAbstractVector units, int index, AxisOrDimension axisFrom, UnitConversionContext conversionCtx) {
+    private static double toInches(RAbstractVector units, int index, AxisOrDimension axisFrom, UnitConversionContext conversionCtx) {
         double inches;
         if (axisFrom.isHorizontal()) {
             if (axisFrom.isDimension()) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
index fd32959d477289aa971379d8cf54ced7a28f50a1..688375a82b87f8560babba74dfc6b6780a5d0013 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java
@@ -25,7 +25,7 @@ final class LInitViewPortStack extends RExternalBuiltinNode {
     }
 
     @Override
-    public Object call(VirtualFrame frame, @SuppressWarnings("unused") RArgsValuesAndNames args) {
+    public Object call(VirtualFrame frame, RArgsValuesAndNames args) {
         initViewPortNode.execute(frame);
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
index a61208b89e4a9aa11607216511b309a4e3df0366..d7ecfcac689f023f97bca41bd86f426545d0e5c3 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLines.java
@@ -52,7 +52,7 @@ public abstract class LLines extends RExternalBuiltinNode.Arg4 {
     }
 
     @Specialization
-    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, @SuppressWarnings("unused") RList arrow) {
+    Object doLines(RAbstractVector x, RAbstractVector y, RList lengths, RList arrow) {
         gridLinesNode.execute(x, y, lengths, arrow);
         return RNull.instance;
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
index 1b234eda3a3fc0e7ff305cf18785e6ec77813c36..27edec3641e8a9af72635d4db573cb0f2cc77b8f 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java
@@ -14,8 +14,11 @@ package com.oracle.truffle.r.library.fastrGrid;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.DeviceCloseException;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RNull;
 
@@ -40,8 +43,17 @@ final class LNewPage extends RExternalBuiltinNode {
     }
 
     @TruffleBoundary
-    private static void openNewPage(GridDevice device) {
-        device.openNewPage();
+    private void openNewPage(GridDevice device) {
+        if (device instanceof FileGridDevice) {
+            String path = GridContext.getContext().getGridState().getNextPageFilename();
+            try {
+                ((FileGridDevice) device).openNewPage(path);
+            } catch (DeviceCloseException e) {
+                throw error(Message.GENERIC, "Cannot save the image. Details: " + e.getMessage());
+            }
+        } else {
+            device.openNewPage();
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
index c8fa2b5c39fa1ff56e03508bc88aed71c8e018a5..a83a14c965abd5bcac251a40c413dd2a97285694 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java
@@ -22,21 +22,25 @@ import com.oracle.truffle.r.library.fastrGrid.device.GridColor;
 import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError.Message;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
-    private static final double SMALL = 0.25;
-    private static final double RADIUS = 0.375;
-    private static final double SQRC = 0.88622692545275801364; /* sqrt(pi / 4) */
-    private static final double DMDC = 1.25331413731550025119; /* sqrt(pi / 4) * sqrt(2) */
     private static final double TRC0 = 1.55512030155621416073; /* sqrt(4 * pi/(3 * sqrt(3))) */
     private static final double TRC1 = 1.34677368708859836060; /* TRC0 * sqrt(3) / 2 */
     private static final double TRC2 = 0.77756015077810708036; /* TRC0 / 2 */
 
+    // empiracally chosen to match GNU R look better
+    private static final double TRIANGLE_SIZE_FACTOR = 1.15;
+
+    // empirically chosen factor to visually approx match GNU R
+    private static final double SIZE_FACTOR = 0.375;
+
+    // we assume at leat 72 points per inch
+    private static final double PIXEL_SIZE = 1. / 72.;
+
     static {
         Casts casts = new Casts(LPoints.class);
         casts.arg(0).mustBe(abstractVectorValue());
@@ -65,120 +69,225 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
 
         // Note: unlike in other drawing primitives, we only consider length of x
         int length = Unit.getLength(xVec);
-        DrawingContext initialDrawingCtx = gpar.getDrawingContext(0);
-        PointDrawingContext pointDrawingCtx = new PointDrawingContext(initialDrawingCtx, initialDrawingCtx.getFillColor(), initialDrawingCtx.getFillColor());
+        ContextCache contextCache = new ContextCache(null);
         for (int i = 0; i < length; i++) {
             Point loc = TransformMatrix.transLocation(Point.fromUnits(xVec, yVec, i, conversionCtx), vpTransform.transform);
             double size = Unit.convertWidth(sizeVec, i, conversionCtx);
             if (loc.isFinite() && Double.isFinite(size)) {
-                pointDrawingCtx = pointDrawingCtx.update(gpar.getDrawingContext(i));
-                pointDrawingCtx = drawSymbol(pointDrawingCtx, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size, loc.x, loc.y);
+                contextCache = contextCache.from(gpar.getDrawingContext(i));
+                drawSymbol(contextCache, dev, cex, pchVec.getDataAt(i % pchVec.getLength()), size * SIZE_FACTOR, loc.x, loc.y);
             }
         }
         return RNull.instance;
     }
 
-    // transcribed from engine.c function GESymbol
-
-    private PointDrawingContext drawSymbol(PointDrawingContext drawingCtx, GridDevice dev, double cex, int pch, double size, double x, double y) {
+    private static void drawSymbol(ContextCache ctxCache, GridDevice dev, double cex, int pch, double halfSize, double x, double y) {
         // pch 0 - 25 are interpreted as geometrical shapes, pch from ascii code of ' ' are
         // interpreted as corresponding ascii character, which should be drawn
+        // the coordinates should be interpreted as the center of the symbol
+        double fullSize = halfSize * 2;
+        DrawingContext emptyFill = ctxCache.getTransparentFill();
         switch (pch) {
-            case 46:
-                return drawDot(drawingCtx, dev, cex, x, y);
+            case 0:
+                drawSquare(emptyFill, dev, halfSize, x, y);
+                break;
             case 1:
-                return drawOctahedron(drawingCtx, dev, GridColor.TRANSPARENT, size, x, y);
-            case 19: /* R filled circle */
-                return drawFilledCircle(drawingCtx, dev, RADIUS * size, x, y);
-            case 20: /* R `Dot' (small circle) */
-                return drawFilledCircle(drawingCtx, dev, SMALL * size, x, y);
-            case 21: /* circles */
-                return drawCircle(drawingCtx, dev, size, x, y);
-            case 22: /* squares */
-                return drawSquare(drawingCtx, dev, size, x, y);
-            case 16:
-                return drawOctahedron(drawingCtx, dev, drawingCtx.getWrapped().getColor(), size, x, y);
+                dev.drawCircle(emptyFill, x, y, halfSize);
+                break;
+            case 2: // triangle up
+                triangleUp(emptyFill, dev, halfSize * TRIANGLE_SIZE_FACTOR, x, y);
+                break;
+            case 3: /* S plus */
+                drawPlus(emptyFill, dev, halfSize, x, y);
+                break;
+            case 4: // S times
+                drawTimes(emptyFill, dev, halfSize, x, y);
+                break;
+            case 5: // S diamond
+                drawDiamond(emptyFill, dev, halfSize, fullSize, x, y);
+                break;
+            case 6: // S triangle point down
+                triangleDown(emptyFill, dev, halfSize * TRIANGLE_SIZE_FACTOR, x, y);
+                break;
+            case 7: // S square and times superimposed
+                drawSquare(emptyFill, dev, halfSize, x, y);
+                drawTimes(emptyFill, dev, halfSize, x, y);
+                break;
+            case 8: // S times and plus superimposed
+                drawPlus(emptyFill, dev, halfSize, x, y);
+                drawTimes(emptyFill, dev, halfSize, x, y);
+                break;
+            case 9: // S diamond and plus superimposed
+                drawPlus(emptyFill, dev, halfSize, x, y);
+                drawDiamond(emptyFill, dev, halfSize, fullSize, x, y);
+                break;
+            case 10: // S circle and plus
+                dev.drawCircle(emptyFill, x, y, halfSize);
+                drawPlus(emptyFill, dev, halfSize, x, y);
+                break;
+            case 11: // S superimposed triangles
+                triangleUp(emptyFill, dev, halfSize * TRIANGLE_SIZE_FACTOR, x, y);
+                triangleDown(emptyFill, dev, halfSize * TRIANGLE_SIZE_FACTOR, x, y);
+                break;
+            case 12: // S square and plus superimposed
+                drawSquare(emptyFill, dev, halfSize, x, y);
+                drawPlus(emptyFill, dev, halfSize, x, y);
+                break;
+            case 13: // S circle and times
+                dev.drawCircle(emptyFill, x, y, halfSize);
+                drawTimes(ctxCache.original, dev, halfSize, x, y);
+                break;
+            case 14: // S rectangle with triangle up
+                dev.drawRect(emptyFill, x - halfSize, y - halfSize, fullSize, fullSize, 0);
+                drawConnected(ctxCache.getTransparentFill(), dev, x - halfSize, y - halfSize, x + halfSize, y - halfSize, x, y + halfSize);
+                break;
+            case 15: // S filled square
+            case 22: // S filled (with different color) square
+                dev.drawRect(ctxCache.getFilled(), x - halfSize, y - halfSize, fullSize, fullSize, 0);
+                break;
+            case 16: // S filled circle (should be 'octagon')
+            case 19: // S filled circle
+            case 21: // S filled (with different color) circle
+                dev.drawCircle(ctxCache.getFilled(), x, y, halfSize);
+                break;
+            case 17: // S filled triangle up
+            case 24: // S filled (with different color) triangle up
+                triangleUp(ctxCache.getFilled(), dev, halfSize * TRIANGLE_SIZE_FACTOR, x, y);
+                break;
+            case 18: // S filled diamond
+            case 23: // S filled (with different color) diamond
+                drawDiamond(ctxCache.getFilled(), dev, halfSize, fullSize, x, y);
+                break;
+            case 20: // S smaller filled circle
+                dev.drawCircle(ctxCache.getFilled(), x, y, halfSize * .6);
+                break;
+            case 25: // S triangle down filled
+                triangleDown(ctxCache.getFilled(), dev, halfSize * TRIANGLE_SIZE_FACTOR, x, y);
+                break;
+            case 46: // small dot
+                // we assume at leat 72 points per inch
+                dev.drawRect(ctxCache.getFilled(), x - PIXEL_SIZE / 2, y - PIXEL_SIZE / 2, PIXEL_SIZE, PIXEL_SIZE, 0);
+                break;
             default:
-                throw RInternalError.unimplemented("grid.points unimplemented symbol " + pch);
+                drawTextSymbol(ctxCache, dev, x, y, new String(new char[]{(char) pch}));
         }
     }
 
-    private PointDrawingContext drawFilledCircle(PointDrawingContext drawingCtxIn, GridDevice dev, double radius, double x, double y) {
-        PointDrawingContext drawingCtx = drawingCtxIn.update(drawingCtxIn.getWrapped().getColor(), drawingCtxIn.getWrapped().getColor());
-        dev.drawCircle(drawingCtx, x, y, radius);
-        return drawingCtx;
+    private static void drawDiamond(DrawingContext ctx, GridDevice dev, double halfSize, double fullSize, double x, double y) {
+        dev.drawRect(ctx, x - halfSize, y - halfSize, fullSize, fullSize, 1.75 * Math.PI);
+    }
+
+    private static void drawSquare(DrawingContext ctx, GridDevice dev, double halfSize, double x, double y) {
+        double fullSize = halfSize * 2.;
+        dev.drawRect(ctx, x - halfSize, y - halfSize, fullSize, fullSize, 0);
+    }
+
+    private static void drawTimes(DrawingContext ctx, GridDevice dev, double halfSize, double x, double y) {
+        drawLine(ctx, dev, x - halfSize, y + halfSize, x + halfSize, y - halfSize);
+        drawLine(ctx, dev, x + halfSize, y + halfSize, x - halfSize, y - halfSize);
+    }
+
+    private static void drawPlus(DrawingContext ctx, GridDevice dev, double halfSize, double x, double y) {
+        drawLine(ctx, dev, x - halfSize, y, x + halfSize, y);
+        drawLine(ctx, dev, x, y + halfSize, x, y - halfSize);
     }
 
-    private PointDrawingContext drawCircle(PointDrawingContext drawingCtx, GridDevice dev, double size, double x, double y) {
-        double xc = RADIUS * size;
-        dev.drawCircle(drawingCtx, x, y, xc);
-        return drawingCtx;
+    private static void triangleDown(DrawingContext ctx, GridDevice dev, double halfSize, double x, double y) {
+        double yc = halfSize * TRC2;
+        double xc = halfSize * TRC1;
+        drawConnected(ctx, dev, x, y - halfSize * TRC0, x - xc, y + yc, x + xc, y + yc);
     }
 
-    private PointDrawingContext drawSquare(PointDrawingContext drawingCtx, GridDevice dev, double size, double x, double y) {
-        double xc = RADIUS * SQRC * size;
-        double yc = RADIUS * SQRC * size;
-        dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc, 0);
-        return drawingCtx;
+    private static void triangleUp(DrawingContext ctx, GridDevice dev, double halfSize, double x, double y) {
+        double yc = halfSize * TRC2;
+        double xc = halfSize * TRC1;
+        drawConnected(ctx, dev, x, y + halfSize * TRC0, x - xc, y - yc, x + xc, y - yc);
     }
 
-    private static PointDrawingContext drawOctahedron(PointDrawingContext drawingCtxIn, GridDevice dev, GridColor fill, double size, double x, double y) {
-        PointDrawingContext drawingCtx = drawingCtxIn.update(drawingCtxIn.getWrapped().getColor(), fill);
-        dev.drawCircle(drawingCtx, x, y, RADIUS * size);
-        return drawingCtx;
+    private static void drawTextSymbol(ContextCache ctxCache, GridDevice dev, double x, double y, String symbols) {
+        double height = dev.getStringHeight(ctxCache.getSymbol(), symbols);
+        double width = dev.getStringWidth(ctxCache.getSymbol(), symbols);
+        dev.drawString(ctxCache.getSymbol(), x - width / 2, y - height / 2, 0, symbols);
     }
 
-    private static PointDrawingContext drawDot(PointDrawingContext drawingCtxIn, GridDevice dev, double cex, double x, double y) {
-        // NOTE: we are *filling* a rect with the current colour (we are not drawing the border AND
-        // we are not using the current fill colour)
-        PointDrawingContext drawingCtx = drawingCtxIn.update(GridColor.TRANSPARENT, drawingCtxIn.getWrapped().getColor());
-        /*
-         * The idea here is to use a 0.01" square, but to be of at least one device unit in each
-         * direction, assuming that corresponds to pixels. That may be odd if pixels are not square,
-         * but only on low resolution devices where we can do nothing better.
-         *
-         * For this symbol only, size is cex (see engine.c).
-         *
-         * Prior to 2.1.0 the offsets were always 0.5.
+    /**
+     * Simpler to use by hand version of drawPolyline. Points are expected to be in format [x1, y1,
+     * x2, y2, ...].
+     */
+    private static void drawConnected(DrawingContext ctx, GridDevice dev, double... points) {
+        assert points.length % 2 == 0 && points.length > 0;
+        double[] x = new double[(points.length / 2) + 1];
+        double[] y = new double[(points.length / 2) + 1];
+        x[x.length - 1] = points[0];
+        y[y.length - 1] = points[1];
+        for (int i = 0; i < x.length - 1; i++) {
+            x[i] = points[i * 2];
+            y[i] = points[(i * 2) + 1];
+        }
+        dev.drawPolygon(ctx, x, y, 0, y.length);
+    }
+
+    private static void drawLine(DrawingContext ctx, GridDevice dev, double x1, double y1, double x2, double y2) {
+        dev.drawPolyLines(ctx, new double[]{x1, x2}, new double[]{y1, y2}, 0, 2);
+    }
+
+    private static final class ContextCache {
+        public final DrawingContext original;
+        private DrawingContext filled;
+        private DrawingContext transprentFill;
+        private DrawingContext symbol;
+
+        private ContextCache(DrawingContext original) {
+            this.original = original;
+        }
+
+        ContextCache from(DrawingContext newOriginal) {
+            if (original == newOriginal) {
+                return this;
+            }
+            return new ContextCache(newOriginal);
+        }
+
+        /**
+         * Context with fill color set to the normal color of the original context.
          */
-        double xc = cex * 0.005;
-        double yc = cex * 0.005;
-        if (cex > 0 && xc < 0.5) {
-            xc = 0.5;
+        DrawingContext getFilled() {
+            if (filled == null) {
+                filled = new PointDrawingContext(original, original.getColor(), original.getColor(), 1);
+            }
+            return filled;
         }
-        if (cex > 0 && yc < 0.5) {
-            yc = 0.5;
+
+        DrawingContext getTransparentFill() {
+            if (transprentFill == null) {
+                transprentFill = new PointDrawingContext(original, original.getColor(), GridColor.TRANSPARENT, 1);
+            }
+            return transprentFill;
+        }
+
+        DrawingContext getSymbol() {
+            if (symbol == null) {
+                symbol = new PointDrawingContext(original, original.getColor(), original.getFillColor(), 1.4);
+            }
+            return symbol;
         }
-        dev.drawRect(drawingCtx, x - xc, y - yc, x + xc, y + yc, 0);
-        return drawingCtx;
     }
 
+    /**
+     * Context that has the same parameters as the given context except for the color and fill color
+     * and multiplication factor for font size, which are given explicitly.
+     */
     private static final class PointDrawingContext implements DrawingContext {
         private final DrawingContext inner;
         private final GridColor color;
         private final GridColor fillColor;
+        private final double fontsizeFactor;
 
-        private PointDrawingContext(DrawingContext inner, GridColor color, GridColor fillColor) {
+        private PointDrawingContext(DrawingContext inner, GridColor color, GridColor fillColor, double fontsizeFactor) {
             this.inner = inner;
             this.color = color;
             this.fillColor = fillColor;
-        }
-
-        // This allows to re-use the existing instance if it would have the same parameters. The
-        // assumption is that the users will actually draw many points in a row with the same
-        // parameters.
-        private PointDrawingContext update(GridColor color, GridColor fillColor) {
-            if (this.color.equals(color) && this.fillColor.equals(fillColor)) {
-                return this;
-            }
-            return new PointDrawingContext(inner, color, fillColor);
-        }
-
-        private PointDrawingContext update(DrawingContext inner) {
-            if (this.inner == inner) {
-                return this;
-            }
-            return new PointDrawingContext(inner, this.color, this.fillColor);
+            this.fontsizeFactor = fontsizeFactor;
         }
 
         @Override
@@ -213,7 +322,7 @@ public abstract class LPoints extends RExternalBuiltinNode.Arg4 {
 
         @Override
         public double getFontSize() {
-            return inner.getFontSize();
+            return inner.getFontSize() * fontsizeFactor;
         }
 
         @Override
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRaster.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRaster.java
new file mode 100644
index 0000000000000000000000000000000000000000..2b9c075642ab3c89aefe158d5deeea4e92fa5d4c
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRaster.java
@@ -0,0 +1,130 @@
+/*
+ * 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) 2001-3 Paul Murrell
+ * Copyright (c) 1998-2013, The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.library.fastrGrid;
+
+import static com.oracle.truffle.r.library.fastrGrid.GridUtils.getDataAtMod;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.library.fastrGrid.Unit.UnitConversionContext;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice.ImageInterpolation;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+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.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+/**
+ * Draws a raster image at specified position. The image may be matrix of integers, in which case it
+ * is used directly, or matrix of any valid color representation, e.g. strings with color codes.
+ */
+public abstract class LRaster extends RExternalBuiltinNode.Arg8 {
+    private static final String NATIVE_RASTER_CLASS = "nativeRaster";
+
+    static {
+        Casts casts = new Casts(LRaster.class);
+        casts.arg(0).mustBe(abstractVectorValue());
+        casts.arg(1).mustBe(abstractVectorValue());
+        casts.arg(2).mustBe(abstractVectorValue());
+        casts.arg(3).mustBe(abstractVectorValue());
+        casts.arg(4).mustBe(abstractVectorValue());
+        casts.arg(5).mustBe(numericValue()).asDoubleVector();
+        casts.arg(6).mustBe(numericValue()).asDoubleVector();
+        casts.arg(7).mustBe(logicalValue()).asLogicalVector();
+    }
+
+    public static LRaster create() {
+        return LRasterNodeGen.create();
+    }
+
+    @Specialization
+    @TruffleBoundary
+    Object doRaster(RAbstractVector raster, RAbstractVector xVec, RAbstractVector yVec, RAbstractVector widthVec, RAbstractVector heightVec, RAbstractDoubleVector hjust, RAbstractDoubleVector vjust,
+                    RAbstractLogicalVector interpolate) {
+        GridContext ctx = GridContext.getContext();
+        GridDevice dev = ctx.getCurrentDevice();
+
+        RList currentVP = ctx.getGridState().getViewPort();
+        GPar gpar = GPar.create(ctx.getGridState().getGpar());
+        ViewPortTransform vpTransform = ViewPortTransform.get(currentVP, dev);
+        ViewPortContext vpContext = ViewPortContext.fromViewPort(currentVP);
+        UnitConversionContext conversionCtx = new UnitConversionContext(vpTransform.size, vpContext, dev, gpar);
+
+        if (vpTransform.rotationAngle != 0) {
+            throw RInternalError.unimplemented("L_raster with view-port rotation.");
+        }
+
+        int[] pixels;
+        if (raster instanceof RAbstractIntVector && isNativeRaster(raster)) {
+            pixels = ((RAbstractIntVector) raster).materialize().getDataWithoutCopying();
+        } else {
+            int rasterLen = raster.getLength();
+            pixels = new int[rasterLen];
+            for (int i = 0; i < rasterLen; i++) {
+                pixels[i] = GridColorUtils.getColor(raster, i).getRawValue();
+            }
+        }
+
+        Object dimsObj = raster.getAttr(RRuntime.DIM_ATTR_KEY);
+        if (!(dimsObj instanceof RAbstractIntVector)) {
+            throw RInternalError.shouldNotReachHere("Dims attribute should always be integer vector.");
+        }
+        RAbstractIntVector dims = (RAbstractIntVector) dimsObj;
+        if (dims.getLength() != 2) {
+            throw error(Message.GENERIC, "L_raster dims attribute is not of size 2");
+        }
+
+        int length = GridUtils.maxLength(xVec, yVec, widthVec, heightVec);
+        for (int i = 0; i < length; i++) {
+            Size size = Size.fromUnits(widthVec, heightVec, i, conversionCtx);
+            Point origLoc = Point.fromUnits(xVec, yVec, i, conversionCtx);
+            Point transLoc = TransformMatrix.transLocation(origLoc, vpTransform.transform);
+            Point loc = transLoc.justify(size, getDataAtMod(hjust, i), getDataAtMod(vjust, i));
+            if (!loc.isFinite() || !size.isFinite()) {
+                continue;
+            }
+            ImageInterpolation interpolation = getInterpolation(interpolate, i);
+            dev.drawRaster(loc.x, loc.y, size.getWidth(), size.getHeight(), pixels, dims.getDataAt(1), interpolation);
+        }
+        return RNull.instance;
+    }
+
+    private static ImageInterpolation getInterpolation(RAbstractLogicalVector interpolation, int idx) {
+        if (RRuntime.fromLogical(interpolation.getDataAt(idx % interpolation.getLength()))) {
+            return ImageInterpolation.LINEAR_INTERPOLATION;
+        }
+        return ImageInterpolation.NEAREST_NEIGHBOR;
+    }
+
+    private static boolean isNativeRaster(RAbstractVector vec) {
+        RStringVector clazz = vec.getClassAttr();
+        if (clazz == null) {
+            return false;
+        }
+        for (int i = 0; i < clazz.getLength(); i++) {
+            if (clazz.getDataAt(i).equals(NATIVE_RASTER_CLASS)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
index f8fb9b0e6da3f6c0989ea781ed35fca95360d790..5ff2d5c8a54518cfc4ed3b061bb01c86bd4f6c34 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java
@@ -78,7 +78,7 @@ public abstract class LUnsetViewPort extends RExternalBuiltinNode.Arg1 {
         return RNull.instance;
     }
 
-    private void safeRemoveFromEnv(REnvironment children, String gvpName) {
+    private static void safeRemoveFromEnv(REnvironment children, String gvpName) {
         try {
             children.rm(gvpName);
         } catch (PutException e) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/FileGridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/FileGridDevice.java
new file mode 100644
index 0000000000000000000000000000000000000000..753f4d5bfccc7d75c9e064bb0934666ba12f2af1
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/FileGridDevice.java
@@ -0,0 +1,41 @@
+/*
+ * 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.device;
+
+/**
+ * Should be implemented by devices that save their output into a file. Such devices should only
+ * accept complete filenames, i.e. without '%d' placeholder, and the handling of the placeholder is
+ * left up to the calling code.
+ */
+public interface FileGridDevice extends GridDevice {
+    /**
+     * Each call to {@link #openNewPage()} should save the current image (into the current path) and
+     * start drawing a new image into the given path, i.e. the given path becomes a new current
+     * path.
+     * 
+     * @param filename tha path where to save the next image, will not contain '%d' symbol as its
+     *            processing should be handled by the caller.
+     * @throws DeviceCloseException
+     */
+    void openNewPage(String filename) throws DeviceCloseException;
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
index 0515ded9b5bf94c49d13a8092c7063d0fbaee6bf..87ed10b88a6d2d714f9d08448f05f3b08b49c558 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/GridDevice.java
@@ -30,6 +30,20 @@ public interface GridDevice {
     int DEFAULT_WIDTH = 720;
     int DEFAULT_HEIGHT = 720;
 
+    /**
+     * Raster image resizing methods.
+     */
+    enum ImageInterpolation {
+        /**
+         * The device should use linear interpolation if available.
+         */
+        LINEAR_INTERPOLATION,
+        /**
+         * The device should use the nearest neighbor interpolation if available.
+         */
+        NEAREST_NEIGHBOR,
+    }
+
     void openNewPage();
 
     /**
@@ -80,6 +94,13 @@ public interface GridDevice {
 
     void drawCircle(DrawingContext ctx, double centerX, double centerY, double radius);
 
+    /**
+     * Draws a raster image at specified position. The pixels array shall be treated as by row
+     * matrix, the values are values compatible with the internal {@link GridColor} representation,
+     * e.g. what {@link GridColor#getRawValue()} would return.
+     */
+    void drawRaster(double leftX, double bottomY, double width, double height, int[] pixels, int pixelsColumnsCount, ImageInterpolation interpolation);
+
     /**
      * Prints a string with left bottom corner at given position rotated by given angle anti clock
      * wise, the centre of the rotation should be the bottom left corer.
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
index baad5ebe4167fd56f54527f64d3d811909de6fff..17f1667bcdae8776d5e7b9656b01aef8ce7aa277 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/SVGDevice.java
@@ -30,6 +30,7 @@ import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.text.DecimalFormat;
+import java.util.Base64;
 import java.util.Collections;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle;
@@ -38,10 +39,10 @@ import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridLineJoin
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 
-public class SVGDevice implements GridDevice {
+public class SVGDevice implements GridDevice, FileGridDevice {
     private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.000");
     private final StringBuilder data = new StringBuilder(1024);
-    private final String filename;
+    private String filename;
     private final double width;
     private final double height;
 
@@ -72,22 +73,24 @@ public class SVGDevice implements GridDevice {
                         height);
     }
 
+    @Override
+    public void openNewPage(String newFilename) throws DeviceCloseException {
+        saveFile();
+        filename = newFilename;
+        openNewPage();
+    }
+
     @Override
     public void close() throws DeviceCloseException {
-        closeSVGDocument();
-        try {
-            Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8);
-        } catch (IOException e) {
-            throw new DeviceCloseException(e);
-        }
+        saveFile();
     }
 
     @Override
-    public void drawRect(DrawingContext ctx, double leftX, double bottomY, double width, double height, double rotationAnticlockWise) {
+    public void drawRect(DrawingContext ctx, double leftX, double bottomY, double newWidth, double newHeight, double rotationAnticlockWise) {
         appendStyle(ctx);
-        append("<rect vector-effect='non-scaling-stroke' x='%.3f' y='%.3f' width='%.3f' height='%.3f'", leftX, transY(bottomY + height), width, height);
+        append("<rect vector-effect='non-scaling-stroke' x='%.3f' y='%.3f' width='%.3f' height='%.3f'", leftX, transY(bottomY + newHeight), newWidth, newHeight);
         if (rotationAnticlockWise != 0) {
-            append("transform='rotate(%.3f %.3f,%.3f)'", toDegrees(rotationAnticlockWise), (leftX + width / 2.), transY(bottomY + height / 2.));
+            append("transform='rotate(%.3f %.3f,%.3f)'", toDegrees(rotationAnticlockWise), (leftX + newWidth / 2.), transY(bottomY + newHeight / 2.));
         }
         data.append("/>"); // end of 'rect' tag
     }
@@ -108,6 +111,13 @@ public class SVGDevice implements GridDevice {
         append("<circle vector-effect='non-scaling-stroke' cx='%.3f' cy='%.3f' r='%.3f'/>", centerX, transY(centerY), radius);
     }
 
+    @Override
+    public void drawRaster(double leftX, double bottomY, double width, double height, int[] pixels, int pixelsColumnsCount, ImageInterpolation interpolation) {
+        byte[] bitmap = Bitmap.create(pixels, pixelsColumnsCount);
+        String base64 = Base64.getEncoder().encodeToString(bitmap);
+        append("<image x='%.3f' y='%.3f' width='%.3f' height='%.3f' preserveAspectRatio='none' xlink:href='data:image/bmp;base64,%s'/>", leftX, transY(bottomY + height), width, height, base64);
+    }
+
     @Override
     public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
         appendStyle(ctx);
@@ -142,7 +152,7 @@ public class SVGDevice implements GridDevice {
             factor = 0.62;
         }
         double letterWidth = (ctx.getFontSize() / INCH_TO_POINTS_FACTOR);
-        double result = factor * (double) text.length() * letterWidth;
+        double result = text.length() * factor * letterWidth;
         for (int i = 0; i < text.length(); i++) {
             char c = text.charAt(i);
             if (c == 'w' || c == 'm') {
@@ -173,7 +183,19 @@ public class SVGDevice implements GridDevice {
         data.append("' ").append(attributes).append(" />");
     }
 
+    private void saveFile() throws DeviceCloseException {
+        closeSVGDocument();
+        try {
+            Files.write(Paths.get(filename), Collections.singleton(data.toString()), StandardCharsets.UTF_8);
+        } catch (IOException e) {
+            throw new DeviceCloseException(e);
+        }
+    }
+
     private void closeSVGDocument() {
+        if (data.length() == 0) {
+            return;
+        }
         if (cachedCtx != null) {
             // see #appendStyle
             append("</g>");
@@ -270,4 +292,60 @@ public class SVGDevice implements GridDevice {
     private static double toDegrees(double rotationAnticlockWise) {
         return (180. / Math.PI) * -rotationAnticlockWise;
     }
+
+    private static final class Bitmap {
+        private static final int FILE_HEADER_SIZE = 14;
+        private static final int IMAGE_HEADER_SIZE = 40;
+        private static final int BITS_PER_PIXEL = 24;
+        private static final int COMPRESSION_TYPE = 0;
+
+        static byte[] create(int[] pixels, int width) {
+            int height = pixels.length / width;
+            int widthInBytes = width * 3;
+            int widthPadding = widthInBytes % 2;
+            widthInBytes += widthPadding;
+
+            int len = FILE_HEADER_SIZE + IMAGE_HEADER_SIZE + height * widthInBytes;
+            byte[] result = new byte[len];
+
+            // file header
+            result[0] = 0x42; // B
+            result[1] = 0x4d; // M
+            int offset = putInt(result, 2, len);
+            offset += 4;    // unused 4B must be zero
+            offset = putInt(result, offset, FILE_HEADER_SIZE + IMAGE_HEADER_SIZE);  // data offset
+
+            // image header
+            offset = putInt(result, offset, IMAGE_HEADER_SIZE);
+            offset = putInt(result, offset, width);
+            offset = putInt(result, offset, height);
+            result[offset++] = 1;   // fixed value
+            result[offset++] = 0;   // fixed value
+            result[offset++] = BITS_PER_PIXEL;
+            result[offset++] = 0;   // bits per pixel is 2B value
+            offset = putInt(result, offset, COMPRESSION_TYPE);
+            // followed by 5 unimportant values (each 4B) that we leave 0
+            offset += 4 * 5;
+
+            // image data
+            for (int row = height - 1; row >= 0; row--) {
+                for (int col = 0; col < width; col++) {
+                    GridColor color = GridColor.fromRawValue(pixels[row * width + col]);
+                    result[offset++] = (byte) (color.getBlue() & 0xff);
+                    result[offset++] = (byte) (color.getGreen() & 0xff);
+                    result[offset++] = (byte) (color.getRed() & 0xff);
+                }
+                offset += widthPadding;
+            }
+            return result;
+        }
+
+        private static int putInt(byte[] data, int offset, int value) {
+            data[offset] = (byte) (value & 0xff);
+            data[offset + 1] = (byte) (value >>> 8 & 0xff);
+            data[offset + 2] = (byte) (value >>> 16 & 0xff);
+            data[offset + 3] = (byte) (value >>> 24 & 0xff);
+            return offset + 4;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
index 577784461859f69a3c600497f361c1f5b141dd17..1f95c9cfd18a2c5a0865f09be84016bacbfdf1aa 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedImageDevice.java
@@ -32,10 +32,12 @@ import java.io.IOException;
 
 import javax.imageio.ImageIO;
 
-public final class BufferedImageDevice extends Graphics2DDevice {
+import com.oracle.truffle.r.library.fastrGrid.device.FileGridDevice;
+
+public final class BufferedImageDevice extends Graphics2DDevice implements FileGridDevice {
     private final BufferedImage image;
-    private final String filename;
     private final String fileType;
+    private String filename;
 
     private BufferedImageDevice(String filename, String fileType, BufferedImage image, Graphics2D graphics, int width, int height) {
         super(graphics, width, height, true);
@@ -56,8 +58,19 @@ public final class BufferedImageDevice extends Graphics2DDevice {
         return new BufferedImageDevice(filename, fileType, image, graphics, width, height);
     }
 
+    @Override
+    public void openNewPage(String newFilename) throws DeviceCloseException {
+        saveImage();
+        filename = newFilename;
+        openNewPage();
+    }
+
     @Override
     public void close() throws DeviceCloseException {
+        saveImage();
+    }
+
+    private void saveImage() throws DeviceCloseException {
         try {
             ImageIO.write(image, fileType, new File(filename));
         } catch (IOException e) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
index 607b0ad8b033aca74cbdcc07b9d807e45b5cee5a..427ec6310465d06f0675b097342113bd52257147 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/BufferedJFrameDevice.java
@@ -59,19 +59,13 @@ public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
 
     public BufferedJFrameDevice(JFrameDevice inner) {
         this.inner = inner;
+        this.inner.setCloseListener(this::clearActions);
     }
 
     @Override
     public void openNewPage() {
         inner.openNewPage();
-        drawActions.clear();
-        if (buffer != null) {
-            // if new page is opened while we are on hold, we should throw away current buffer. In
-            // other words that is like starting new hold without previous flush.
-            buffer.dispose();
-            buffer = null;
-            hold();
-        }
+        clearActions();
     }
 
     @Override
@@ -146,6 +140,12 @@ public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
         drawActions.add(() -> inner.drawCircle(ctx, centerX, centerY, radius));
     }
 
+    @Override
+    public void drawRaster(double leftX, double bottomY, double width, double height, int[] pixels, int pixelsColumnsCount, ImageInterpolation interpolation) {
+        inner.drawRaster(leftX, bottomY, width, height, pixels, pixelsColumnsCount, interpolation);
+        drawActions.add(() -> inner.drawRaster(leftX, bottomY, width, height, pixels, pixelsColumnsCount, interpolation));
+    }
+
     @Override
     public void drawString(DrawingContext ctx, double leftX, double bottomY, double rotationAnticlockWise, String text) {
         inner.drawString(ctx, leftX, bottomY, rotationAnticlockWise, text);
@@ -188,6 +188,17 @@ public final class BufferedJFrameDevice implements GridDevice, ImageSaver {
         setGraphics(inner.getCurrentFrame().getGraphics());
     }
 
+    private void clearActions() {
+        drawActions.clear();
+        if (buffer != null) {
+            // if new page is opened while we are on hold, we should throw away current buffer. In
+            // other words that is like starting new hold without previous flush.
+            buffer.dispose();
+            buffer = null;
+            hold();
+        }
+    }
+
     private void setGraphics(Graphics graphics) {
         Graphics2DDevice.defaultInitGraphics((Graphics2D) graphics);
         inner.getGraphics2D().dispose();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
index 90bf1adc20281dd8002220b8599c20c35214d8ea..b9834220b64f3f7ccacf8ebf69a617ba4c1f3243 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/Graphics2DDevice.java
@@ -30,13 +30,17 @@ import java.awt.Color;
 import java.awt.Font;
 import java.awt.FontMetrics;
 import java.awt.Graphics2D;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
 import java.awt.Paint;
 import java.awt.RenderingHints;
 import java.awt.Shape;
+import java.awt.Toolkit;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Path2D;
 import java.awt.geom.Rectangle2D;
+import java.awt.image.MemoryImageSource;
 
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext;
 import com.oracle.truffle.r.library.fastrGrid.device.DrawingContext.GridFontStyle;
@@ -59,7 +63,7 @@ public class Graphics2DDevice implements GridDevice {
     // may wish to apply his/her own transformations to the graphics object and we should not
     // interfere with these. In cases we do use transformation, we make sure to set back the
     // original one after we're done.
-    static final double AWT_POINTS_IN_INCH = 72.;
+    static final double AWT_POINTS_IN_INCH = GraphicsEnvironment.isHeadless() ? 72. : Toolkit.getDefaultToolkit().getScreenResolution();
 
     private static BasicStroke blankStroke;
 
@@ -87,29 +91,38 @@ public class Graphics2DDevice implements GridDevice {
     static void defaultInitGraphics(Graphics2D graphics) {
         graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
         graphics.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
+        graphics.setBackground(Color.WHITE);
     }
 
     @Override
     public void openNewPage() {
+        ensureOpen();
         graphics.clearRect(0, 0, getWidthAwt(), getHeightAwt());
+        cachedContext = null;
     }
 
     @Override
     public void drawRect(DrawingContext ctx, double leftXIn, double bottomYIn, double widthIn, double heightIn, double rotationAnticlockWise) {
-        int leftX = transX(leftXIn);
-        int topY = transY(bottomYIn + heightIn);
-        int width = transDim(widthIn);
-        int height = transDim(heightIn);
+        ensureOpen();
+        double leftXReal = transX(leftXIn);
+        double topYReal = transY(bottomYIn + heightIn);
+        int rectWidth = transDim(widthIn, leftXReal);
+        int rectHeight = transDim(heightIn, topYReal);
+        int leftX = iround(leftXReal);
+        int topY = iround(topYReal);
         setContext(ctx);
         if (rotationAnticlockWise == 0.) {
-            drawShape(ctx, new Rectangle2D.Double(leftX, topY, width, height));
-            return;
+            drawShape(ctx, new Rectangle2D.Double(leftX, topY, rectWidth, rectHeight));
+        } else {
+            int halfWidth = iround(rectWidth / 2.);
+            int halfHeight = iround(rectHeight / 2.);
+            transformed(iround(leftX + halfWidth), iround(topY + halfHeight), rotationAnticlockWise, () -> drawShape(ctx, new Rectangle2D.Double(-halfWidth, -halfHeight, rectWidth, rectHeight)));
         }
-        transformed(leftX + width / 2, topY + height / 2, rotationAnticlockWise, () -> drawShape(ctx, new Rectangle2D.Double(-(width / 2), -(height / 2), width, height)));
     }
 
     @Override
     public void drawPolyLines(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+        ensureOpen();
         Path2D.Double path = getPath2D(x, y, startIndex, length);
         setContext(ctx);
         graphics.draw(path);
@@ -117,6 +130,7 @@ public class Graphics2DDevice implements GridDevice {
 
     @Override
     public void drawPolygon(DrawingContext ctx, double[] x, double[] y, int startIndex, int length) {
+        ensureOpen();
         Path2D.Double path = getPath2D(x, y, startIndex, length);
         setContext(ctx);
         drawShape(ctx, path);
@@ -124,19 +138,31 @@ public class Graphics2DDevice implements GridDevice {
 
     @Override
     public void drawCircle(DrawingContext ctx, double centerXIn, double centerYIn, double radiusIn) {
+        ensureOpen();
         setContext(ctx);
-        int centerX = transX(centerXIn);
-        int centerY = transY(centerYIn);
-        int radius = transDim(radiusIn);
-        drawShape(ctx, new Ellipse2D.Double(centerX - radius, centerY - radius, radius * 2d, radius * 2d));
+        double xRel = transX(centerXIn - radiusIn);
+        double yRel = transY(centerYIn + radiusIn);
+        int diameter = transDim(radiusIn * 2d, Math.max(xRel % 1, yRel % 1));
+        drawShape(ctx, new Ellipse2D.Double(iround(xRel), iround(yRel), diameter, diameter));
+    }
+
+    @Override
+    public void drawRaster(double leftX, double bottomY, double width, double height, int[] pixels, int pixelsColumnsCount, ImageInterpolation interpolation) {
+        ensureOpen();
+        graphics.setRenderingHint(RenderingHints.KEY_INTERPOLATION, fromInterpolation(interpolation));
+        Image image = Toolkit.getDefaultToolkit().createImage(new MemoryImageSource(pixelsColumnsCount, pixels.length / pixelsColumnsCount, pixels, 0, pixelsColumnsCount));
+        double yRel = transY(bottomY + height);
+        double xRel = transX(leftX);
+        graphics.drawImage(image, iround(xRel), iround(yRel), transDim(width, xRel), transDim(height, yRel), null);
     }
 
     @Override
     public void drawString(DrawingContext ctx, double leftXIn, double bottomYIn, double rotationAnticlockWise, String text) {
+        ensureOpen();
         setContextAndFont(ctx);
-        int leftX = transX(leftXIn);
+        int leftX = iround(transX(leftXIn));
         FontMetrics fontMetrics = graphics.getFontMetrics(graphics.getFont());
-        int bottomY = transY(bottomYIn) - fontMetrics.getDescent();
+        int bottomY = iround(transY(bottomYIn)) - fontMetrics.getDescent();
         transformed(leftX, bottomY, rotationAnticlockWise, () -> graphics.drawString(text, 0, 0));
     }
 
@@ -179,25 +205,35 @@ public class Graphics2DDevice implements GridDevice {
         return height;
     }
 
+    /**
+     * If the device can be closed by an action outside of the R interpreter (not e.g. dev.close()),
+     * then the device should be able to re-open itself if any drawing happens after it was closed
+     * in such way.
+     */
+    void ensureOpen() {
+        // nop
+    }
+
     void setGraphics2D(Graphics2D newGraphics) {
         assert newGraphics != null;
         graphics = newGraphics;
+        cachedContext = null;
     }
 
     public Graphics2D getGraphics2D() {
         return graphics;
     }
 
-    private int transY(double y) {
-        return getHeightAwt() - (int) (y * AWT_POINTS_IN_INCH);
+    private double transY(double y) {
+        return getHeightAwt() - y * AWT_POINTS_IN_INCH;
     }
 
-    private static int transX(double x) {
-        return (int) (x * AWT_POINTS_IN_INCH);
+    private static double transX(double x) {
+        return x * AWT_POINTS_IN_INCH;
     }
 
-    private static int transDim(double widthOrHeight) {
-        return (int) (widthOrHeight * AWT_POINTS_IN_INCH);
+    private static int transDim(double widthOrHeight, double transformedAxis) {
+        return (int) Math.round(widthOrHeight * AWT_POINTS_IN_INCH + transformedAxis % 1);
     }
 
     private static void initStrokes() {
@@ -257,7 +293,7 @@ public class Graphics2DDevice implements GridDevice {
 
     // Transformation of DrawingContext data types to AWT constants
 
-    private String getFontName(String gridFontFamily) {
+    private static String getFontName(String gridFontFamily) {
         if (gridFontFamily == null) {
             return null;
         }
@@ -274,7 +310,7 @@ public class Graphics2DDevice implements GridDevice {
         return gridFontFamily;
     }
 
-    private int getAwtFontStyle(GridFontStyle fontStyle) {
+    private static int getAwtFontStyle(GridFontStyle fontStyle) {
         switch (fontStyle) {
             case PLAIN:
                 return Font.PLAIN;
@@ -293,7 +329,7 @@ public class Graphics2DDevice implements GridDevice {
         return new Color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha());
     }
 
-    private BasicStroke getStrokeFromCtx(DrawingContext ctx) {
+    private static BasicStroke getStrokeFromCtx(DrawingContext ctx) {
         byte[] type = ctx.getLineType();
         double width = ctx.getLineWidth();
         int lineJoin = fromGridLineJoin(ctx.getLineJoin());
@@ -306,7 +342,7 @@ public class Graphics2DDevice implements GridDevice {
         }
         float[] pattern = new float[type.length];
         for (int i = 0; i < pattern.length; i++) {
-            pattern[i] = (float) (type[i]);
+            pattern[i] = type[i];
         }
         return new BasicStroke((float) (width), endCap, lineJoin, lineMitre, pattern, 0f);
     }
@@ -336,4 +372,15 @@ public class Graphics2DDevice implements GridDevice {
                 throw RInternalError.shouldNotReachHere("unexpected value of GridLineJoin enum");
         }
     }
+
+    private static Object fromInterpolation(ImageInterpolation interpolation) {
+        if (interpolation == ImageInterpolation.NEAREST_NEIGHBOR) {
+            return RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR;
+        }
+        return RenderingHints.VALUE_INTERPOLATION_BILINEAR;
+    }
+
+    private static int iround(double val) {
+        return (int) Math.round(val);
+    }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
index b9faaaa9ffbda0758f11f75e2f2a8b268917f2f5..a284e5e34cffc18e12415d7d3e845bda2fb26dcc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/device/awt/JFrameDevice.java
@@ -39,24 +39,19 @@ import javax.swing.JPanel;
 
 public final class JFrameDevice extends Graphics2DDevice {
 
-    private final JFrame currentFrame;
-    private final boolean disposeResources;
+    private final FastRFrame currentFrame;
     private Runnable onResize;
+    private Runnable onClose;
 
     /**
      * @param frame The frame that should be used for drawing.
      * @param graphics The graphics object that should be used for drawing. This constructor
-     *            overload allows to initialize the graphics object.
-     * @param disposeResources Should the frame and graphics objects be disposed at {@link #close()}
-     *            .
+     *            overload allows to initialize the graphics object. .
      */
-    private JFrameDevice(JFrame frame, Graphics2D graphics, boolean disposeResources) {
+    private JFrameDevice(FastRFrame frame, Graphics2D graphics) {
         super(graphics, frame.getContentPane().getWidth(), frame.getContentPane().getHeight(), true);
         currentFrame = frame;
-        this.disposeResources = disposeResources;
-        if (currentFrame instanceof FastRFrame) {
-            ((FastRFrame) currentFrame).device = this;
-        }
+        currentFrame.device = this;
     }
 
     /**
@@ -65,19 +60,15 @@ public final class JFrameDevice extends Graphics2DDevice {
      */
     public static JFrameDevice create(int width, int height) {
         FastRFrame frame = new FastRFrame(width, height);
-        frame.setVisible(true);
-        frame.pack();
-        Graphics2D graphics = (Graphics2D) frame.getGraphics();
-        defaultInitGraphics(graphics);
-        return new JFrameDevice(frame, graphics, true);
+        Graphics2D graphics = initFrame(frame);
+        graphics.clearRect(0, 0, width, height);
+        return new JFrameDevice(frame, graphics);
     }
 
     @Override
     public void close() throws DeviceCloseException {
-        if (disposeResources) {
-            getGraphics2D().dispose();
-            currentFrame.dispose();
-        }
+        getGraphics2D().dispose();
+        currentFrame.dispose();
     }
 
     @Override
@@ -90,14 +81,36 @@ public final class JFrameDevice extends Graphics2DDevice {
         return currentFrame.getContentPane().getHeight();
     }
 
+    @Override
+    void ensureOpen() {
+        if (!currentFrame.isVisible()) {
+            getGraphics2D().dispose();
+            setGraphics2D(initFrame(currentFrame));
+            // TODO: for some reason this does not always clear the whole page.
+            getGraphics2D().clearRect(0, 0, currentFrame.getWidth(), currentFrame.getHeight());
+        }
+    }
+
     public void setResizeListener(Runnable onResize) {
         this.onResize = onResize;
     }
 
+    public void setCloseListener(Runnable onClose) {
+        this.onClose = onClose;
+    }
+
     JFrame getCurrentFrame() {
         return currentFrame;
     }
 
+    private static Graphics2D initFrame(FastRFrame frame) {
+        frame.setVisible(true);
+        frame.pack();
+        Graphics2D graphics = (Graphics2D) frame.getGraphics();
+        defaultInitGraphics(graphics);
+        return graphics;
+    }
+
     static class FastRFrame extends JFrame {
         private static final long serialVersionUID = 1L;
         private final JPanel fastRComponent = new JPanel();
@@ -128,7 +141,9 @@ public final class JFrameDevice extends Graphics2DDevice {
             addWindowFocusListener(new WindowAdapter() {
                 @Override
                 public void windowClosing(WindowEvent e) {
-                    dispose();
+                    if (device.onClose != null) {
+                        device.onClose.run();
+                    }
                 }
             });
             addComponentListener(new ComponentAdapter() {
@@ -139,22 +154,30 @@ public final class JFrameDevice extends Graphics2DDevice {
                     }
                     if (!resizeScheduled) {
                         resizeScheduled = true;
-                        timer.schedule(new TimerTask() {
-                            @Override
-                            public void run() {
-                                oldWidth = getWidth();
-                                oldHeight = getHeight();
-                                resizeScheduled = false;
-                                if (device.onResize != null) {
-                                    device.onResize.run();
-                                }
-                            }
-                        }, 1000);
+                        scheduleResize();
                     }
                 }
             });
         }
 
+        private void scheduleResize() {
+            timer.schedule(new TimerTask() {
+                @Override
+                public void run() {
+                    if (device == null) {
+                        scheduleResize();
+                        return;
+                    }
+                    oldWidth = getWidth();
+                    oldHeight = getHeight();
+                    resizeScheduled = false;
+                    if (device.onResize != null) {
+                        device.onResize.run();
+                    }
+                }
+            }, 1000);
+        }
+
         private void center() {
             Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
             Dimension frameSize = getSize();
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
index 6ae4427041d6d613254cd87fdb1f0ba971e8d5ad..e8051d5c63c0263639650ca2a42699774dc20f65 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevCairo.java
@@ -43,12 +43,12 @@ public class DevCairo extends RExternalBuiltinNode {
 
         String filename = RRuntime.asString(args.getArgument(0));
         int witdh = RRuntime.asInteger(args.getArgument(2));
-        int height = RRuntime.asInteger(args.getArgument(2));
+        int height = RRuntime.asInteger(args.getArgument(3));
         if (RRuntime.isNA(witdh) || RRuntime.isNA(height) || RRuntime.isNA(filename) || filename.isEmpty()) {
             throw error(Message.INVALID_ARG_TYPE);
         }
 
-        GridContext.getContext().setCurrentDevice("svg", new SVGDevice(filename, (double) witdh / 72., (double) height / 72.));
+        GridContext.getContext().setCurrentDevice("svg", new SVGDevice(FileDevUtils.formatInitialFilename(filename), witdh / 72., height / 72.), filename);
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java
index 853f82bcf3b07e76bb14ff163b5c5ce2c2e811cd..5bd49669c4885423c25632ad656332ed5ed1a2fa 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/DevHoldFlush.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.library.fastrGrid.GridContext;
 import com.oracle.truffle.r.library.fastrGrid.GridState;
+import com.oracle.truffle.r.library.fastrGrid.device.GridDevice;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 
 public abstract class DevHoldFlush extends RExternalBuiltinNode.Arg1 {
@@ -45,14 +46,18 @@ public abstract class DevHoldFlush extends RExternalBuiltinNode.Arg1 {
     int doInteger(int num) {
         GridState gridState = GridContext.getContext().getGridState();
         int result = gridState.getDevHoldCount();
+        GridDevice currentDevice = GridContext.getContext().getCurrentDevice();
+        if (currentDevice == null) {
+            return result;
+        }
         if (num < 0) {
             result = gridState.setDevHoldCount(Math.max(0, result + num));
             if (result == 0) {
-                GridContext.getContext().getCurrentDevice().flush();
+                currentDevice.flush();
             }
         } else if (num > 0) {
             if (result == 0) {
-                GridContext.getContext().getCurrentDevice().hold();
+                currentDevice.hold();
             }
             result = gridState.setDevHoldCount(result + num);
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/FileDevUtils.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/FileDevUtils.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b3d1de5038f9fd1d407bb87c7c31690b6001b86
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/FileDevUtils.java
@@ -0,0 +1,38 @@
+/*
+ * 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.grDevices;
+
+import com.oracle.truffle.api.CompilerAsserts;
+
+public class FileDevUtils {
+    public static String formatInitialFilename(String filename) {
+        return formatFilename(filename, 1);
+    }
+
+    public static String formatFilename(String filename, int pageIndex) {
+        CompilerAsserts.neverPartOfCompilation();
+        assert filename != null;
+        assert pageIndex >= 1;
+        return String.format(filename, pageIndex);
+    }
+}
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
index 9825b273c127b2caef56c0d77c931e95285ec364..de15f10dccd2b944a99a7bf02480d989c5ac3b61 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/grDevices/InitWindowedDevice.java
@@ -100,8 +100,8 @@ public final class InitWindowedDevice extends RExternalBuiltinNode {
         String formatName = name.substring(0, name.indexOf("::"));
         String filename = name.substring(name.lastIndexOf(':') + 1);
         try {
-            BufferedImageDevice device = BufferedImageDevice.open(filename, formatName, width, height);
-            GridContext.getContext().setCurrentDevice(formatName, device);
+            BufferedImageDevice device = BufferedImageDevice.open(FileDevUtils.formatInitialFilename(filename), formatName, width, height);
+            GridContext.getContext().setCurrentDevice(formatName.toUpperCase(), device, filename);
         } catch (NotSupportedImageFormatException e) {
             throw error(Message.GENERIC, String.format("Format '%s' is not supported.", formatName));
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
index 39cca90ea1e04c78909fae9683842a6d8f4268cb..524eeb912a1a86689b13e6dc427156186d67d920 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/CPar.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
 
 public final class CPar extends RExternalBuiltinNode {
     static {
@@ -64,7 +65,11 @@ public final class CPar extends RExternalBuiltinNode {
         return RDataFactory.createList(result, RDataFactory.createStringVector(resultNames, RDataFactory.COMPLETE_VECTOR));
     }
 
-    private Object getParam(String name, GridDevice device) {
+    private static Object getParam(String name, GridDevice device) {
+        if (name == null) {
+            // TODO: a hot-fix to enable package tests (e.g. cluster)
+            return RNull.instance;
+        }
         switch (name) {
             case "din":
                 return RDataFactory.createDoubleVector(new double[]{device.getWidth(), device.getHeight()}, RDataFactory.COMPLETE_VECTOR);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/R/fastrGraphics.R b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/R/fastrGraphics.R
new file mode 100644
index 0000000000000000000000000000000000000000..2ffbef80c874914e8e0457462f1055a3f1d6ed33
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/R/fastrGraphics.R
@@ -0,0 +1,173 @@
+# 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.
+
+# Emulates some graphics package functions with grid. The ideal implementation
+# would emulate the lowest level R functions that call to graphics externals,
+# e.g. plot.xy, title, ... So far we only provide higher level "plot" that also
+# prints a warning message instructing the user to use grid/lattice/ggplot2 instead
+
+eval(expression({
+    graphicsWarning <- function(name) {
+    	# lookup original function and fetch signature
+    	fun <- tryCatch(get(name, environment()), error=function(x) NULL)
+    	if(!is.null(fun)) {
+    	    sig <- formals(fun)
+    	} else {
+    	    sig <- NULL
+    	}
+    	
+        replacementFun <- function(...) {
+            warning(paste0(name, " not supported.", " Note: FastR does not support graphics package and most of its functions. Please use grid package or grid based packages like lattice instead."))
+            NULL
+        }
+
+		if(!is.null(sig)) {
+        	formals(replacementFun) <- sig
+        }
+        return(replacementFun)
+    }
+
+    plot.default <- function (x, y = NULL, type = "p", xlim = NULL, ylim = NULL,
+        log = "", main = NULL, sub = NULL, xlab = NULL, ylab = NULL,
+        ann = par("ann"), axes = TRUE, frame.plot = axes, panel.first = NULL,
+        panel.last = NULL, asp = NA, ...)
+    {
+        library(grid)
+        xlabel <- if (!missing(x)) deparse(substitute(x))
+        ylabel <- if (!missing(y)) deparse(substitute(y))
+        xy <- xy.coords(x, y, xlabel, ylabel, log)
+        xlab <- if (is.null(xlab)) xy$xlab else xlab
+        ylab <- if (is.null(ylab)) xy$ylab else ylab
+        xlim <- if (is.null(xlim)) range(xy$x[is.finite(xy$x)]) else xlim
+        ylim <- if (is.null(ylim)) range(xy$y[is.finite(xy$y)]) else ylim
+        grid.newpage()
+        dev.hold()
+        on.exit(dev.flush())
+
+        xlim <- range(xy$x[is.finite(xy$x)])
+        ylim <- range(xy$y[is.finite(xy$y)])
+        xfactor <- 1 / (xlim[[2]] - xlim[[1]])
+        yfactor <- 1 / (ylim[[2]] - ylim[[1]])
+
+        pushViewport(viewport(width=.7, height=.7))
+        grid.points((xy$x - xlim[[1]]) * xfactor, (xy$y - ylim[[1]]) * yfactor)
+
+        pushViewport(viewport(width=1.1, height=1.1))
+        grid.rect()
+        popViewport()
+
+        pushViewport(viewport(width=1, height=1.1))
+        grid.xaxis(seq(0, 1, by=.2), label = round(xlim[[1]] + seq(0, 1, by=.2) / xfactor, 2))
+        popViewport()
+
+        pushViewport(viewport(width=1.1, height=1))
+        grid.yaxis(seq(0, 1, by=.2), label = round(ylim[[1]] + seq(0, 1, by=.2) / yfactor, 2))
+        popViewport()
+
+        popViewport()
+        if (!is.null(main)) {
+            grid.text(main, 0.5, 0.91, gp=gpar(font=2))
+        }
+
+        grid.text("FastR does not support graphics package and most of its functions. \nThe 'plot' function is emulated to a small extent. \nPlease use grid package or grid based packages like lattice or ggplot2 instead.", gp=gpar(fontsize=10))
+        graphicsWarning()
+        invisible()
+    }
+
+    # Note: explicitly supported functions: din
+    # Note: harmless functions that we do not override: co.intervals, hist.default
+    # Note: S3 dispatch functions that may dispatch to lattice/ggplot2/etc. implementation: hist, contour, lines, pairs, points, text
+
+    abline <- graphicsWarning("abline");
+    arrows <- graphicsWarning("arrows");
+    assocplot <- graphicsWarning("assocplot");
+    axis <- graphicsWarning("axis");
+    Axis <- graphicsWarning("Axis");
+    axis.Date <- graphicsWarning("axis.Date");
+    axis.POSIXct <- graphicsWarning("axis.POSIXct");
+    axTicks <- graphicsWarning("axTicks");
+    barplot.default <- graphicsWarning("barplot.default");
+    box <- graphicsWarning("box");
+    boxplot.default <- graphicsWarning("boxplot.default");
+    boxplot.matrix <- graphicsWarning("boxplot.matrix");
+    bxp <- graphicsWarning("bxp");
+    cdplot <- graphicsWarning("cdplot");
+    clip <- graphicsWarning("clip");
+    close.screen <- graphicsWarning("close.screen");
+    contour.default <- graphicsWarning("contour.default");
+    coplot <- graphicsWarning("coplot");
+    curve <- graphicsWarning("curve");
+    dotchart <- graphicsWarning("dotchart");
+    erase.screen <- graphicsWarning("erase.screen");
+    filled.contour <- graphicsWarning("filled.contour");
+    fourfoldplot <- graphicsWarning("fourfoldplot");
+    frame <- graphicsWarning("frame");
+    grconvertX <- graphicsWarning("grconvertX");
+    grconvertY <- graphicsWarning("grconvertY");
+    grid <- graphicsWarning("grid");
+    identify <- graphicsWarning("identify");
+    image <- graphicsWarning("image");
+    image.default <- graphicsWarning("image.default");
+    layout <- graphicsWarning("layout");
+    layout.show <- graphicsWarning("layout.show");
+    lcm <- graphicsWarning("lcm");
+    legend <- graphicsWarning("legend");
+    lines.default <- graphicsWarning("lines.default");
+    locator <- graphicsWarning("locator");
+    matlines <- graphicsWarning("matlines");
+    matplot <- graphicsWarning("matplot");
+    matpoints <- graphicsWarning("matpoints");
+    mosaicplot <- graphicsWarning("mosaicplot");
+    mtext <- graphicsWarning("mtext");
+    pairs.default <- graphicsWarning("pairs.default");
+    panel.smooth <- graphicsWarning("panel.smooth");
+    persp <- graphicsWarning("persp");
+    pie <- graphicsWarning("pie");
+    plot.design <- graphicsWarning("plot.design");
+    plot.function <- graphicsWarning("plot.function");
+    plot.new <- graphicsWarning("plot.new");
+    plot.window <- graphicsWarning("plot.window");
+    plot.xy <- graphicsWarning("plot.xy");
+    points.default <- graphicsWarning("points.default");
+    polygon <- graphicsWarning("polygon");
+    polypath <- graphicsWarning("polypath");
+    rasterImage <- graphicsWarning("rasterImage");
+    rect <- graphicsWarning("rect");
+    rug <- graphicsWarning("rug");
+    screen <- graphicsWarning("screen");
+    segments <- graphicsWarning("segments");
+    smoothScatter <- graphicsWarning("smoothScatter");
+    spineplot <- graphicsWarning("spineplot");
+    split.screen <- graphicsWarning("split.screen");
+    stars <- graphicsWarning("stars");
+    stem <- graphicsWarning("stem");
+    strheight <- graphicsWarning("strheight");
+    stripchart <- graphicsWarning("stripchart");
+    strwidth <- graphicsWarning("strwidth");
+    sunflowerplot <- graphicsWarning("sunflowerplot");
+    symbols <- graphicsWarning("symbols");
+    text.default <- graphicsWarning("text.default");
+    title <- graphicsWarning("title");
+    xinch <- graphicsWarning("xinch");
+    xspline <- graphicsWarning("xspline");
+    xyinch <- graphicsWarning("xyinch");
+    yinch <- graphicsWarning("yinch");
+}), asNamespace("graphics"))
\ No newline at end of file
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
index f99012e978ce97b5acaeadaa66f323021627937c..d0f5518a6e39bff1c18ac8d49218dc8a49cf56df 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java
@@ -15,6 +15,7 @@
 package com.oracle.truffle.r.library.fastrGrid.graphics;
 
 import com.oracle.truffle.r.library.fastrGrid.FastRGridExternalLookup;
+import com.oracle.truffle.r.runtime.FastRConfig;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.ROptions;
@@ -22,6 +23,7 @@ import com.oracle.truffle.r.runtime.ROptions.OptionsException;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
@@ -64,9 +66,14 @@ public final class RGridGraphicsAdapter {
     public static void initialize() {
         addDevice(NULL_DEVICE);
         setCurrentDevice(NULL_DEVICE);
-        ROptions.ContextStateImpl options = RContext.getInstance().stateROptions;
+        RContext ctx = RContext.getInstance();
+        ROptions.ContextStateImpl options = ctx.stateROptions;
+        if (options.getValue(DEFAULT_DEVICE_OPTION) != RNull.instance) {
+            return;
+        }
+        String defaultDevice = (ctx.isInteractive() && FastRConfig.InternalGridAwtSupport) ? "awt" : "svg";
         try {
-            options.setValue(DEFAULT_DEVICE_OPTION, "awt");
+            options.setValue(DEFAULT_DEVICE_OPTION, defaultDevice);
         } catch (OptionsException e) {
             RError.warning(RError.NO_CALLER, Message.GENERIC, "FastR could not set the 'device' options to awt.");
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
index 00ac91621ba2c891c36d0fd298552d9fbf5a8823..65d3767af0f2d472f056608b22f9e913564d2517 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java
@@ -31,7 +31,6 @@ import com.oracle.truffle.r.library.methods.MethodsListDispatchFactory.GetGeneri
 import com.oracle.truffle.r.nodes.access.AccessSlotNode;
 import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen;
 import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
@@ -100,7 +99,6 @@ public class MethodsListDispatch {
         protected Object initMethodFallback(@SuppressWarnings("unused") Object x) {
             return RNull.instance;
         }
-
     }
 
     public abstract static class R_methodsPackageMetaName extends RExternalBuiltinNode.Arg3 {
@@ -172,7 +170,6 @@ public class MethodsListDispatch {
         protected RS4Object callGetClassFromCache(RS4Object klass, @SuppressWarnings("unused") REnvironment table) {
             return klass;
         }
-
     }
 
     public abstract static class R_set_method_dispatch extends RExternalBuiltinNode.Arg1 {
@@ -238,7 +235,7 @@ public class MethodsListDispatch {
             Object opx = op;
             if ((op instanceof RFunction) && !((RFunction) op).isBuiltin()) {
                 String internalName = RRuntime.asString(initAccessSlotNode().executeAccess(op, "internal"));
-                opx = RContext.lookupBuiltin(internalName);
+                opx = RContext.getInstance().lookupBuiltin(internalName);
                 if (opx == null) {
                     throw error(RError.Message.GENERIC, "'internal' slot does not name an internal function: " + internalName);
                 }
@@ -464,11 +461,11 @@ public class MethodsListDispatch {
 
             }
             RCallNode callNode = (RCallNode) matchedCall.getRep();
-            RNode f = ReadVariableNode.create(RRuntime.R_DOT_NEXT_METHOD);
+            RNode f = RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, RRuntime.R_DOT_NEXT_METHOD, false).asRNode();
             ArgumentsSignature sig = callNode.getSyntaxSignature();
             RSyntaxNode[] args = new RSyntaxNode[sig.getLength()];
             for (int i = 0; i < args.length; i++) {
-                args[i] = ReadVariableNode.create(sig.getName(i));
+                args[i] = RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, sig.getName(i), false);
             }
             RLanguage newCall = RDataFactory.createLanguage(RCallNode.createCall(RSyntaxNode.SOURCE_UNAVAILABLE, f, sig, args));
             Object res = RContext.getEngine().eval(newCall, ev.getFrame());
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
index 741c70902416f676b80ebb64b405effafc205a6c..526dcfa7d628bba87bac7547e90d43469da3adc5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java
@@ -56,7 +56,6 @@ public class Slot {
         protected Object getSlot(Object object, String name) {
             return accessSlotNode.executeAccess(castAttributable.executeObject(object), getInternedName(name));
         }
-
     }
 
     public abstract static class R_setSlot extends RExternalBuiltinNode.Arg3 {
@@ -84,6 +83,5 @@ public class Slot {
         protected Object setSlot(Object object, String name, Object value) {
             return updateSlotNode.executeUpdate(castAttributable.executeObject(object), getInternedName(name), value);
         }
-
     }
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
index 0bd6d97f09823da2e2123a82c5f5d042aeefbcde..bbdcd3fd61e16e8c2ca127b3bd2d7cffdd7f8355 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/SubstituteDirect.java
@@ -54,10 +54,10 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
 
     @Specialization
     @TruffleBoundary
-    protected static Object substituteDirect(Object object, REnvironment env) {
+    protected Object substituteDirect(Object object, REnvironment env) {
         if (object instanceof RLanguage) {
             RLanguage lang = (RLanguage) object;
-            return RASTUtils.createLanguageElement(RSubstitute.substitute(env, lang.getRep()));
+            return RASTUtils.createLanguageElement(RSubstitute.substitute(env, lang.getRep(), getRLanguage()));
         } else {
             return object;
         }
@@ -65,13 +65,13 @@ public abstract class SubstituteDirect extends RExternalBuiltinNode.Arg2 {
 
     @Specialization(guards = {"list.getNames() == null || list.getNames().getLength() == 0"})
     @TruffleBoundary
-    protected static Object substituteDirect(Object object, @SuppressWarnings("unused") RList list) {
+    protected Object substituteDirect(Object object, @SuppressWarnings("unused") RList list) {
         return substituteDirect(object, createNewEnvironment());
     }
 
     @Specialization(guards = {"list.getNames() != null", "list.getNames().getLength() > 0"})
     @TruffleBoundary
-    protected static Object substituteDirect(Object object, RList list,
+    protected Object substituteDirect(Object object, RList list,
                     @Cached("createList2EnvNode()") RList2EnvNode list2Env) {
         return substituteDirect(object, createEnvironment(list, list2Env));
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
index 1b7b81345c61a2dee531da2469918a904077780f..c0183e5841ef8b80453f77a7ce2e3332e32d2d49 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java
@@ -47,7 +47,7 @@ public final class CompleteCases extends RExternalBuiltinNode {
     }
 
     private int checkAbstractVectorLength(int len, Object obj) {
-        Object entry = RRuntime.asAbstractVector(obj);
+        Object entry = RRuntime.convertScalarVectors(obj);
         if (entry instanceof RAbstractVector) {
             RAbstractVector vector = (RAbstractVector) entry;
             int entryLength = vector.isMatrix() ? vector.getDimensions()[0] : vector.getLength();
@@ -106,56 +106,56 @@ public final class CompleteCases extends RExternalBuiltinNode {
             if (arg instanceof RPairList) {
                 for (Object t = ((RPairList) arg).car(); t != RNull.instance; t = ((RPairList) t).cdr()) {
                     Object entry = ((RPairList) t).car();
-                    iterateAbstractVectorContents(len, result, i, entry);
+                    iterateAbstractVectorContents(len, result, entry);
                 }
             } else if (arg instanceof RList) {
                 RList list = (RList) arg;
                 for (int entry = 0; entry < list.getLength(); entry++) {
-                    iterateAbstractVectorContents(len, result, i, list.getDataAt(entry));
+                    iterateAbstractVectorContents(len, result, list.getDataAt(entry));
                 }
             } else {
-                iterateAbstractVectorContents(len, result, i, arg);
+                iterateAbstractVectorContents(len, result, arg);
             }
         }
 
         return RDataFactory.createLogicalVector(result, true);
     }
 
-    private void iterateAbstractVectorContents(int len, byte[] result, int i, Object obj) {
+    private void iterateAbstractVectorContents(int len, byte[] result, Object obj) {
         Object entry = RRuntime.asAbstractVector(obj);
         if (entry instanceof RAbstractIntVector) {
             RAbstractIntVector v = (RAbstractIntVector) entry;
             for (int e = 0; e < v.getLength(); e++) {
                 if (RRuntime.isNA(v.getDataAt(e))) {
-                    result[i % len] = RRuntime.LOGICAL_FALSE;
+                    result[e % len] = RRuntime.LOGICAL_FALSE;
                 }
             }
         } else if (entry instanceof RAbstractLogicalVector) {
             RAbstractLogicalVector v = (RAbstractLogicalVector) entry;
             for (int e = 0; e < v.getLength(); e++) {
                 if (RRuntime.isNA(v.getDataAt(e))) {
-                    result[i % len] = RRuntime.LOGICAL_FALSE;
+                    result[e % len] = RRuntime.LOGICAL_FALSE;
                 }
             }
         } else if (entry instanceof RAbstractDoubleVector) {
             RAbstractDoubleVector v = (RAbstractDoubleVector) entry;
             for (int e = 0; e < v.getLength(); e++) {
                 if (Double.isNaN(v.getDataAt(e))) {
-                    result[i % len] = RRuntime.LOGICAL_FALSE;
+                    result[e % len] = RRuntime.LOGICAL_FALSE;
                 }
             }
         } else if (entry instanceof RAbstractComplexVector) {
             RAbstractComplexVector v = (RAbstractComplexVector) entry;
             for (int e = 0; e < v.getLength(); e++) {
                 if (Double.isNaN(v.getDataAt(e).getRealPart()) || Double.isNaN(v.getDataAt(e).getImaginaryPart())) {
-                    result[i % len] = RRuntime.LOGICAL_FALSE;
+                    result[e % len] = RRuntime.LOGICAL_FALSE;
                 }
             }
         } else if (entry instanceof RAbstractStringVector) {
             RAbstractStringVector v = (RAbstractStringVector) entry;
             for (int e = 0; e < v.getLength(); e++) {
                 if (RRuntime.isNA(v.getDataAt(e))) {
-                    result[i % len] = RRuntime.LOGICAL_FALSE;
+                    result[e % len] = RRuntime.LOGICAL_FALSE;
                 }
             }
         } else {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
index d3dad0bc79bf3e3e0c56e7c91ab3d3e68a98f5f7..2db1002741a2ad78d23122863da374121ab3f4fc 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java
@@ -32,10 +32,10 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.RCallSpecialNode;
@@ -44,6 +44,7 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -129,12 +130,22 @@ public abstract class Deriv extends RExternalBuiltinNode {
 
     @Specialization(guards = "isConstant(expr)")
     protected Object derive(VirtualFrame frame, Object expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
-        return derive(frame, RDataFactory.createLanguage(ConstantNode.create(expr)), names, functionArg, tag, hessian);
+        return derive(frame.materialize(), createConstant(expr), names, functionArg, tag, hessian);
+    }
+
+    @TruffleBoundary
+    private static ConstantNode createConstant(Object expr) {
+        return ConstantNode.create(expr);
     }
 
     @Specialization
     protected Object derive(VirtualFrame frame, RSymbol expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
-        return derive(frame, (RBaseNode) RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false), names, functionArg, tag, hessian);
+        return derive(frame.materialize(), createLookup(expr), names, functionArg, tag, hessian);
+    }
+
+    @TruffleBoundary
+    private static RBaseNode createLookup(RSymbol expr) {
+        return (RBaseNode) RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, expr.getName(), false);
     }
 
     @Specialization
@@ -145,11 +156,12 @@ public abstract class Deriv extends RExternalBuiltinNode {
 
     @Specialization
     protected Object derive(VirtualFrame frame, RLanguage expr, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
-        return derive(frame, expr.getRep(), names, functionArg, tag, hessian);
+        return derive(frame.materialize(), expr.getRep(), names, functionArg, tag, hessian);
     }
 
-    private Object derive(VirtualFrame frame, RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
-        return findDerive(elem, names, functionArg, tag, hessian).getResult(frame);
+    @TruffleBoundary
+    private Object derive(MaterializedFrame frame, RBaseNode elem, RAbstractStringVector names, Object functionArg, String tag, boolean hessian) {
+        return findDerive(elem, names, functionArg, tag, hessian).getResult(frame.materialize(), getRLanguage());
     }
 
     private static final class DerivResult {
@@ -169,18 +181,13 @@ public abstract class Deriv extends RExternalBuiltinNode {
             result = null;
         }
 
-        private Object getResult(VirtualFrame frame) {
+        private Object getResult(MaterializedFrame frame, TruffleRLanguage language) {
             if (result != null) {
                 return result;
             }
-            RootCallTarget callTarget = getRootCallTarget();
+            RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(language, RSyntaxNode.LAZY_DEPARSE, targetArgs, blockCall, null);
             FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), frame);
-            return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, frame.materialize());
-        }
-
-        @TruffleBoundary
-        private RootCallTarget getRootCallTarget() {
-            return RContext.getASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, targetArgs, blockCall, null);
+            return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, frame);
         }
     }
 
@@ -208,7 +215,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
         int nexpr = exprlist.size();
 
         if (fIndex > 0) {
-            exprlist.add(ReadVariableNode.create(tag + fIndex));
+            exprlist.add(createLookup(tag + fIndex));
         } else {
             exprlist.add(cloneElement(elem.asRSyntaxNode()));
         }
@@ -220,20 +227,19 @@ public abstract class Deriv extends RExternalBuiltinNode {
 
         for (int i = 0, k = 0; i < nderiv; i++) {
             if (dIndex[i] > 0) {
-                exprlist.add(ReadVariableNode.create(tag + dIndex[i]));
+                exprlist.add(createLookup(tag + dIndex[i]));
 
                 if (hessian) {
                     RBaseNode dExpr = d(elem, names.getDataAt(i));
                     for (int j = i; j < nderiv; j++) {
                         if (d2Index[k] > 0) {
-                            exprlist.add(ReadVariableNode.create(tag + d2Index[k]));
+                            exprlist.add(createLookup(tag + d2Index[k]));
                         } else {
                             exprlist.add((RSyntaxNode) d(dExpr, names.getDataAt(j)));
                         }
                         k++;
                     }
                 }
-
             } else {
                 // the first derivative is constant or simple variable
                 // TODO: do not call the d twice
@@ -243,7 +249,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
                 if (hessian) {
                     for (int j = i; j < nderiv; j++) {
                         if (d2Index[k] > 0) {
-                            exprlist.add(ReadVariableNode.create(tag + d2Index[k]));
+                            exprlist.add(createLookup(tag + d2Index[k]));
                         } else {
                             RBaseNode d2Expr = d(dExpr, names.getDataAt(j));
                             if (isZero((RSyntaxElement) d2Expr)) {
@@ -298,7 +304,6 @@ public abstract class Deriv extends RExternalBuiltinNode {
                     }
                 }
             }
-
         }
         // attr(.value, "gradient") <- .grad
         exprlist.set(p++, addGrad());
@@ -307,7 +312,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
         }
 
         // .value
-        exprlist.set(p++, ReadVariableNode.create(".value"));
+        exprlist.set(p++, createLookup(".value"));
 
         // prune exprlist
         exprlist.removeAll(Collections.singleton(null));
@@ -316,7 +321,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
         for (RSyntaxNode e : exprlist) {
             blockStatements.add(RCodeBuilder.argument(e));
         }
-        RSyntaxNode blockCall = RContext.getASTBuilder().call(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.create("{"), blockStatements);
+        RSyntaxNode blockCall = RContext.getASTBuilder().call(RSyntaxNode.LAZY_DEPARSE, createLookup("{"), blockStatements);
 
         if (functionArg instanceof RAbstractStringVector) {
             RAbstractStringVector funArgNames = (RAbstractStringVector) functionArg;
@@ -348,7 +353,6 @@ public abstract class Deriv extends RExternalBuiltinNode {
             RExpression res = RDataFactory.createExpression(new Object[]{lan});
             return new DerivResult(res);
         }
-
     }
 
     private int findSubexpression(RBaseNode expr, List<RSyntaxNode> exprlist, String tag) {
@@ -368,7 +372,7 @@ public abstract class Deriv extends RExternalBuiltinNode {
                 for (int i = 0; i < args.length; i++) {
                     int k = accept(args[i]);
                     if (k > 0) {
-                        newArgs.add(RCodeBuilder.argument(ReadVariableNode.create(tag + k)));
+                        newArgs.add(RCodeBuilder.argument(createLookup(tag + k)));
                     } else {
                         newArgs.add(RCodeBuilder.argument(cloneElement(args[i])));
                     }
@@ -391,7 +395,6 @@ public abstract class Deriv extends RExternalBuiltinNode {
             protected Integer visit(RSyntaxFunction element) {
                 throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_EXPRESSION, "FindSubexprs");
             }
-
         };
         return vis.accept((RSyntaxElement) expr);
     }
@@ -518,9 +521,9 @@ public abstract class Deriv extends RExternalBuiltinNode {
 
     static RSyntaxNode newCall(String functionName, RSyntaxElement arg1, RSyntaxElement arg2) {
         if (arg2 == null) {
-            return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create(functionName), (RSyntaxNode) arg1);
+            return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup(functionName), (RSyntaxNode) arg1);
         } else {
-            return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create(functionName), (RSyntaxNode) arg1, (RSyntaxNode) arg2);
+            return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup(functionName), (RSyntaxNode) arg1, (RSyntaxNode) arg2);
         }
     }
 
@@ -603,7 +606,6 @@ public abstract class Deriv extends RExternalBuiltinNode {
             protected RSyntaxElement visit(RSyntaxFunction element) {
                 throw RInternalError.shouldNotReachHere();
             }
-
         };
 
         exprlist.set(fromIndex, (RSyntaxNode) vis.accept(exprListNode));
@@ -611,24 +613,28 @@ public abstract class Deriv extends RExternalBuiltinNode {
         replace(subexprName, replacement, exprlist, fromIndex + 1);
     }
 
+    private static RSyntaxNode createLookup(String name) {
+        return RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, name, false);
+    }
+
     private static RSyntaxNode createAssignNode(String varName, RSyntaxNode rhs) {
-        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(varName.intern()), addParens(rhs));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), createLookup(varName.intern()), addParens(rhs));
     }
 
     private static RSyntaxNode hessAssign1(String varName, RSyntaxNode rhs) {
-        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("["), createLookup(".hessian"), ConstantNode.create(REmpty.instance),
                         ConstantNode.create(varName.intern()), ConstantNode.create(varName.intern()));
-        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, rhs);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), tmp, rhs);
     }
 
     private static RSyntaxNode hessAssign2(String varName1, String varName2, RSyntaxNode rhs) {
-        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("["), createLookup(".hessian"), ConstantNode.create(REmpty.instance),
                         ConstantNode.create(varName1.intern()), ConstantNode.create(varName2.intern()));
-        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".hessian"), ConstantNode.create(REmpty.instance),
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("["), createLookup(".hessian"), ConstantNode.create(REmpty.instance),
                         ConstantNode.create(varName2.intern()), ConstantNode.create(varName1.intern()));
 
-        RSyntaxNode tmp3 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp2, rhs);
-        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp1, tmp3);
+        RSyntaxNode tmp3 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), tmp2, rhs);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), tmp1, tmp3);
     }
 
     private static RSyntaxNode createGrad(RAbstractStringVector names) {
@@ -637,15 +643,15 @@ public abstract class Deriv extends RExternalBuiltinNode {
         for (int i = 0; i < n; i++) {
             cArgs.add(RCodeBuilder.argument(ConstantNode.create(names.getDataAt(i).intern())));
         }
-        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), cArgs);
-        RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("list"), ConstantNode.create(RNull.instance), tmp1);
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("c"), cArgs);
+        RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("list"), ConstantNode.create(RNull.instance), tmp1);
 
-        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("length"), ReadVariableNode.create(".value"));
-        RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), tmp2, ConstantNode.create(n));
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("length"), createLookup(".value"));
+        RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("c"), tmp2, ConstantNode.create(n));
         ConstantNode data = ConstantNode.create(0.);
 
-        RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("array"), data, dim, dimnames);
-        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(".grad"), p);
+        RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("array"), data, dim, dimnames);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), createLookup(".grad"), p);
     }
 
     private static RSyntaxNode createHess(RAbstractStringVector names) {
@@ -654,32 +660,32 @@ public abstract class Deriv extends RExternalBuiltinNode {
         for (int i = 0; i < n; i++) {
             cArgs.add(RCodeBuilder.argument(ConstantNode.create(names.getDataAt(i).intern())));
         }
-        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), cArgs);
+        RSyntaxNode tmp1 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("c"), cArgs);
         RSyntaxNode tmp1Clone = cloneElement(tmp1);
-        RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("list"), ConstantNode.create(RNull.instance), tmp1, tmp1Clone);
+        RSyntaxNode dimnames = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("list"), ConstantNode.create(RNull.instance), tmp1, tmp1Clone);
 
-        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("length"), ReadVariableNode.create(".value"));
-        RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("c"), tmp2, ConstantNode.create(n), ConstantNode.create(n));
+        RSyntaxNode tmp2 = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("length"), createLookup(".value"));
+        RSyntaxNode dim = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("c"), tmp2, ConstantNode.create(n), ConstantNode.create(n));
         ConstantNode data = ConstantNode.create(0.);
 
-        RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("array"), data, dim, dimnames);
-        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), ReadVariableNode.create(".hessian"), p);
+        RSyntaxNode p = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("array"), data, dim, dimnames);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), createLookup(".hessian"), p);
     }
 
     private static RSyntaxNode derivAssign(String name, RSyntaxNode expr) {
-        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("["), ReadVariableNode.create(".grad"), ConstantNode.create(REmpty.instance),
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("["), createLookup(".grad"), ConstantNode.create(REmpty.instance),
                         ConstantNode.create(name.intern()));
-        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, expr);
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), tmp, expr);
     }
 
     private static RSyntaxNode addGrad() {
-        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("attr"), ReadVariableNode.create(".value"), ConstantNode.create("gradient"));
-        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, ReadVariableNode.create(".grad"));
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("attr"), createLookup(".value"), ConstantNode.create("gradient"));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), tmp, createLookup(".grad"));
     }
 
     private static RSyntaxNode addHess() {
-        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("attr"), ReadVariableNode.create(".value"), ConstantNode.create("hessian"));
-        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, ReadVariableNode.create("<-"), tmp, ReadVariableNode.create(".hessian"));
+        RSyntaxNode tmp = RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("attr"), createLookup(".value"), ConstantNode.create("hessian"));
+        return RContext.getASTBuilder().call(RSyntaxNode.SOURCE_UNAVAILABLE, createLookup("<-"), tmp, createLookup(".hessian"));
     }
 
     private static boolean isForm(RSyntaxElement expr, String functionName) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java
index 8dc3708ecd3527565a524513b83072f1e4407a53..f257304d630ffdd9e0cbd760e02995fd4714e201 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java
@@ -404,5 +404,4 @@ public class DerivVisitor extends RSyntaxVisitor<RSyntaxElement> {
         Number n = (Number) ((RSyntaxConstant) elem).getValue();
         return ConstantNode.create(n.intValue() + 1);
     }
-
 }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
index 7b78cebbe247c874e39264c65f996c488133bced..b62147da84a016d7f4cd51f1ab5090db514cc0a9 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/C_ParseRd.java
@@ -30,9 +30,9 @@ 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.r.ffi.impl.nodes.AsIntegerNode;
+import com.oracle.truffle.r.ffi.impl.nodes.AsLogicalNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
-import com.oracle.truffle.r.nodes.ffi.AsIntegerNode;
-import com.oracle.truffle.r.nodes.ffi.AsLogicalNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.conn.RConnection;
@@ -44,7 +44,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
 
 public abstract class C_ParseRd extends RExternalBuiltinNode.Arg9 {
-    @Child ToolsRFFI.ParseRdNode parseRdNode = RFFIFactory.getRFFI().getToolsRFFI().createParseRdNode();
+    @Child private ToolsRFFI.ParseRdNode parseRdNode = RFFIFactory.getToolsRFFI().createParseRdNode();
 
     static {
         Casts casts = new Casts(C_ParseRd.class);
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
index 98db4f99c4790b0d617a24f7ef62f6fe0aa13a9a..27121e59664552083dad8b778d51d4adcc792de5 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java
@@ -54,7 +54,10 @@ public abstract class DirChmod extends RExternalBuiltinNode.Arg2 {
         Path path = FileSystems.getDefault().getPath(pathName);
         int fileMask = setGroupWrite ? GRPWRITE_FILE_MASK : FILE_MASK;
         int dirMask = setGroupWrite ? GRPWRITE_DIR_MASK : DIR_MASK;
-        assert path.isAbsolute();
+        if (!path.toFile().exists()) {
+            return RNull.instance;
+        }
+        assert path.isAbsolute() : path;
         try (Stream<Path> stream = Files.walk(path, Integer.MAX_VALUE)) {
             Iterator<Path> iter = stream.iterator();
             while (iter.hasNext()) {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
index 86b2f791bb7d4dbf9a075bce6171d28f924a47a9..e2777a22970298172a63991cce695976081c0c0c 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java
@@ -14,11 +14,11 @@ package com.oracle.truffle.r.library.utils;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 // Translated from GnuR: library/utils/io.c
@@ -33,10 +33,10 @@ public abstract class Menu extends RExternalBuiltinNode.Arg1 {
     @Specialization
     @TruffleBoundary
     protected int menu(RAbstractStringVector choices) {
-        ConsoleHandler ch = RContext.getInstance().getConsoleHandler();
+        ConsoleIO console = RContext.getInstance().getConsole();
         int first = choices.getLength() + 1;
-        ch.print("Selection: ");
-        String response = ch.readLine().trim();
+        console.print("Selection: ");
+        String response = console.readLine().trim();
         if (response.length() > 0) {
             if (Character.isDigit(response.charAt(0))) {
                 try {
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
index 8ef4e9fb592f66cc0f89ae4b40c45ee331b81000..49efa1fd131ed509dc5d88b3a5ffebe7056d6fdb 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprof.java
@@ -81,7 +81,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * the function name.
  *
  */
-public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFactory.Listener, MemoryCopyTracer.Listener {
+public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements MemoryCopyTracer.Listener {
 
     static {
         Casts casts = new Casts(Rprof.class);
@@ -114,8 +114,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa
                     warning(RError.Message.GENERIC, "Rprof: gc profiling not supported");
                 }
                 if (memProfiling) {
-                    RDataFactory.addListener(this);
-                    RDataFactory.setTracingState(true);
+                    RDataFactory.addListener(LISTENER);
                     MemoryCopyTracer.addListener(this);
                     MemoryCopyTracer.setTracingState(true);
                 }
@@ -133,21 +132,26 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa
         return RNull.instance;
     }
 
-    @Override
-    @TruffleBoundary
-    public void reportAllocation(RTypedValue data) {
-        RprofState profState = RprofState.get();
-        long size = RObjectSize.getObjectSize(data, Rprofmem.myIgnoreObjectHandler);
-        if (data instanceof RAbstractVector) {
-            if (size >= Rprofmem.LARGE_VECTOR) {
-                profState.memoryQuad.largeV += size;
+    private static final RDataFactory.Listener LISTENER = new RDataFactory.Listener() {
+        @Override
+        @TruffleBoundary
+        public void reportAllocation(RTypedValue data) {
+            RprofState profState = RprofState.get();
+            if (profState.memoryQuad == null) {
+                return;
+            }
+            long size = RObjectSize.getObjectSize(data, Rprofmem.myIgnoreObjectHandler);
+            if (data instanceof RAbstractVector) {
+                if (size >= Rprofmem.LARGE_VECTOR) {
+                    profState.memoryQuad.largeV += size;
+                } else {
+                    profState.memoryQuad.smallV += size;
+                }
             } else {
-                profState.memoryQuad.smallV += size;
+                profState.memoryQuad.nodes += size;
             }
-        } else {
-            profState.memoryQuad.nodes += size;
         }
-    }
+    };
 
     @Override
     @TruffleBoundary
@@ -359,7 +363,7 @@ public abstract class Rprof extends RExternalBuiltinNode.Arg8 implements RDataFa
             out.close();
             this.setOut(null);
             if (this.memoryProfiling) {
-                RDataFactory.setTracingState(false);
+                RDataFactory.removeListener(LISTENER);
                 MemoryCopyTracer.setTracingState(false);
             }
         }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java
index 34a5b00b398ed1f03bc1408f29547dbac905126e..197dc7b9bd1672be42b9ed79677a120422757e34 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Rprofmem.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState.RprofState;
 
-public abstract class Rprofmem extends RExternalBuiltinNode.Arg3 implements RDataFactory.Listener {
+public abstract class Rprofmem extends RExternalBuiltinNode.Arg3 {
 
     static {
         Casts casts = new Casts(Rprofmem.class);
@@ -75,8 +75,7 @@ public abstract class Rprofmem extends RExternalBuiltinNode.Arg3 implements RDat
             try {
                 PrintStream out = new PrintStream(new FileOutputStream(filename, append));
                 profmemState.initialize(out, thresholdVec.getDataAt(0));
-                RDataFactory.addListener(this);
-                RDataFactory.setTracingState(true);
+                RDataFactory.addListener(LISTENER);
             } catch (IOException ex) {
                 throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filename));
             }
@@ -116,39 +115,40 @@ public abstract class Rprofmem extends RExternalBuiltinNode.Arg3 implements RDat
 
     static final RObjectSize.IgnoreObjectHandler myIgnoreObjectHandler = new MyIgnoreObjectHandler();
 
-    @Override
-    @TruffleBoundary
-    public void reportAllocation(RTypedValue data) {
-        // We could do some in memory buffering
-        // TODO write out full stack
-        RprofmemState profmemState = RprofmemState.get();
-        Frame frame = Utils.getActualCurrentFrame();
-        if (frame == null) {
-            // not an R evaluation, some internal use
-            return;
-        }
-        RFunction func = RArguments.getFunction(frame);
-        if (func == null) {
-            return;
-        }
-        String name = func.getRootNode().getName();
-
-        long size = RObjectSize.getObjectSize(data, myIgnoreObjectHandler);
-        if (data instanceof RAbstractVector && size >= LARGE_VECTOR) {
-            if (size > profmemState.threshold) {
-                profmemState.out().printf("%d: %s\n", size, name);
+    private static final RDataFactory.Listener LISTENER = new RDataFactory.Listener() {
+        @Override
+        public void reportAllocation(RTypedValue data) {
+            // We could do some in memory buffering
+            // TODO write out full stack
+            RprofmemState profmemState = RprofmemState.get();
+            Frame frame = Utils.getActualCurrentFrame();
+            if (frame == null) {
+                // not an R evaluation, some internal use
+                return;
             }
-        } else {
-            int pageCount = profmemState.pageCount;
-            long pcs = pageCount + size;
-            if (pcs > PAGE_SIZE) {
-                profmemState.out().printf("new page: %s\n", name);
-                profmemState.pageCount = (int) (pcs - PAGE_SIZE);
+            RFunction func = RArguments.getFunction(frame);
+            if (func == null) {
+                return;
+            }
+            String name = func.getRootNode().getName();
+
+            long size = RObjectSize.getObjectSize(data, myIgnoreObjectHandler);
+            if (data instanceof RAbstractVector && size >= LARGE_VECTOR) {
+                if (size > profmemState.threshold) {
+                    profmemState.out().printf("%d: %s\n", size, name);
+                }
             } else {
-                profmemState.pageCount = (int) pcs;
+                int pageCount = profmemState.pageCount;
+                long pcs = pageCount + size;
+                if (pcs > PAGE_SIZE) {
+                    profmemState.out().printf("new page: %s\n", name);
+                    profmemState.pageCount = (int) (pcs - PAGE_SIZE);
+                } else {
+                    profmemState.pageCount = (int) pcs;
+                }
             }
         }
-    }
+    };
 
     private static final class RprofmemState extends RprofState {
         private double threshold;
@@ -170,7 +170,7 @@ public abstract class Rprofmem extends RExternalBuiltinNode.Arg3 implements RDat
 
         @Override
         public void cleanup(int status) {
-            RDataFactory.setTracingState(false);
+            RDataFactory.removeListener(LISTENER);
             closeAndResetOut();
         }
     }
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Unzip.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Unzip.java
new file mode 100644
index 0000000000000000000000000000000000000000..334edb9283eff0847d165f2a9dc8566333ffb5ec
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Unzip.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2017, 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.utils;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.function.Predicate;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RIntVector;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+public abstract class Unzip extends RExternalBuiltinNode.Arg7 {
+
+    static {
+        Casts casts = new Casts(Unzip.class);
+        casts.arg(0, "zipfile").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+        casts.arg(1, "files").allowNull().mustBe(stringValue()).asStringVector();
+        casts.arg(2, "exdir").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+        casts.arg(3, "list").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst().map(toBoolean());
+        casts.arg(4, "overwrite").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst().map(toBoolean());
+        casts.arg(5, "junkpaths").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst().map(toBoolean());
+        casts.arg(6, "setTimes").mustBe(logicalValue()).asLogicalVector().mustBe(singleElement()).findFirst().map(toBoolean());
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected Object unzip(String zipfile, @SuppressWarnings("unused") RNull files, String exdir, boolean list, boolean overwrite, boolean junkpaths, boolean setTimes) {
+        return unzip(zipfile, (RAbstractStringVector) null, exdir, list, overwrite, junkpaths, setTimes);
+    }
+
+    @Override
+    protected RBaseNode getErrorContext() {
+        return RError.SHOW_CALLER;
+    }
+
+    @Specialization
+    @TruffleBoundary
+    protected Object unzip(String zipfile, RAbstractStringVector files, String exdir, boolean list, boolean overwrite, boolean junkpaths, boolean setTimes) {
+        if (list) {
+            return list(zipfile);
+        }
+        Predicate<String> filter;
+        boolean[] found;
+        if (files == null) {
+            found = null;
+            filter = x -> true;
+        } else {
+            found = new boolean[files.getLength()];
+            filter = x -> {
+                for (int i = 0; i < files.getLength(); i++) {
+                    if (x.equals(files.getDataAt(i))) {
+                        found[i] = true;
+                        return true;
+                    }
+                }
+                return false;
+            };
+        }
+
+        File targetDir = new File(exdir);
+        if (!targetDir.exists() || !targetDir.isDirectory()) {
+            throw error(Message.GENERIC, "invalid target directory");
+        }
+        try (ZipInputStream stream = new ZipInputStream(new FileInputStream(Utils.tildeExpand(zipfile)))) {
+            ZipEntry entry;
+            ArrayList<String> extracted = new ArrayList<>();
+            byte[] buffer = new byte[2048];
+            while ((entry = stream.getNextEntry()) != null) {
+                if (filter.test(entry.getName())) {
+                    File target = new File(targetDir, junkpaths ? new File(entry.getName()).getName() : entry.getName());
+                    if (!target.exists() || overwrite) {
+                        try (FileOutputStream output = new FileOutputStream(target)) {
+                            extracted.add(target.getPath());
+                            int length;
+                            while ((length = stream.read(buffer)) > 0) {
+                                output.write(buffer, 0, length);
+                            }
+                        }
+                        if (setTimes) {
+                            target.setLastModified(entry.getTime());
+                        }
+                    }
+                }
+            }
+            if (files != null) {
+                for (int i = 0; i < found.length; i++) {
+                    if (!found[i]) {
+                        warning(Message.FILE_NOT_FOUND_IN_ZIP);
+                        break;
+                    }
+                }
+            }
+            RIntVector result = RDataFactory.createIntVector(new int[]{0}, true);
+            result.setAttr("extracted", RDataFactory.createStringVector(extracted.toArray(new String[0]), true));
+            return result;
+        } catch (IOException e) {
+            throw error(Message.GENERIC, "error while extracting zip: " + e.getMessage());
+        }
+    }
+
+    @SuppressWarnings("deprecation")
+    private Object list(String zipfile) {
+        try (ZipInputStream stream = new ZipInputStream(new FileInputStream(Utils.tildeExpand(zipfile)))) {
+            ArrayList<ZipEntry> entryList = new ArrayList<>();
+            ZipEntry entry;
+            while ((entry = stream.getNextEntry()) != null) {
+                entryList.add(entry);
+            }
+            String[] names = new String[entryList.size()];
+            double[] sizes = new double[entryList.size()];
+            String[] dates = new String[entryList.size()];
+            for (int i = 0; i < entryList.size(); i++) {
+                entry = entryList.get(i);
+                names[i] = entry.getName();
+                sizes[i] = entry.getSize();
+                // rounding up to minutes
+                Date date = new Date(entry.getTime() + (30 * 1000));
+                dates[i] = String.format("%04d-%02d-%02d %02d:%02d", date.getYear() + 1900, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes());
+            }
+            return RDataFactory.createList(new Object[]{RDataFactory.createStringVector(names, true), RDataFactory.createDoubleVector(sizes, true), RDataFactory.createStringVector(dates, true)});
+        } catch (IOException e) {
+            throw error(Message.GENERIC, "error while extracting zip: " + e.getMessage());
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.native.recommended/Makefile b/com.oracle.truffle.r.native.recommended/Makefile
index 9b9eaa96e99c6fac69eb797e7f37c6ef9e51e2a5..b44020033d70fa87dc57b5079d0ef954b2d045e3 100644
--- a/com.oracle.truffle.r.native.recommended/Makefile
+++ b/com.oracle.truffle.r.native.recommended/Makefile
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -51,6 +51,7 @@ GNUR_RECOMMENDED_TARS := $(foreach pkg, $(GNUR_RECOMMENDED_PKGNAMES),$(GNUR_HOME
 all: install.recommended
 
 ifdef FASTR_RELEASE
+ifneq ($(FASTR_RFFI),managed)
 install.recommended: $(GNUR_RECOMMENDED_TARS)
 	for pkgtar in $(GNUR_RECOMMENDED_TARS); do \
 		$(FASTR_R_HOME)/bin/R CMD INSTALL --library=$(FASTR_R_HOME)/library $$pkgtar; \
@@ -62,6 +63,9 @@ ifeq ($(OS_NAME),Darwin)
 			mx rupdatelib $(FASTR_R_HOME)/library/$$pkgname/libs; \
 		fi \
 	done
+endif
+else
+install.recommended:
 endif
 	touch install.recommended
 else
diff --git a/com.oracle.truffle.r.native/Makefile b/com.oracle.truffle.r.native/Makefile
index 69ba9ce1860aaf7d021ada51424d36dc30cad552..9c35cd4da67430a24da06d00f9d72cc5b3b55131 100644
--- a/com.oracle.truffle.r.native/Makefile
+++ b/com.oracle.truffle.r.native/Makefile
@@ -30,13 +30,10 @@ export FASTR_NATIVE_DIR = $(TOPDIR)
 export R_VERSION = $(subst R-,,$(notdir $(basename $(basename $(wildcard $(FASTR_R_HOME)/libdownloads/R-*.gz)))))
 export GNUR_HOME = $(TOPDIR)/gnur/R-$(R_VERSION)
 
+
 ifndef FASTR_RFFI
-ifeq ($(FASTR_MANAGED),true)
-export FASTR_RFFI = managed
-else
 export FASTR_RFFI = jni
 endif
-endif
 
 # Completely accurate dependency analysis is very difficult for this project, so use a version number
 # to force a clean build, and elsewhere use sentinels to avoid rebuilding when we can't compute the 
diff --git a/com.oracle.truffle.r.native/fficall/Makefile b/com.oracle.truffle.r.native/fficall/Makefile
index 68f128ec2b78f4fc076992505b5961a2562c2ce9..26af0d4dc33b222419a910f1a2cf9138b41ac76f 100644
--- a/com.oracle.truffle.r.native/fficall/Makefile
+++ b/com.oracle.truffle.r.native/fficall/Makefile
@@ -39,8 +39,6 @@ R_LIBNAME := libR$(DYLIB_EXT)
 R_LIB := $(FASTR_LIB_DIR)/$(R_LIBNAME)
 JNIBOOT_LIBNAME := libjniboot$(DYLIB_EXT)
 JNIBOOT_LIB := $(FASTR_LIB_DIR)/$(JNIBOOT_LIBNAME)
-CACCESS_LIBNAME := libcaccess$(DYLIB_EXT)
-CACCESS_LIB := $(FASTR_LIB_DIR)/$(CACCESS_LIBNAME)
 
 ifeq ($(OS_NAME), Darwin)
 VERSION_FLAGS := -current_version $(R_VERSION) -compatibility_version $(R_VERSION)
@@ -61,11 +59,13 @@ ifeq ($(FASTR_RFFI),managed)
 else
 ifeq ($(OS_NAME),Darwin)
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) -Wl,-rpath,@loader_path/ -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack  -lpcre -lz $(VERSION_FLAGS)
+ifneq ($(FASTR_RFFI),llvm)	
 	install_name_tool -change libRblas.dylib @rpath/libRblas.dylib $(R_LIB)
 	install_name_tool -change libRlapack.dylib @rpath/libRlapack.dylib $(R_LIB)
 	install_name_tool -id @rpath/libR.dylib $(R_LIB)
 # check if we captured libpcre/libz, rpath those in libR
 	mx rupdatelib $(FASTR_LIB_DIR)
+endif
 else
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) $(shell echo $(PKG_LDFLAGS_OVERRIDE)) -Wl,-rpath,'$$ORIGIN' -o $(R_LIB) $(wildcard lib/*.o) -L$(FASTR_LIB_DIR) -lRblas -lRlapack  -lpcre -lz
 endif
@@ -79,6 +79,7 @@ ifeq ($(FASTR_RFFI),nfi)
 fficall.done: common.done
 	$(MAKE) -C src/truffle_nfi all
 	touch fficall.done
+
 else
 ifeq ($(FASTR_RFFI),llvm)
 fficall.done: common.done
@@ -88,6 +89,7 @@ else
 ifeq ($(FASTR_RFFI),jni)
 fficall.done: common.done $(JNIBOOT_LIB)
 	$(MAKE) -C src/jni all
+	touch fficall.done
 
 jniboot.done:
 	$(MAKE) -C src/jniboot all
@@ -96,24 +98,20 @@ jniboot.done:
 $(JNIBOOT_LIB): jniboot.done
 	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(JNIBOOT_LIB) src/jniboot/jniboot.o $(VERSION_FLAGS)
 ifeq ($(OS_NAME),Darwin)
+ifneq ($(FASTR_RFFI),llvm)	
 	install_name_tool -id @rpath/libjniboot.dylib $(JNIBOOT_LIB)
 endif
+endif
 else
 	$(error unknown value for FASTR_RFFI)
-endif
-	touch fficall.done
-endif
-endif
-endif
+endif #jni
+endif #llvm
+endif #nfi
+endif #managed
 
 common.done:
 	$(MAKE) -C src/common all	
 
-$(CACCESS_LIB): src/caccess/caccess.o
-	$(DYLIB_LD) $(DYLIB_LDFLAGS) -o $(CACCESS_LIB) src/caccess/caccess.o $(VERSION_FLAGS)
-ifeq ($(OS_NAME),Darwin)
-	install_name_tool -id @rpath/libcaccess.dylib $(CACCESS_LIB)
-endif
 
 clean:
 	$(MAKE) -C src/common clean
@@ -128,6 +126,5 @@ endif
 endif
 	rm -rf $(R_LIB)
 	rm -rf $(JNIBOOT_LIB)
-	rm -rf $(CACCESS_LIB)
 	rm -rf fficall.done
 
diff --git a/com.oracle.truffle.r.native/fficall/src/common/Makefile b/com.oracle.truffle.r.native/fficall/src/common/Makefile
index da61c6bf96907dd3197e0c9b1756110d79660779..ac09cf124f3b7d650c040d45e265d90054c49b43 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/Makefile
+++ b/com.oracle.truffle.r.native/fficall/src/common/Makefile
@@ -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
@@ -25,6 +25,7 @@
 
 ifneq ($(MAKECMDGOALS),clean)
 include $(FASTR_NATIVE_DIR)/platform.mk
+
 endif
 
 .PHONY: all clean
@@ -34,8 +35,12 @@ OBJ = ../../lib
 
 GNUR_APPL_C_FILES = pretty.c interv.c
 GNUR_APPL_SRC = $(GNUR_HOME)/src/appl
-# the Fortran sources are not recompiled, just copied
-GNUR_APPL_F_OBJECTS := $(wildcard $(GNUR_APPL_SRC)/d*.o $(GNUR_APPL_SRC)/d*.ll)
+# the Fortran sources are not recompiled (except for LLVM), just copied
+ifneq ($(FASTR_RFFI),llvm)	
+GNUR_APPL_F_OBJECTS := $(wildcard $(GNUR_APPL_SRC)/d*.o)
+else
+GNUR_APPL_F_OBJECTS :=
+endif
 
 GNUR_MAIN_C_FILES = colors.c devices.c engine.c format.c graphics.c plot.c plot3d.c plotmath.c rlocale.c sort.c
 GNUR_MAIN_SRC = $(GNUR_HOME)/src/main
@@ -64,7 +69,9 @@ endif
 all: Makefile $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(OBJ)/copy_appl_objects
 
 $(OBJ)/copy_appl_objects: $(GNUR_APPL_F_OBJECTS)
+ifneq ($(FASTR_RFFI),llvm)
 	cp $(GNUR_APPL_F_OBJECTS) $(OBJ)
+endif
 	touch $(OBJ)/copy_appl_objects
 
 $(C_OBJECTS): | $(OBJ)
diff --git a/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c b/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
index 184f0869edeb7e2a760cdf6364a5f9242211d572..4d6ac072c5ba151c2f0ca47ad22df74a74ad5413 100644
--- a/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c
@@ -35,7 +35,7 @@ INLINE_FUN R_len_t length(SEXP s)
     int i;
     switch (TYPEOF(s)) {
     case NILSXP:
-	return 0;
+        return 0;
     case LGLSXP:
     case INTSXP:
     case REALSXP:
@@ -45,20 +45,15 @@ INLINE_FUN R_len_t length(SEXP s)
     case VECSXP:
     case EXPRSXP:
     case RAWSXP:
-	return LENGTH(s);
-    case LISTSXP:
-    case LANGSXP:
     case DOTSXP:
-	i = 0;
-	while (s != NULL && s != R_NilValue) {
-	    i++;
-	    s = CDR(s);
-	}
-	return i;
     case ENVSXP:
-	return Rf_envlength(s);
+    case LISTSXP:
+    case LANGSXP:
+        // Note: all these types should have specialization in MiscNodes$LENGTHNode
+        return LENGTH(s);
     default:
-	return 1;
+        // e.g. SYMSXP (symbol), CLOSXP (closure)
+        return 1;
     }
 }
 
@@ -67,7 +62,7 @@ INLINE_FUN R_xlen_t xlength(SEXP s)
     int i;
     switch (TYPEOF(s)) {
     case NILSXP:
-	return 0;
+        return 0;
     case LGLSXP:
     case INTSXP:
     case REALSXP:
@@ -77,20 +72,13 @@ INLINE_FUN R_xlen_t xlength(SEXP s)
     case VECSXP:
     case EXPRSXP:
     case RAWSXP:
-	return XLENGTH(s);
-    case LISTSXP:
-    case LANGSXP:
     case DOTSXP:
-	i = 0;
-	while (s != NULL && s != R_NilValue) {
-	    i++;
-	    s = CDR(s);
-	}
-	return i;
     case ENVSXP:
-	return Rf_envlength(s);
+    case LISTSXP:
+    case LANGSXP:
+        return XLENGTH(s);
     default:
-	return 1;
+        return 1;
     }
 }
 
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
similarity index 97%
rename from com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
rename to com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
index 94d50549cc5151b44e1bb62db7633a4b59258ddf..44b8bf7102dac472baa11a2dbcc4d41c3aa2842f 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacks.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcalls.h
@@ -23,9 +23,9 @@
 #ifndef CALLBACKS_H
 #define CALLBACKS_H
 
-#include "rffi_callbacksindex.h"
+#include "rffi_upcallsindex.h"
 
-extern void* callbacks[];
+extern void* *callbacks;
 
 // This is the complete set , including those not yet implemented
 
@@ -270,13 +270,19 @@ typedef SEXP (*call_R_BaseNamespace)();
 typedef SEXP (*call_R_MethodsNamespace)();
 typedef SEXP (*call_R_GlobalEnv)();
 typedef SEXP (*call_R_NamespaceRegistry)();
-typedef SEXP (*call_R_Interactive)();
+typedef int (*call_R_Interactive)();
 typedef SEXP (*call_R_GlobalContext)();
 typedef SEXP (*call_R_CHAR)(SEXP x);
 typedef char *(*call_R_HomeDir)();
 typedef void (*call_R_CleanUp)(int sa, int status, int runlast);
 typedef void (*call_Rf_gsetVar)(SEXP symbol, SEXP value, SEXP rho);
 typedef double (*call_unif_rand)();
+typedef double (*call_Rf_qunif)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_dunif)(double a, double b, double c, int d);
+typedef double (*call_Rf_punif)(double a, double b, double c, int d, int e);
+typedef double (*call_Rf_runif)(double x, double y);
+
+typedef SEXP (*call_getvar)();
 
 #endif
 
diff --git a/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
new file mode 100644
index 0000000000000000000000000000000000000000..f17d3f1c1952664e5635140c1d46dbd2461cf3a9
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h
@@ -0,0 +1,150 @@
+// GENERATED; DO NOT EDIT
+#ifndef RFFI_UPCALLSINDEX_H
+#define RFFI_UPCALLSINDEX_H
+
+#define ATTRIB_x 0
+#define CADDR_x 1
+#define CADR_x 2
+#define CAR_x 3
+#define CDDR_x 4
+#define CDR_x 5
+#define DUPLICATE_ATTRIB_x 6
+#define ENCLOS_x 7
+#define GetRNGstate_x 8
+#define INTEGER_x 9
+#define IS_S4_OBJECT_x 10
+#define LENGTH_x 11
+#define LOGICAL_x 12
+#define NAMED_x 13
+#define OBJECT_x 14
+#define PRCODE_x 15
+#define PRENV_x 16
+#define PRINTNAME_x 17
+#define PRSEEN_x 18
+#define PRVALUE_x 19
+#define PutRNGstate_x 20
+#define RAW_x 21
+#define RDEBUG_x 22
+#define REAL_x 23
+#define RSTEP_x 24
+#define R_BaseEnv_x 25
+#define R_BaseNamespace_x 26
+#define R_BindingIsLocked_x 27
+#define R_CHAR_x 28
+#define R_CleanUp_x 29
+#define R_ExternalPtrAddr_x 30
+#define R_ExternalPtrProtected_x 31
+#define R_ExternalPtrTag_x 32
+#define R_FindNamespace_x 33
+#define R_GetConnection_x 34
+#define R_GlobalContext_x 35
+#define R_GlobalEnv_x 36
+#define R_Home_x 37
+#define R_HomeDir_x 38
+#define R_Interactive_x 39
+#define R_MakeExternalPtr_x 40
+#define R_MethodsNamespace_x 41
+#define R_NamespaceRegistry_x 42
+#define R_NewHashedEnv_x 43
+#define R_ParseVector_x 44
+#define R_PromiseExpr_x 45
+#define R_ReadConnection_x 46
+#define R_SetExternalPtrAddr_x 47
+#define R_SetExternalPtrProtected_x 48
+#define R_SetExternalPtrTag_x 49
+#define R_TempDir_x 50
+#define R_ToplevelExec_x 51
+#define R_WriteConnection_x 52
+#define R_compute_identical_x 53
+#define R_do_MAKE_CLASS_x 54
+#define R_do_new_object_x 55
+#define R_do_slot_x 56
+#define R_do_slot_assign_x 57
+#define R_getContextCall_x 58
+#define R_getContextEnv_x 59
+#define R_getContextFun_x 60
+#define R_getContextSrcRef_x 61
+#define R_getGlobalFunctionContext_x 62
+#define R_getParentFunctionContext_x 63
+#define R_insideBrowser_x 64
+#define R_isEqual_x 65
+#define R_isGlobal_x 66
+#define R_lsInternal3_x 67
+#define R_new_custom_connection_x 68
+#define R_tryEval_x 69
+#define Rf_GetOption1_x 70
+#define Rf_PairToVectorList_x 71
+#define Rf_ScalarDouble_x 72
+#define Rf_ScalarInteger_x 73
+#define Rf_ScalarLogical_x 74
+#define Rf_ScalarString_x 75
+#define Rf_allocArray_x 76
+#define Rf_allocMatrix_x 77
+#define Rf_allocVector_x 78
+#define Rf_any_duplicated_x 79
+#define Rf_asChar_x 80
+#define Rf_asInteger_x 81
+#define Rf_asLogical_x 82
+#define Rf_asReal_x 83
+#define Rf_classgets_x 84
+#define Rf_coerceVector_x 85
+#define Rf_cons_x 86
+#define Rf_copyListMatrix_x 87
+#define Rf_copyMatrix_x 88
+#define Rf_defineVar_x 89
+#define Rf_dunif_x 90
+#define Rf_duplicate_x 91
+#define Rf_error_x 92
+#define Rf_errorcall_x 93
+#define Rf_eval_x 94
+#define Rf_findFun_x 95
+#define Rf_findVar_x 96
+#define Rf_findVarInFrame_x 97
+#define Rf_findVarInFrame3_x 98
+#define Rf_getAttrib_x 99
+#define Rf_gsetVar_x 100
+#define Rf_inherits_x 101
+#define Rf_install_x 102
+#define Rf_installChar_x 103
+#define Rf_isNull_x 104
+#define Rf_isString_x 105
+#define Rf_lengthgets_x 106
+#define Rf_mkCharLenCE_x 107
+#define Rf_namesgets_x 108
+#define Rf_ncols_x 109
+#define Rf_nrows_x 110
+#define Rf_punif_x 111
+#define Rf_qunif_x 112
+#define Rf_runif_x 113
+#define Rf_setAttrib_x 114
+#define Rf_str2type_x 115
+#define Rf_warning_x 116
+#define Rf_warningcall_x 117
+#define Rprintf_x 118
+#define SETCADR_x 119
+#define SETCAR_x 120
+#define SETCDR_x 121
+#define SET_NAMED_FASTR_x 122
+#define SET_RDEBUG_x 123
+#define SET_RSTEP_x 124
+#define SET_S4_OBJECT_x 125
+#define SET_STRING_ELT_x 126
+#define SET_SYMVALUE_x 127
+#define SET_TAG_x 128
+#define SET_TYPEOF_FASTR_x 129
+#define SET_VECTOR_ELT_x 130
+#define STRING_ELT_x 131
+#define SYMVALUE_x 132
+#define TAG_x 133
+#define TYPEOF_x 134
+#define UNSET_S4_OBJECT_x 135
+#define VECTOR_ELT_x 136
+#define getConnectionClassString_x 137
+#define getOpenModeString_x 138
+#define getSummaryDescription_x 139
+#define isSeekable_x 140
+#define unif_rand_x 141
+
+#define UPCALLS_TABLE_SIZE 142
+
+#endif // RFFI_UPCALLSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/variables.h b/com.oracle.truffle.r.native/fficall/src/common/rffi_variablesindex.h
similarity index 52%
rename from com.oracle.truffle.r.native/fficall/src/truffle_llvm/variables.h
rename to com.oracle.truffle.r.native/fficall/src/common/rffi_variablesindex.h
index 3a245b1fa929a70ebea8719ae90c36704da0bc17..9e7702e4e7e87601e15c2179fdf493bbceda6ffc 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/variables.h
+++ b/com.oracle.truffle.r.native/fficall/src/common/rffi_variablesindex.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -20,6 +20,9 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#ifndef RFFI_VARIABLESINDEX_H
+#define RFFI_VARIABLESINDEX_H
+
 #define R_Home_x 0
 #define R_TempDir_x 1
 #define R_NilValue_x 2
@@ -34,42 +37,44 @@
 #define R_Bracket2Symbol_x 11
 #define R_BracketSymbol_x 12
 #define R_BraceSymbol_x 13
-#define R_ClassSymbol_x 14
-#define R_DeviceSymbol_x 15
-#define R_DevicesSymbol_x 16
-#define R_DimNamesSymbol_x 17
-#define R_DimSymbol_x 18
-#define R_DollarSymbol_x 19
-#define R_DotsSymbol_x 20
-#define R_DropSymbol_x 21
-#define R_LastvalueSymbol_x 22
-#define R_LevelsSymbol_x 23
-#define R_ModeSymbol_x 24
-#define R_NameSymbol_x 25
-#define R_NamesSymbol_x 26
-#define R_NaRmSymbol_x 27
-#define R_PackageSymbol_x 28
-#define R_QuoteSymbol_x 29
-#define R_RowNamesSymbol_x 30
-#define R_SeedsSymbol_x 31
-#define R_SourceSymbol_x 32
-#define R_TspSymbol_x 33
-#define R_dot_defined_x 34
-#define R_dot_Method_x 35
-#define R_dot_target_x 36
-#define R_SrcrefSymbol_x 37
-#define R_SrcfileSymbol_x 38
-#define R_NaString_x 39
-#define R_NaN_x 40
-#define R_PosInf_x 41
-#define R_NegInf_x 42
-#define R_NaReal_x 43
-#define R_NaInt_x 44
-#define R_BlankString_x 45
-#define R_BlankScalarString_x 46
-#define R_TrueValue_x 47
-#define R_FalseValue_x 48
-#define R_LogicalNAValue_x 49
-#define R_BaseSymbol_x 50
-#define R_NamespaceEnvSymbol_x 51
-#define R_RestartToken_x 52
+#define R_DoubleColonSymbol_x 14
+#define R_ClassSymbol_x 15
+#define R_DeviceSymbol_x 16
+#define R_DevicesSymbol_x 17
+#define R_DimNamesSymbol_x 18
+#define R_DimSymbol_x 19
+#define R_DollarSymbol_x 20
+#define R_DotsSymbol_x 21
+#define R_DropSymbol_x 22
+#define R_LastvalueSymbol_x 23
+#define R_LevelsSymbol_x 24
+#define R_ModeSymbol_x 25
+#define R_NameSymbol_x 26
+#define R_NamesSymbol_x 27
+#define R_NaRmSymbol_x 28
+#define R_PackageSymbol_x 29
+#define R_QuoteSymbol_x 30
+#define R_RowNamesSymbol_x 31
+#define R_SeedsSymbol_x 32
+#define R_SourceSymbol_x 33
+#define R_TspSymbol_x 34
+#define R_dot_defined_x 35
+#define R_dot_Method_x 36
+#define R_dot_target_x 37
+#define R_SrcrefSymbol_x 38
+#define R_SrcfileSymbol_x 39
+#define R_NaString_x 40
+#define R_NaN_x 41
+#define R_PosInf_x 42
+#define R_NegInf_x 43
+#define R_NaReal_x 44
+#define R_NaInt_x 45
+#define R_BlankString_x 46
+#define R_BlankScalarString_x 47
+#define R_BaseSymbol_x 48
+#define R_NamespaceEnvSymbol_x 49
+#define R_RestartToken_x 50
+
+#define VARIABLES_TABLE_SIZE 50
+
+#endif // RFFI_VARIABLESINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
index 5a7fbf2b020fc89449638892db907504afa229fc..f642af5f5bfc1ba2fcc4e0023bb6fcd77010d9de 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Connections.c
@@ -59,10 +59,10 @@ static void setFd(Rconnection con, jint fd) {
 
 void init_connections(JNIEnv *env) {
 	/* int readConn(int, byte[]) */
-	readConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ReadConnection", "(I[B)I", 0);
+	readConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ReadConnection", "(ILjava/lang/Object;)I", 0);
 
 	/* int writeConn(int, byte[]) */
-	writeConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_WriteConnection", "(I[B)I", 0);
+	writeConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_WriteConnection", "(ILjava/lang/Object;)I", 0);
 
 	/* RConnection getConnection(int) */
 	getConnMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_GetConnection", "(I)Ljava/lang/Object;", 0);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
index 723290cfea319d97cce90c45762f13087bd4ed28..c6509c52bb13b0824bd4ce330cec8dda3b45c8c2 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Parse.c
@@ -31,7 +31,7 @@ static jfieldID parseExprFieldID;
 
 void init_parse(JNIEnv *env) {
 	parseMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ParseVector", "(Ljava/lang/Object;ILjava/lang/Object;)Ljava/lang/Object;", 0);
-	parseResultClass = checkFindClass(env, "com/oracle/truffle/r/nodes/ffi/ParseResult");
+	parseResultClass = checkFindClass(env, "com/oracle/truffle/r/ffi/impl/common/ParseResult");
 	parseStatusFieldID = checkGetFieldID(env, parseResultClass, "parseStatus", "I", 0);
 	parseExprFieldID = checkGetFieldID(env, parseResultClass, "expr", "Ljava/lang/Object;", 0);
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Random.c b/com.oracle.truffle.r.native/fficall/src/jni/Random.c
index 4c958521f14747b05fe32b15575b49b1026a53bb..59276104123776465262e2ad4a4309b4f6732bb0 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Random.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Random.c
@@ -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
@@ -27,8 +27,8 @@ static jmethodID PutRNGstate_MethodID;
 static jmethodID UnifRand_MethodID;
 
 void init_random(JNIEnv *env) {
-	GetRNGstate_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "GetRNGstate", "()V", 0);
-	PutRNGstate_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "PutRNGstate", "()V", 0);
+	GetRNGstate_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "GetRNGstate", "()I", 0);
+	PutRNGstate_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "PutRNGstate", "()I", 0);
 	UnifRand_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "unif_rand", "()D", 0);
 }
 
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 88a5b6e9b3ba8e93b958ce16d0e495bf87d60b1d..df4334d68d32c0db6f1bb09aa9ad22d112762a8b 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
@@ -31,7 +31,7 @@ static jmethodID findSymbolID;
 
 void init_dynload(JNIEnv *env) {
     DLLClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL");
-    JNI_PkgInitClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/JNI_PkgInit");
+    JNI_PkgInitClass = checkFindClass(env, "com/oracle/truffle/r/ffi/impl/jni/JNI_PkgInit");
     DotSymbolClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL$DotSymbol");
     RegisteredNativeSymbolClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/DLL$RegisteredNativeSymbol");
 
@@ -88,7 +88,7 @@ void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr) {
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PkgInit_setSymbol(JNIEnv *env, jclass c, jint nstOrd, jlong routinesAddr, jint index) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1PkgInit_setSymbol(JNIEnv *env, jclass c, jint nstOrd, jlong routinesAddr, jint index) {
 	const char *name;
 	long fun;
 	int numArgs;
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
index c38eab99ff203ac76050c0cbcb3e6c973662168d..3442b2b89d5c0d098153548c6d73e581e29658a0 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
@@ -307,7 +307,7 @@ void uR_Busy(int x) {
 
 void uR_CleanUp(SA_TYPE x, int y, int z) {
 	JNIEnv *jniEnv = getEnv();
-	jmethodID methodID = checkGetMethodID(jniEnv, UpCallsRFFIClass, "R_CleanUp", "(III)V", 1);
+	jmethodID methodID = checkGetMethodID(jniEnv, UpCallsRFFIClass, "R_CleanUp", "(III)I", 1);
 	(*jniEnv)->CallStaticVoidMethod(jniEnv, UpCallsRFFIClass, methodID, x, y, z);
 }
 
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
index 1f63778f8fcd6e079a470f5f67b58bb504920c18..87605b88e859b232b52c5273435005c89ddd3549 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rinternals.c
@@ -49,6 +49,7 @@ static jmethodID Rf_defineVarMethodID;
 static jmethodID Rf_findVarMethodID;
 static jmethodID Rf_findVarInFrameMethodID;
 static jmethodID Rf_findVarInFrame3MethodID;
+static jmethodID ATTRIBMethodID;
 static jmethodID Rf_getAttribMethodID;
 static jmethodID Rf_setAttribMethodID;
 static jmethodID Rf_isStringMethodID;
@@ -56,6 +57,7 @@ static jmethodID Rf_isNullMethodID;
 static jmethodID Rf_installCharMethodID;
 static jmethodID Rf_installMethodID;
 static jmethodID Rf_warningcallMethodID;
+static jmethodID Rf_errorcallMethodID;
 static jmethodID Rf_warningMethodID;
 static jmethodID Rf_errorMethodID;
 static jmethodID R_NewHashedEnvMethodID;
@@ -95,6 +97,7 @@ static jmethodID LENGTH_MethodID;
 static jmethodID R_do_slot_MethodID;
 static jmethodID R_do_slot_assign_MethodID;
 static jmethodID R_MethodsNamespaceMethodID;
+static jmethodID Rf_str2type_MethodID;
 static jmethodID Rf_asIntegerMethodID;
 static jmethodID Rf_asRealMethodID;
 static jmethodID Rf_asCharMethodID;
@@ -105,6 +108,7 @@ static jmethodID Rf_PairToVectorListMethodID;
 static jmethodID gnuRCodeForObjectMethodID;
 static jmethodID NAMED_MethodID;
 static jmethodID SET_TYPEOF_FASTR_MethodID;
+static jmethodID SET_NAMED_FASTR_MethodID;
 static jmethodID TYPEOF_MethodID;
 static jmethodID OBJECT_MethodID;
 static jmethodID DUPLICATE_ATTRIB_MethodID;
@@ -142,6 +146,7 @@ static jmethodID Rf_copyListMatrixMethodID;
 static jmethodID Rf_copyMatrixMethodID;
 static jmethodID Rf_nrowsMethodID;
 static jmethodID Rf_ncolsMethodID;
+static jmethodID Rf_namesgetsMethodID;
 
 static jclass CharSXPWrapperClass;
 jclass JNIUpCallsRFFIImplClass;
@@ -156,33 +161,35 @@ void init_internals(JNIEnv *env) {
 	Rf_consMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_cons", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_evalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_eval", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_findFunMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findFun", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	Rf_defineVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_defineVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 0);
+	Rf_defineVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_defineVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	Rf_findVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVar", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_findVarInFrameMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVarInFrame", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_findVarInFrame3MethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_findVarInFrame3", "(Ljava/lang/Object;Ljava/lang/Object;I)Ljava/lang/Object;", 0);
+	ATTRIBMethodID = checkGetMethodID(env, UpCallsRFFIClass, "ATTRIB", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_getAttribMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_getAttrib", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	Rf_setAttribMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_setAttrib", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 0);
+	Rf_setAttribMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_setAttrib", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	Rf_isStringMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isString", "(Ljava/lang/Object;)I", 0);
 	Rf_isNullMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_isNull", "(Ljava/lang/Object;)I", 0);
 	Rf_installMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_install", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_installCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_installChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	Rf_warningMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warning", "(Ljava/lang/Object;)V", 0);
-	Rf_warningcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warningcall", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
-	Rf_errorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_error", "(Ljava/lang/Object;)V", 0);
-	Rf_allocVectorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocVector", "(II)Ljava/lang/Object;", 0);
+	Rf_warningMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warning", "(Ljava/lang/Object;)I", 0);
+	Rf_warningcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_warningcall", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
+	Rf_errorcallMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_errorcall", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
+	Rf_errorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_error", "(Ljava/lang/Object;)I", 0);
+	Rf_allocVectorMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocVector", "(IJ)Ljava/lang/Object;", 0);
 	Rf_allocMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocMatrix", "(III)Ljava/lang/Object;", 0);
 	Rf_allocArrayMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_allocArray", "(ILjava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_duplicateMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_duplicate", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
-	Rf_any_duplicatedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_any_duplicated", "(Ljava/lang/Object;I)I", 0);
-	R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Lcom/oracle/truffle/r/runtime/env/REnvironment;Ljava/lang/Object;)Lcom/oracle/truffle/r/runtime/env/REnvironment;", 0);
+	Rf_any_duplicatedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_any_duplicated", "(Ljava/lang/Object;I)J", 0);
+	R_NewHashedEnvMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_NewHashedEnv", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	Rf_classgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_classgets", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	RprintfMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rprintf", "(Ljava/lang/Object;)V", 0);
+	RprintfMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rprintf", "(Ljava/lang/Object;)I", 0);
 	R_do_MAKE_CLASS_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_MAKE_CLASS", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_do_new_object_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_new_object", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_FindNamespaceMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_FindNamespace", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_BindingIsLockedID = checkGetMethodID(env, UpCallsRFFIClass, "R_BindingIsLocked", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	Rf_GetOption1MethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_GetOption1", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	Rf_gsetVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_gsetVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)V", 0);
+	Rf_gsetVarMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_gsetVar", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	Rf_inheritsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_inherits", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	Rf_lengthgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_lengthgets", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
 //	Rf_rPsortMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_rPsort", "(Lcom/oracle/truffle/r/runtime/data/RDoubleVector;II)", 0);
@@ -199,19 +206,20 @@ void init_internals(JNIEnv *env) {
 	SETCDR_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SETCDR", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	SETCADR_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SETCADR", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	SYMVALUE_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SYMVALUE", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	SET_SYMVALUE_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_SYMVALUE", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
-	SET_STRING_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_STRING_ELT", "(Ljava/lang/Object;ILjava/lang/Object;)V", 0);
-	SET_VECTOR_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_VECTOR_ELT", "(Ljava/lang/Object;ILjava/lang/Object;)V", 0);
+	SET_SYMVALUE_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_SYMVALUE", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
+	SET_STRING_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_STRING_ELT", "(Ljava/lang/Object;JLjava/lang/Object;)I", 0);
+	SET_VECTOR_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_VECTOR_ELT", "(Ljava/lang/Object;JLjava/lang/Object;)I", 0);
 	RAW_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "RAW", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	REAL_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "REAL", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	LOGICAL_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "LOGICAL", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	INTEGER_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "INTEGER", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	STRING_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "STRING_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
-	VECTOR_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "VECTOR_ELT", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
+	STRING_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "STRING_ELT", "(Ljava/lang/Object;J)Ljava/lang/Object;", 0);
+	VECTOR_ELT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "VECTOR_ELT", "(Ljava/lang/Object;J)Ljava/lang/Object;", 0);
 	LENGTH_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "LENGTH", "(Ljava/lang/Object;)I", 0);
 	R_do_slot_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_slot", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_do_slot_assign_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_do_slot_assign", "(Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_MethodsNamespaceMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_MethodsNamespace", "()Ljava/lang/Object;", 0);
+	Rf_str2type_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_str2type", "(Ljava/lang/Object;)I", 0);
 	Rf_asIntegerMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asInteger", "(Ljava/lang/Object;)I", 0);
 	Rf_asRealMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asReal", "(Ljava/lang/Object;)D", 0);
 	Rf_asCharMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_asChar", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
@@ -221,17 +229,18 @@ void init_internals(JNIEnv *env) {
 	Rf_PairToVectorListMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_PairToVectorList", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	NAMED_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "NAMED", "(Ljava/lang/Object;)I", 0);
 	SET_TYPEOF_FASTR_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_TYPEOF_FASTR", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
+	SET_NAMED_FASTR_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_NAMED_FASTR", "(Ljava/lang/Object;I)Ljava/lang/Object;", 0);
 	TYPEOF_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "TYPEOF", "(Ljava/lang/Object;)I", 0);
 	OBJECT_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "OBJECT", "(Ljava/lang/Object;)I", 0);
-	DUPLICATE_ATTRIB_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "DUPLICATE_ATTRIB", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
+	DUPLICATE_ATTRIB_MethodID = checkGetMethodID(env, UpCallsRFFIClass, "DUPLICATE_ATTRIB", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 	IS_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "IS_S4_OBJECT", "(Ljava/lang/Object;)I", 0);
-	SET_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_S4_OBJECT", "(Ljava/lang/Object;)V", 0);
-	UNSET_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "UNSET_S4_OBJECT", "(Ljava/lang/Object;)V", 0);
-	R_tryEvalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_tryEval", "(Ljava/lang/Object;Ljava/lang/Object;Z)Ljava/lang/Object;", 0);
+	SET_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_S4_OBJECT", "(Ljava/lang/Object;)I", 0);
+	UNSET_S4_OBJECTMethodID = checkGetMethodID(env, UpCallsRFFIClass, "UNSET_S4_OBJECT", "(Ljava/lang/Object;)I", 0);
+	R_tryEvalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_tryEval", "(Ljava/lang/Object;Ljava/lang/Object;I)Ljava/lang/Object;", 0);
 	RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "RDEBUG", "(Ljava/lang/Object;)I", 0);
-	SET_RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_RDEBUG", "(Ljava/lang/Object;I)V", 0);
+	SET_RDEBUGMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_RDEBUG", "(Ljava/lang/Object;I)I", 0);
 	RSTEPMethodID = checkGetMethodID(env, UpCallsRFFIClass, "RSTEP", "(Ljava/lang/Object;)I", 0);
-	SET_RSTEPMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_RSTEP", "(Ljava/lang/Object;I)V", 0);
+	SET_RSTEPMethodID = checkGetMethodID(env, UpCallsRFFIClass, "SET_RSTEP", "(Ljava/lang/Object;I)I", 0);
 	ENCLOSMethodID = checkGetMethodID(env, UpCallsRFFIClass, "ENCLOS", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	PRVALUEMethodID = checkGetMethodID(env, UpCallsRFFIClass, "PRVALUE", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_lsInternal3MethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_lsInternal3", "(Ljava/lang/Object;II)Ljava/lang/Object;", 0);
@@ -246,18 +255,19 @@ void init_internals(JNIEnv *env) {
 	R_ExternalPtrAddrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrAddr", "(Ljava/lang/Object;)J", 0);
 	R_ExternalPtrTagMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrTag", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
 	R_ExternalPtrProtectedMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_ExternalPtrProtected", "(Ljava/lang/Object;)Ljava/lang/Object;", 0);
-	R_SetExternalPtrAddrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrAddr", "(Ljava/lang/Object;J)V", 0);
-	R_SetExternalPtrTagMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrTag", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
-	R_SetExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrProtected", "(Ljava/lang/Object;Ljava/lang/Object;)V", 0);
+	R_SetExternalPtrAddrMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrAddr", "(Ljava/lang/Object;J)I", 0);
+	R_SetExternalPtrTagMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrTag", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
+	R_SetExternalPtrProtMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_SetExternalPtrProtected", "(Ljava/lang/Object;Ljava/lang/Object;)I", 0);
 
     R_compute_identicalMethodID = checkGetMethodID(env, UpCallsRFFIClass, "R_compute_identical", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 0);
-    Rf_copyListMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyListMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)V", 0);
-    Rf_copyMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)V", 0);
+    Rf_copyListMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyListMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 0);
+    Rf_copyMatrixMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_copyMatrix", "(Ljava/lang/Object;Ljava/lang/Object;I)I", 0);
     Rf_nrowsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_nrows", "(Ljava/lang/Object;)I", 0);
     Rf_ncolsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_ncols", "(Ljava/lang/Object;)I", 0);
+    Rf_namesgetsMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_namesgets", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", 0);
 
     // static JNI-specific methods
-	JNIUpCallsRFFIImplClass = checkFindClass(env, "com/oracle/truffle/r/runtime/ffi/jni/JNIUpCallsRFFIImpl");
+	JNIUpCallsRFFIImplClass = checkFindClass(env, "com/oracle/truffle/r/ffi/impl/jni/JNIUpCallsRFFIImpl");
 	restoreHandlerStacksMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "R_ToplevelExecRestoreErrorHandlerStacks", "(Ljava/lang/Object;)V", 1);
     setCompleteMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "setComplete", "(Ljava/lang/Object;Z)V", 1);
 	logNotCharSXPWrapperMethodID = checkGetMethodID(env, JNIUpCallsRFFIImplClass, "logNotCharSXPWrapper", "(Ljava/lang/Object;)V", 1);
@@ -356,8 +366,9 @@ SEXP Rf_dimnamesgets(SEXP x, SEXP y) {
 SEXP Rf_eval(SEXP expr, SEXP env) {
 	TRACE(TARGpp, expr, env);
     JNIEnv *thisenv = getEnv();
-    updateNativeArrays(thisenv);
+    updateJObjects(thisenv);
     SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_evalMethodID, expr, env);
+    updateNativeArrays(thisenv);
     return checkRef(thisenv, result);
 }
 
@@ -399,6 +410,7 @@ SEXP Rf_getAttrib(SEXP vec, SEXP name) {
 SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) {
 	TRACE(TARGppp, vec,name, val);
 	JNIEnv *thisenv = getEnv();
+	updateJObject(thisenv, val);
 	(*thisenv)->CallVoidMethod(thisenv, UpCallsRFFIObject, Rf_setAttribMethodID, vec, name, val);
 	return val;
 }
@@ -597,7 +609,14 @@ void Rf_error(const char *format, ...) {
 }
 
 void Rf_errorcall(SEXP x, const char *format, ...) {
-	unimplemented("Rf_errorcall");
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	JNIEnv *thisenv = getEnv();
+	jstring string = (*thisenv)->NewStringUTF(thisenv, buf);
+	(*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_errorcallMethodID, x, string);
 }
 
 void Rf_warningcall(SEXP x, const char *format, ...) {
@@ -724,7 +743,9 @@ SEXP R_lsInternal3(SEXP env, Rboolean all, Rboolean sorted) {
 }
 
 SEXP Rf_namesgets(SEXP x, SEXP y) {
-	return unimplemented("Rf_namesgets");
+	JNIEnv *thisenv = getEnv();
+	SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_namesgetsMethodID, x, y);
+	return checkRef(thisenv, result);
 }
 
 SEXP GetOption1(SEXP tag)
@@ -769,13 +790,11 @@ SEXP CDR(SEXP e) {
 }
 
 SEXP CAAR(SEXP e) {
-    unimplemented("CAAR");
-    return NULL;
+    return CAR(CAR(e));
 }
 
 SEXP CDAR(SEXP e) {
-    unimplemented("CDAR");
-    return NULL;
+    return CDR(CAR(e));
 }
 
 SEXP CADR(SEXP e) {
@@ -1205,9 +1224,11 @@ int TYPEOF(SEXP x) {
 	return (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, TYPEOF_MethodID, x);
 }
 
-SEXP ATTRIB(SEXP x){
-    unimplemented("ATTRIB");
-    return NULL;
+SEXP ATTRIB(SEXP x) {
+    TRACE(TARGp, x);
+    JNIEnv *thisenv = getEnv();
+    SEXP result = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, ATTRIBMethodID, x);
+    return checkRef(thisenv, result);
 }
 
 int OBJECT(SEXP x){
@@ -1245,7 +1266,8 @@ SEXP SET_TYPEOF_FASTR(SEXP x, int v){
 }
 
 void SET_NAMED(SEXP x, int v){
-    unimplemented("SET_NAMED");
+    JNIEnv *thisenv = getEnv();
+    (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, SET_NAMED_FASTR_MethodID, x, v);
 }
 
 void SET_ATTRIB(SEXP x, SEXP v){
@@ -1381,12 +1403,13 @@ SEXP Rf_asS4(SEXP x, Rboolean b, int i) {
 
 static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, jboolean silent) {
 	JNIEnv *thisenv = getEnv();
-    updateNativeArrays(thisenv);
-	jobject tryResult =  (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_tryEvalMethodID, x, y, silent);
+    updateJObjects(thisenv);
+	jobject tryResult =  (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_tryEvalMethodID, x, y, (int) silent);
 	// If tryResult is NULL, an error occurred
 	if (ErrorOccurred) {
 		*ErrorOccurred = tryResult == NULL;
 	}
+    updateNativeArrays(thisenv);
 	return checkRef(thisenv, tryResult);
 }
 
@@ -1537,6 +1560,12 @@ SEXP R_do_new_object(SEXP class_def) {
     return checkRef(thisenv, result);
 }
 
+SEXPTYPE Rf_str2type(const char *name) {
+    JNIEnv *thisenv = getEnv();
+    jstring jsName = (*thisenv)->NewStringUTF(thisenv, name);
+    return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, Rf_str2type_MethodID, jsName);
+}
+
 static SEXP jniGetMethodsNamespace() {
     JNIEnv *thisenv = getEnv();
     return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, R_MethodsNamespaceMethodID);
@@ -1546,7 +1575,7 @@ int R_check_class_etc (SEXP x, const char **valid) {
 	return R_check_class_etc_helper(x, valid, jniGetMethodsNamespace);
 }
 
-SEXP R_PreserveObject(SEXP x) {
+SEXP R_PreserveObject_FASTR(SEXP x) {
 	// convert to a JNI global ref until explicitly released
 	return createGlobalRef(getEnv(), x, 0);
 }
@@ -1574,4 +1603,3 @@ void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
     JNIEnv *thisenv = getEnv();
     (*thisenv)->CallIntMethod(thisenv, UpCallsRFFIObject, Rf_copyMatrixMethodID, s, t, byrow);
 }
-
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rmath.c b/com.oracle.truffle.r.native/fficall/src/jni/Rmath.c
index 2182b9c413902d5ac2bd03bad3fa91c6a3a896c5..400076323adf70436f97874c84e925d54fa812a7 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rmath.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rmath.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2015, 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,17 @@
  */
 #include <rffiutils.h>
 
+static jmethodID Rf_runifMethodID;
+static jmethodID Rf_punifMethodID;
+static jmethodID Rf_qunifMethodID;
+static jmethodID Rf_dunifMethodID;
+
 void init_rmath(JNIEnv *env) {
 
+	Rf_runifMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_runif", "(DD)D", 0);
+	Rf_punifMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_punif", "(DDDII)D", 0);
+	Rf_qunifMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_qunif", "(DDDII)D", 0);
+	Rf_dunifMethodID = checkGetMethodID(env, UpCallsRFFIClass, "Rf_dunif", "(DDDI)D", 0);
 }
 
 double Rf_dnorm(double a, double b, double c, int d) {
@@ -63,23 +72,27 @@ void Rf_pnorm_both(double a, double * b, double * c, int d, int e) {
 }
 
 double Rf_dunif(double a, double b, double c, int d) {
-    unimplemented("Rf_dunif");
-    return 0;
+	TRACE(TARGs, a, b);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_dunifMethodID, a, b, c, d);
 }
 
 double Rf_punif(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_punif");
-    return 0;
+	TRACE(TARGs, a, b);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_punifMethodID, a, b, c, d, e);
 }
 
 double Rf_qunif(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qunif");
-    return 0;
+	TRACE(TARGs, a, b);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_qunifMethodID, a, b, c, d, e);
 }
 
 double Rf_runif(double a, double b) {
-    unimplemented("Rf_runif");
-    return 0;
+	TRACE(TARGs, a, b);
+	JNIEnv *thisenv = getEnv();
+	return (*thisenv)->CallDoubleMethod(thisenv, UpCallsRFFIObject, Rf_runifMethodID, a, b);
 }
 
 double Rf_dgamma(double a, double b, double c, int d) {
@@ -682,8 +695,11 @@ double Rf_fprec(double a, double b) {
 }
 
 double Rf_fsign(double a, double b) {
-    unimplemented("Rf_fsign");
-    return 0;
+#ifdef IEEE_754
+    if (ISNAN(a) || ISNAN(b))
+	return a + b;
+#endif
+    return ((b >= 0) ? fabs(a) : -fabs(b));
 }
 
 double Rf_ftrunc(double a) {
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c
index bd570ec5022b2a8a4703188087a92f611583e87a..c47930bf89edfdb2e9eacd44b206bb5c8baf091e 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/appl_rffi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,9 +26,13 @@
 extern void dqrdc2_(double *x, int *ldx, int *n, int *p, double *tol, int *rank, double *qraux, int* pivot, double *work);
 extern void dqrcf_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *b, int* info);
 extern void dqrls_(double *x, int *n, int *p, double *y, int *ny, double *tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work);
+extern void dqrqty_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *qty);
+extern void dqrqy_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *qy);
+extern void dqrrsd_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *rsd);
+extern void dqrxb_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *xb);
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrdc2(JNIEnv *env, jclass c,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1RAppl_native_1dqrdc2(JNIEnv *env, jclass c,
 		jdoubleArray jx, jint ldx, jint n, jint p, jdouble tol, jintArray jrank, jdoubleArray jqraux,
 		jintArray jpivot, jdoubleArray jwork) {
 	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
@@ -45,7 +49,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrdc2(JNIEnv *env,
 }
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrcf(JNIEnv *env, jclass c,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1RAppl_native_1dqrcf(JNIEnv *env, jclass c,
 		jdoubleArray jx, jint n, jint k, jdoubleArray jqraux, jdoubleArray jy, jint ny, jdoubleArray jb, jintArray jinfo) {
 	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
 	double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL);
@@ -61,7 +65,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrcf(JNIEnv *env,
 }
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrls(JNIEnv *env, jclass c,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1RAppl_native_1dqrls(JNIEnv *env, jclass c,
 		jdoubleArray jx, int n, int p, jdoubleArray jy, int ny, double tol, jdoubleArray jb,
 		jdoubleArray jrsd, jdoubleArray jqty, jintArray jk, jintArray jjpvt, jdoubleArray jqraux, jdoubleArray jwork) {
 	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
@@ -84,3 +88,59 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1RAppl_native_1dqrls(JNIEnv *env,
 	(*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0);
 	(*env)->ReleasePrimitiveArrayCritical(env, jwork, work, 0);
 }
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1RAppl_native_1dqrqty(JNIEnv *env, jclass c,
+		jdoubleArray jx, int n, int k, jdoubleArray jqraux, jdoubleArray jy, int ny, jdoubleArray jqty) {
+	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
+	double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL);
+	double *y = (*env)->GetPrimitiveArrayCritical(env, jy, NULL);
+	double *qty = (*env)->GetPrimitiveArrayCritical(env, jqty, NULL);
+	dqrqty_(x, &n, &k, qraux, y, &ny, qty);
+	(*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jy, y, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqty, qty, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1RAppl_native_1dqrqy(JNIEnv *env, jclass c,
+		jdoubleArray jx, int n, int k, jdoubleArray jqraux, jdoubleArray jy, int ny, jdoubleArray jqy) {
+	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
+	double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL);
+	double *y = (*env)->GetPrimitiveArrayCritical(env, jy, NULL);
+	double *qy = (*env)->GetPrimitiveArrayCritical(env, jqy, NULL);
+	dqrqy_(x, &n, &k, qraux, y, &ny, qy);
+	(*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jy, y, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqy, qy, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1RAppl_native_1dqrrsd(JNIEnv *env, jclass c,
+		jdoubleArray jx, int n, int k, jdoubleArray jqraux, jdoubleArray jy, int ny, jdoubleArray jrsd) {
+	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
+	double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL);
+	double *y = (*env)->GetPrimitiveArrayCritical(env, jy, NULL);
+	double *rsd = (*env)->GetPrimitiveArrayCritical(env, jrsd, NULL);
+	dqrrsd_(x, &n, &k, qraux, y, &ny, rsd);
+	(*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jy, y, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jrsd, rsd, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1RAppl_native_1dqrxb(JNIEnv *env, jclass c,
+		jdoubleArray jx, int n, int k, jdoubleArray jqraux, jdoubleArray jy, int ny, jdoubleArray jxb) {
+	double *x = (*env)->GetPrimitiveArrayCritical(env, jx, NULL);
+	double *qraux = (*env)->GetPrimitiveArrayCritical(env, jqraux, NULL);
+	double *y = (*env)->GetPrimitiveArrayCritical(env, jy, NULL);
+	double *xb = (*env)->GetPrimitiveArrayCritical(env, jxb, NULL);
+	dqrxb_(x, &n, &k, qraux, y, &ny, xb);
+	(*env)->ReleasePrimitiveArrayCritical(env, jx, x, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jqraux, qraux, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jy, y, 0);
+	(*env)->ReleasePrimitiveArrayCritical(env, jxb, xb, 0);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c
index 6e19483674032eda9043ff7ae6e93bcdf963738e..1dfb0c1fbfb2f871181cd6e38c5690ccc83a92f8 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/base_rffi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -34,13 +34,13 @@
 #include <errno.h>
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1getpid(JNIEnv *env, jclass c) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Base_native_1getpid(JNIEnv *env, jclass c) {
 	pid_t pid = getpid();
 	return (jint) pid;
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1getwd(JNIEnv *env, jclass c, jbyteArray jdest, int len) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Base_native_1getwd(JNIEnv *env, jclass c, jbyteArray jdest, int len) {
     char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL);
     char *r = getcwd(dest, len);
     if (r == NULL) return 0;
@@ -49,7 +49,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1getwd(JNIEnv *env, j
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1setwd(JNIEnv *env, jclass c, jstring jdir) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Base_native_1setwd(JNIEnv *env, jclass c, jstring jdir) {
     const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL);
     int rc = chdir(dir);
     (*env)->ReleaseStringUTFChars(env, jdir, dir);
@@ -57,7 +57,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1setwd(JNIEnv *env, j
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1mkdtemp(JNIEnv *env, jclass c, jbyteArray jtemplate) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Base_native_1mkdtemp(JNIEnv *env, jclass c, jbyteArray jtemplate) {
     char *template = (char*) (*env)->GetByteArrayElements(env, jtemplate, NULL);
     char *r = mkdtemp(template);
     int rc = 1;
@@ -70,7 +70,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1mkdtemp(JNIEnv *env,
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1mkdir(JNIEnv *env, jclass c, jstring jdir, jint mode) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Base_native_1mkdir(JNIEnv *env, jclass c, jstring jdir, jint mode) {
     const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL);
     int rc = mkdir(dir, mode);
     (*env)->ReleaseStringUTFChars(env, jdir, dir);
@@ -78,7 +78,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1mkdir(JNIEnv *env, j
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1chmod(JNIEnv *env, jclass c, jstring jdir, jint mode) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Base_native_1chmod(JNIEnv *env, jclass c, jstring jdir, jint mode) {
     const char *dir = (*env)->GetStringUTFChars(env, jdir, NULL);
     int rc = chmod(dir, mode);
     (*env)->ReleaseStringUTFChars(env, jdir, dir);
@@ -86,7 +86,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1chmod(JNIEnv *env, j
 }
 
 JNIEXPORT jlong JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1strtol(JNIEnv *env, jclass c, jstring js, jint base, jintArray jerrno) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Base_native_1strtol(JNIEnv *env, jclass c, jstring js, jint base, jintArray jerrno) {
     const char *s = (*env)->GetStringUTFChars(env, js, NULL);
     jlong rc = strtol(s, NULL, base);
     if (errno) {
@@ -99,7 +99,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1strtol(JNIEnv *env,
 }
 
 JNIEXPORT jstring JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1readlink(JNIEnv *env, jclass c, jstring jpath, jintArray jerrno) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Base_native_1readlink(JNIEnv *env, jclass c, jstring jpath, jintArray jerrno) {
     const char *path = (*env)->GetStringUTFChars(env, jpath, NULL);
     char buf[4096];
     int len = readlink(path, buf, 4096);
@@ -120,7 +120,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Base_native_1readlink(JNIEnv *env
 static jmethodID addPathID = 0;
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Glob_doglob(JNIEnv *env, jobject obj, jstring pattern) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Glob_doglob(JNIEnv *env, jobject obj, jstring pattern) {
 	glob_t globstruct;
 
 	if (addPathID == 0) {
@@ -140,7 +140,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Glob_doglob(JNIEnv *env, jobject
 }
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UtsName_getutsname(JNIEnv *env, jobject obj) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1UtsName_getutsname(JNIEnv *env, jobject obj) {
 	struct utsname name;
 
 	uname(&name);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c
index 9f1015280a6f3e5edb4e47ff5e135564e6330422..c4f9325efeaa0e4b01ac1e58a88b796c9610bcd7 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/c_rffi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,6 +22,7 @@
  */
 
 #include <rffiutils.h>
+#include <stdbool.h>
 
 static jclass intArrayClass;
 static jclass doubleArrayClass;
@@ -330,17 +331,8 @@ typedef void (*c65func)(void *arg1, void *arg2, void *arg3, void *arg4, void *ar
         void *arg57, void *arg58, void *arg59, void *arg60, void *arg61, void *arg62, void *arg63, void *arg64,
         void *arg65);
 
-
-JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1C_c(JNIEnv *env, jclass c, jlong address, jobjectArray args) {
-	int len = (*env)->GetArrayLength(env, args);
-	void *cargs[len];
-	jobject jarrays[len];
-	for (int i = 0; i < len; i++) {
-		jarrays[i] = (*env)->GetObjectArrayElement(env, args, i);
-		cargs[i] = (*env)->GetPrimitiveArrayCritical(env, jarrays[i], NULL);
-	}
-	switch (len) {
+static void doCall(jlong address, int len, void** cargs) {
+  switch (len) {
     case 0: {
         c0func c0 = (c0func) address;
         (*c0)();
@@ -969,9 +961,51 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1C_c(JNIEnv *env, jclass c, jlong
         break;
     }
 	}
-
-	for (int i = 0; i < len; i++) {
-		(*env)->ReleasePrimitiveArrayCritical(env, jarrays[i], cargs[i], 0);
-	}
 }
 
+// Note: hasStrings indicates that the args array may contain 2 dimensional byte arrays, which represent string vectors.
+JNIEXPORT void JNICALL
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1C_c(JNIEnv *env, jclass c, jlong address, jobjectArray args, jboolean hasStrings) {
+  int len = (*env)->GetArrayLength(env, args);
+  void *cargs[len];     // pointers to primitive arrays suitable for the actual c call
+  jobject jarrays[len]; // jarray instances corresponding to cargs native counterparts
+  jobject *dim2[len];   // if corresponding jarray[i] is 2-dimensional, this holds the array of jarrays, otherwise NULL
+  jclass byteArrayClass = NULL;
+  if (hasStrings) {
+      byteArrayClass = (*env)->FindClass(env, "[[B");
+  }
+
+  for (int i = 0; i < len; i++) {
+    jarrays[i] = (*env)->GetObjectArrayElement(env, args, i);
+    bool isString = hasStrings && (*env)->IsInstanceOf(env, jarrays[i], byteArrayClass);
+    if (isString) {
+      int len2 = (*env)->GetArrayLength(env, jarrays[i]);
+      dim2[i] = calloc(sizeof(jobject), len2);
+      const char **strArgs = calloc(sizeof(const char*), len2);
+      cargs[i] = strArgs;
+      for (int j = 0; j < len2; j++) {
+        dim2[i][j] = (*env)->GetObjectArrayElement(env, jarrays[i], j);
+        strArgs[j] = (*env)->GetPrimitiveArrayCritical(env, dim2[i][j], NULL);
+      }
+    } else {
+      dim2[i] = NULL;
+      cargs[i] = (*env)->GetPrimitiveArrayCritical(env, jarrays[i], NULL);
+    }
+  }
+
+  doCall(address, len, cargs);
+
+  for (int i = 0; i < len; i++) {
+    if (dim2[i] != NULL) {
+      int len2 = (*env)->GetArrayLength(env, jarrays[i]);
+      const char **strArgs = (const char**) cargs[i];
+      for (int j = 0; j < len2; j++) {
+        (*env)->ReleasePrimitiveArrayCritical(env, dim2[i][j], (void*) strArgs[j], 0);
+      }
+      free(dim2[i]);
+      free(cargs[i]);
+    } else {
+      (*env)->ReleasePrimitiveArrayCritical(env, jarrays[i], cargs[i], 0);
+    }
+  }
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
index 47ffc6ef39c9b9608027e0c8edaa93da6704d717..cb031ad01cace44fb384e1d4f1c7486deaa968b1 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/call_rffi.c
@@ -27,7 +27,7 @@
 
 // The entry point from JNI_Call that initializes the system
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_initialize(JNIEnv *env, jclass c,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_initialize(JNIEnv *env, jclass c,
 		jobject upCallInstance, jobjectArray initialValues) {
 	init_utils(env, upCallInstance); // must be first
 	init_variables(env, initialValues);
@@ -42,7 +42,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_initialize(JNIEnv *env, jcla
 }
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_nativeSetTempDir(JNIEnv *env, jclass c, jstring tempDir) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_nativeSetTempDir(JNIEnv *env, jclass c, jstring tempDir) {
 	setTempDir(env, tempDir);
 }
 
@@ -345,7 +345,7 @@ typedef SEXP (*call64func)(SEXP arg1, SEXP arg2, SEXP arg3, SEXP arg4, SEXP arg5
         );
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call0(JNIEnv *env, jclass c, jlong address) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call0(JNIEnv *env, jclass c, jlong address) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
 	callEnter(env, &error_jmpbuf);
@@ -358,7 +358,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call0(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call1(JNIEnv *env, jclass c, jlong address, jobject arg1) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call1(JNIEnv *env, jclass c, jlong address, jobject arg1) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
 	callEnter(env, &error_jmpbuf);
@@ -371,7 +371,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call1(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call2(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call2(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
 	callEnter(env, &error_jmpbuf);
@@ -384,7 +384,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call2(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call3(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call3(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -398,7 +398,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call3(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call4(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call4(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -412,7 +412,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call4(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call5(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call5(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -426,7 +426,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call5(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call6(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call6(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5, jobject arg6) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -440,7 +440,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call6(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call7(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call7(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -454,7 +454,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call7(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call8(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call8(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7, jobject arg8) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -468,7 +468,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call8(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call9(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call9(JNIEnv *env, jclass c, jlong address, jobject arg1, jobject arg2,
 		jobject arg3, jobject arg4, jobject arg5, jobject arg6, jobject arg7, jobject arg8, jobject arg9) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
@@ -482,7 +482,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call9(JNIEnv *env, jclass c,
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call(JNIEnv *env, jclass c, jlong address, jobjectArray args) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_call(JNIEnv *env, jclass c, jlong address, jobjectArray args) {
 	jmp_buf error_jmpbuf;
 	jobject result = NULL;
 	callEnter(env, &error_jmpbuf);
@@ -1227,7 +1227,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_call(JNIEnv *env, jclass c,
 typedef void (*callVoid1func)(SEXP arg1);
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_callVoid1(JNIEnv *env, jclass c, jlong address, jobject arg1) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_callVoid1(JNIEnv *env, jclass c, jlong address, jobject arg1) {
 	jmp_buf error_jmpbuf;
 	callEnter(env, &error_jmpbuf);
 	if (!setjmp(error_jmpbuf)) {
@@ -1240,7 +1240,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_callVoid1(JNIEnv *env, jclas
 typedef void (*callVoid0func)();
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Call_callVoid0(JNIEnv *env, jclass c, jlong address) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Call_callVoid0(JNIEnv *env, jclass c, jlong address) {
 	jmp_buf error_jmpbuf;
 	callEnter(env, &error_jmpbuf);
 	if (!setjmp(error_jmpbuf)) {
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
index daa89b365bfb54df08344acace2f4ef8e57b8686..83606709d3d4a3d85239ff64ec81144e25566b74 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/lapack_rffi.c
@@ -26,7 +26,7 @@
 extern void ilaver_(int *major, int *minor, int *patch);
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1ilaver(JNIEnv *env, jclass klass, jintArray jversion) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1ilaver(JNIEnv *env, jclass klass, jintArray jversion) {
 	int major;
 	int minor;
 	int patch;
@@ -42,7 +42,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1ilaver(JNIEnv *env
 extern int dgeev_(char *jobVL, char *jobVR, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgeev(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dgeev(JNIEnv *env, jclass klass,
         char jobVL, char jobVR, int n, jdoubleArray ja, int lda, jdoubleArray jwr, jdoubleArray jwi, jdoubleArray jvl, int ldvl, jdoubleArray jvr, int ldvr, jdoubleArray jwork, int lwork) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     double *wr = (*env)->GetPrimitiveArrayCritical(env, jwr, NULL);
@@ -64,7 +64,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgeev(JNIEnv *env,
 extern int dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *lwork, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgeqp3(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dgeqp3(JNIEnv *env, jclass klass,
         int m, int n, jdoubleArray ja, int lda, jintArray jjpvt, jdoubleArray jtau, jdoubleArray jwork, int lwork) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     int *jpvt = (*env)->GetPrimitiveArrayCritical(env, jjpvt, NULL);
@@ -82,7 +82,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgeqp3(JNIEnv *env
 extern int dormqr_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dormqr(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dormqr(JNIEnv *env, jclass klass,
         char side, char trans, int m, int n, int k, jdoubleArray ja, int lda, jdoubleArray jtau, jdoubleArray jc, int ldc, jdoubleArray jwork, int lwork) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     double *tau = (*env)->GetPrimitiveArrayCritical(env, jtau, NULL);
@@ -100,7 +100,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dormqr(JNIEnv *env
 extern int dtrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dtrtrs(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dtrtrs(JNIEnv *env, jclass klass,
         char uplo, char trans, char diag, int n, int nrhs, jdoubleArray ja, int lda, jdoubleArray jb, int ldb) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     double *b = (*env)->GetPrimitiveArrayCritical(env, jb, NULL);
@@ -114,7 +114,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dtrtrs(JNIEnv *env
 extern int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgetrf(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dgetrf(JNIEnv *env, jclass klass,
         int m, int n, jdoubleArray ja, int lda, jintArray jipiv) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     int *ipiv = (*env)->GetPrimitiveArrayCritical(env, jipiv, NULL);
@@ -128,7 +128,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgetrf(JNIEnv *env
 extern int dpotrf_(char *uplo, int *n, double *a, int *lda, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotrf(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dpotrf(JNIEnv *env, jclass klass,
         char uplo, int n, jdoubleArray ja, int lda) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     int info;
@@ -140,7 +140,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotrf(JNIEnv *env
 extern int dpotri_(char *uplo, int *n, double *a, int *lda, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotri(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dpotri(JNIEnv *env, jclass klass,
         char uplo, int n, jdoubleArray ja, int lda) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     int info;
@@ -152,7 +152,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpotri(JNIEnv *env
 extern int dpstrf_(char *uplo, int *n, double *a, int *lda, int *piv, int *rank, double *tol, double *work, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpstrf(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dpstrf(JNIEnv *env, jclass klass,
         char uplo, int n, jdoubleArray ja, int lda, jintArray jpiv, jintArray jrank, double tol, jdoubleArray jwork) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     int *piv = (*env)->GetPrimitiveArrayCritical(env, jpiv, NULL);
@@ -170,7 +170,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dpstrf(JNIEnv *env
 extern int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgesv(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dgesv(JNIEnv *env, jclass klass,
         int n, int nrhs, jdoubleArray ja, int lda, jintArray jipiv, jdoubleArray jb, int ldb) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     int *ipiv = (*env)->GetPrimitiveArrayCritical(env, jipiv, NULL);
@@ -186,7 +186,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgesv(JNIEnv *env,
 extern double dlange_(char *norm, int *m, int *n, double *a, int *lda, double *work);
 
 JNIEXPORT jdouble JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dlange(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dlange(JNIEnv *env, jclass klass,
         char norm, int m, int n, jdoubleArray ja, int lda, jdoubleArray jwork) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     double *work = jwork == NULL ? NULL : (*env)->GetPrimitiveArrayCritical(env, jwork, NULL);
@@ -199,7 +199,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dlange(JNIEnv *env
 extern int dgecon_(char *norm, int *n, double *a, int *lda, double *anorm, double *rcond, double *work, int *iwork, int *info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dgecon(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dgecon(JNIEnv *env, jclass klass,
         char norm, int n, jdoubleArray ja, int lda, double anorm, jdoubleArray jrcond, jdoubleArray jwork, jintArray jiwork) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
     double *rcond = (*env)->GetPrimitiveArrayCritical(env, jrcond, NULL);
@@ -218,7 +218,7 @@ extern int dsyevr_(char *jobz, char *range, char *uplo, int *n, double* a, int *
                 double* z, int *ldz, int* isuppz, double* work, int *lwork, int* iwork, int *liwork, int* info);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Lapack_native_1dsyevr(JNIEnv *env, jclass klass,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Lapack_native_1dsyevr(JNIEnv *env, jclass klass,
 		char jobz, char range, char uplo, int n, jdoubleArray ja, int lda, double vl, double vu, int il, int iu, double abstol, jintArray jm, jdoubleArray jw,
 		                    jdoubleArray jz, int ldz, jintArray jisuppz, jdoubleArray jwork, int lwork, jintArray jiwork, int liwork) {
     double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c
index b4ee639d1e7c9df1c303574cc9de1a4a060afed2..baef3889374ddf4129114528356cc8c67532154b 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/misc_rffi.c
@@ -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
@@ -24,7 +24,7 @@
 #include <rffiutils.h>
 
 JNIEXPORT jdouble JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Misc_exactSumFunc(JNIEnv *env, jclass c, jdoubleArray values, jboolean hasNa, jboolean naRm) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Misc_exactSumFunc(JNIEnv *env, jclass c, jdoubleArray values, jboolean hasNa, jboolean naRm) {
 	jint length = (*env)->GetArrayLength(env, values);
 	jdouble* contents = (jdouble*) (*env)->GetPrimitiveArrayCritical(env, values, NULL);
 
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c
index c8964b9ee037f0e2ad27ab154cbe497ceee15ac9..8f804e4c4eedeab65aa4ce2393ddb13277d16aa7 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c
@@ -32,12 +32,12 @@ void init_pcre(JNIEnv *env) {
 }
 
 JNIEXPORT jlong JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeMaketables(JNIEnv *env, jclass c) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1PCRE_nativeMaketables(JNIEnv *env, jclass c) {
 	return (jlong) pcre_maketables();
 }
 
 JNIEXPORT jobject JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, jclass c, jstring pattern, jint options, jlong tables) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, jclass c, jstring pattern, jint options, jlong tables) {
 	const char *patternChars = (*env)->GetStringUTFChars(env, pattern, NULL);
 	char *errorMessage;
 	int errOffset;
@@ -51,14 +51,14 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeCompile(JNIEnv *env, j
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeGetCaptureCount(JNIEnv *env, jclass c, jlong code, jlong extra) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1PCRE_nativeGetCaptureCount(JNIEnv *env, jclass c, jlong code, jlong extra) {
     int captureCount;
 	int rc = pcre_fullinfo((void *)code, (void *)extra, PCRE_INFO_CAPTURECOUNT, &captureCount);
     return rc < 0 ? rc : captureCount;
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeGetCaptureNames(JNIEnv *env, jclass c, jlong code, jlong extra, jobjectArray ret) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1PCRE_nativeGetCaptureNames(JNIEnv *env, jclass c, jlong code, jlong extra, jobjectArray ret) {
     int nameCount;
     int nameEntrySize;
     char* nameTable;
@@ -85,7 +85,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeGetCaptureNames(JNIEnv
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1PCRE_nativeExec(JNIEnv *env, jclass c, jlong code, jlong extra, jstring subject,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1PCRE_nativeExec(JNIEnv *env, jclass c, jlong code, jlong extra, jstring subject,
 	jint startOffset, jint options, jintArray ovector, jint ovectorLen) {
 	const char *subjectChars = (*env)->GetStringUTFChars(env, subject, NULL);
 	int subjectLength = (*env)->GetStringUTFLength(env, subject);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
index 9df3ebbeafedac00a00faa15d25b1209a8d7bf49..0049e90276011528e5e091a589bf3388ecf676eb 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.c
@@ -26,7 +26,6 @@
 #include <errno.h>
 #include <assert.h>
 
-
 /*
  * All calls pass through one of the call(N) methods in rfficall.c, which carry the JNIEnv value,
  * that needs to be saved for reuse in the many R functions such as Rf_allocVector.
@@ -73,6 +72,8 @@ static int nativeArrayTableHwm;
 static int nativeArrayTableLastIndex;
 static int nativeArrayTableLength;
 static void releaseNativeArray(JNIEnv *env, int index);
+static NativeArrayElem *findNativeArray(JNIEnv *env, SEXP x);
+static void updateNativeArray(JNIEnv *env, int index);
 
 static jfieldID CharSXPWrapperContentsFieldID;
 extern jmethodID logNotCharSXPWrapperMethodID;
@@ -215,7 +216,6 @@ void invalidateNativeArray(JNIEnv *env, SEXP oldObj) {
             fprintf(traceFile, "invalidateNativeArray(%p): found\n", oldObj);
 #endif
             releaseNativeArray(env, i);
-            nativeArrayTable[i].obj = NULL;
         }
     }
 #if TRACE_NATIVE_ARRAYS
@@ -223,40 +223,77 @@ void invalidateNativeArray(JNIEnv *env, SEXP oldObj) {
 #endif
 }
 
-void updateNativeArrays(JNIEnv *env) {
-    // We just release the arrays, the up call may change their contents in the R world,
-    // so we cannot re-use the native buffers which may be out of sync
+void updateJObjects(JNIEnv *env) {
     int oldHwm = nativeArrayTableHwmStack[callDepth - 1];
     for (int i = oldHwm; i < nativeArrayTableHwm; i++) {
-        releaseNativeArray(env, i);
+        NativeArrayElem cv = nativeArrayTable[i];
+        if (cv.obj != NULL) {
+            updateJObject(env, cv.obj);
+        }
     }
 }
 
+// Updates the data on the Java side from the data on the native side
+void updateJObject(JNIEnv *env, SEXP x) {
+#if TRACE_NATIVE_ARRAYS
+    fprintf(traceFile, "updateJObject(%p)\n", x);
+#endif
+	NativeArrayElem *cv = findNativeArray(env, x);
+	if (cv != NULL && cv->data != NULL && cv->type != CHARSXP) {
+#if TRACE_NATIVE_ARRAYS
+        fprintf(traceFile, "updateJObject(%p): updating\n", x);
+#endif
+        int len = (*env)->GetArrayLength(env, cv->jArray);
+        switch (cv->type) {
+            case INTSXP:
+                (*env)->SetIntArrayRegion(env, cv->jArray, 0, len, cv->data);
+                break;
+            case REALSXP:
+                (*env)->SetDoubleArrayRegion(env, cv->jArray, 0, len, cv->data);
+                break;
+            case RAWSXP:
+                (*env)->SetByteArrayRegion(env, cv->jArray, 0, len, cv->data);
+                break;
+            case LGLSXP: {
+                int *data = (int*) cv->data;
+                jbyte *byteData = malloc(len * sizeof(jbyte));
+                for (int i = 0; i < len; ++i) {
+                    byteData[i] = data[i];
+                }
+                (*env)->SetByteArrayRegion(env, cv->jArray, 0, len, byteData);
+                free(byteData);
+                break;
+            }
+            default:
+                fatalError("updateJObject: unexpected type");
+        }
+    }
+}
 
-static void *findNativeArray(JNIEnv *env, SEXP x) {
+static NativeArrayElem *findNativeArray(JNIEnv *env, SEXP x) {
     if (nativeArrayTableLastIndex < nativeArrayTableHwm) {
-        NativeArrayElem cv = nativeArrayTable[nativeArrayTableLastIndex];
-        if (cv.obj != NULL && (cv.obj == x || fast_IsSameObject(cv.obj, x))) {
-            void *data = cv.data;
+        NativeArrayElem *cv = &nativeArrayTable[nativeArrayTableLastIndex];
+        if (cv->obj != NULL && (cv->obj == x || fast_IsSameObject(cv->obj, x))) {
+            void *data = cv->data;
 #if TRACE_NATIVE_ARRAYS
             fprintf(traceFile, "findNativeArray(%p): found %p (cached)\n", x, data);
 #endif
-            return data;
+            return cv;
         }
     }
     int i;
     assert(isValidJNIRef(env, x));
     for (i = 0; i < nativeArrayTableHwm; i++) {
-        NativeArrayElem cv = nativeArrayTable[i];
-        if (cv.obj != NULL) {
-            assert(isValidJNIRef(env, cv.obj));
-            if (fast_IsSameObject(cv.obj, x)) {
+        NativeArrayElem *cv = &nativeArrayTable[i];
+        if (cv->obj != NULL) {
+            assert(isValidJNIRef(env, cv->obj));
+            if (fast_IsSameObject(cv->obj, x)) {
                 nativeArrayTableLastIndex = i;
-                void *data = cv.data;
+                void *data = cv->data;
 #if TRACE_NATIVE_ARRAYS
                 fprintf(traceFile, "findNativeArray(%p): found %p\n", x, data);
 #endif
-                return data;
+                return cv;
             }
         }
     }
@@ -266,9 +303,10 @@ static void *findNativeArray(JNIEnv *env, SEXP x) {
     return NULL;
 }
 
+
 static void addNativeArray(JNIEnv *env, SEXP x, SEXPTYPE type, void *jArray, void *data) {
 #if TRACE_NATIVE_ARRAYS
-    fprintf(traceFile, "addNativeArray(x=%p, t=%p, ix=%d)\n", x, data, nativeArrayTableHwm);
+    fprintf(traceFile, "addNativeArray(x=%p, t=%p, ix=%d, type=%d)\n", x, data, nativeArrayTableHwm, type);
 #endif
     // check for overflow
     if (nativeArrayTableHwm >= nativeArrayTableLength) {
@@ -289,40 +327,22 @@ static void addNativeArray(JNIEnv *env, SEXP x, SEXPTYPE type, void *jArray, voi
     nativeArrayTableHwm++;
 }
 
-void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) {
-    void *data = findNativeArray(thisenv, x);
+static void* extractVectorNativeArray(JNIEnv *thisenv, jarray jArray, SEXPTYPE type) {
     jboolean isCopy;
-    if (data == NULL) {
-        jarray jArray;
-        switch (type) {
-        case INTSXP: {
-            jintArray intArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, INTEGER_MethodID, x);
-            int len = (*thisenv)->GetArrayLength(thisenv, intArray);
-            data = (*thisenv)->GetIntArrayElements(thisenv, intArray, &isCopy);
-            jArray = intArray;
-            break;
-        }
+    int len = (*thisenv)->GetArrayLength(thisenv, jArray);
+    switch (type) {
+        case INTSXP:
+            return (*thisenv)->GetIntArrayElements(thisenv, (jintArray) jArray, &isCopy);
 
-        case REALSXP: {
-            jdoubleArray doubleArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, REAL_MethodID, x);
-            int len = (*thisenv)->GetArrayLength(thisenv, doubleArray);
-            data = (*thisenv)->GetDoubleArrayElements(thisenv, doubleArray, &isCopy);
-            jArray = doubleArray;
-            break;
-        }
+        case REALSXP:
+            return (*thisenv)->GetDoubleArrayElements(thisenv, (jdoubleArray) jArray, &isCopy);
 
-        case RAWSXP: {
-            jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, RAW_MethodID, x);
-            int len = (*thisenv)->GetArrayLength(thisenv, byteArray);
-            data = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy);
-            jArray = byteArray;
-            break;
-        }
+        case RAWSXP:
+            return (*thisenv)->GetByteArrayElements(thisenv, (jbyteArray) jArray, &isCopy);
 
         case LGLSXP: {
             // Special treatment because R FFI wants int* and FastR represents using byte[]
-            jbyteArray byteArray = (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, LOGICAL_MethodID, x);
-            int len = (*thisenv)->GetArrayLength(thisenv, byteArray);
+            jbyteArray byteArray = (jbyteArray) jArray;
             jbyte* internalData = (*thisenv)->GetByteArrayElements(thisenv, byteArray, &isCopy);
             int* idata = malloc(len * sizeof(int));
             for (int i = 0; i < len; i++) {
@@ -330,31 +350,133 @@ void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) {
                 idata[i] = value == 0 ? FALSE : value == 1 ? TRUE : NA_INTEGER;
             }
             (*thisenv)->ReleaseByteArrayElements(thisenv, byteArray, internalData, JNI_ABORT);
-            jArray = byteArray;
-            data = idata;
-            break;
+            return idata;
         }
+    }
+}
 
-        case CHARSXP: {
-        	jstring string = stringFromCharSXP(thisenv, x);
-        	data = (void *) stringToChars(thisenv, string);
-            jArray = string;
-            break;
+static jarray getJArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) {
+   switch (type) {
+       case INTSXP:
+          return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, INTEGER_MethodID, x);
+       case REALSXP:
+          return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, REAL_MethodID, x);
+       case RAWSXP:
+          return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, RAW_MethodID, x);
+       case LGLSXP:
+          return (*thisenv)->CallObjectMethod(thisenv, UpCallsRFFIObject, LOGICAL_MethodID, x);
+       default:
+          fatalError("getNativeArray: unexpected type");
+   }
+}
+
+void *getNativeArray(JNIEnv *thisenv, SEXP x, SEXPTYPE type) {
+#if TRACE_NATIVE_ARRAYS
+    fprintf(traceFile, "getNativeArray(%p)\n", x);
+#endif
+    NativeArrayElem *cv = findNativeArray(thisenv, x);
+    void *data = NULL;
+    if (cv != NULL) {
+        data = cv->data;
+    }
+    if (data == NULL) {
+        jarray jArray;
+        switch (type) {
+            case INTSXP:
+            case REALSXP:
+            case RAWSXP:
+            case LGLSXP: {
+                jArray = getJArray(thisenv, x, type);
+                data = extractVectorNativeArray(thisenv, jArray, type);
+                break;
+            }
+            case CHARSXP: {
+                jstring string = stringFromCharSXP(thisenv, x);
+                data = (void *) stringToChars(thisenv, string);
+                jArray = string;
+                break;
+            }
+            default:
+                fatalError("getNativeArray: unexpected type");
         }
+        addNativeArray(thisenv, x, type, jArray, data);
+    }
+    return data;
+}
+
+void updateNativeArrays(JNIEnv *env) {
+    int oldHwm = nativeArrayTableHwmStack[callDepth - 1];
+    for (int i = oldHwm; i < nativeArrayTableHwm; i++) {
+        updateNativeArray(env, i);
+    }
+}
 
+int getTypeSize(SEXPTYPE type) {
+   switch (type) {
+        case INTSXP:
+        case LGLSXP:
+            return sizeof(jint);
+        case RAWSXP:
+            return sizeof(jbyte);
+        case REALSXP:
+           return sizeof(jdouble);
         default:
-            fatalError("getNativeArray: unexpected type");
+           fatalError("getNativeArray: unexpected type");
+   }
+}
 
+static void updateNativeArray(JNIEnv *env, int i) {
+    NativeArrayElem cv = nativeArrayTable[i];
+    if (cv.obj != NULL && cv.type != CHARSXP) {
+        jarray current = getJArray(env, cv.obj, cv.type);
+        if (fast_IsSameObject(current, cv.jArray)) {
+#if TRACE_NATIVE_ARRAYS
+            fprintf(traceFile, "updateNativeArray(x=%p, t=%p, ix=%d, type=%d): copying data from Java\n", cv.obj, cv.data, i, cv.type);
+#endif
+            // same array, copy back the contents
+            int len = (*env)->GetArrayLength(env, cv.jArray);
+            switch (cv.type) {
+                case INTSXP:
+                    (*env)->GetIntArrayRegion(env, cv.jArray, 0, len, cv.data);
+                    break;
+                case REALSXP:
+                    (*env)->GetDoubleArrayRegion(env, cv.jArray, 0, len, cv.data);
+                    break;
+                case RAWSXP:
+                    (*env)->GetByteArrayRegion(env, cv.jArray, 0, len, cv.data);
+                    break;
+                case LGLSXP: {
+                    jbyte *byteData = malloc(len * sizeof(jbyte));
+                    (*env)->GetByteArrayRegion(env, cv.jArray, 0, len, byteData);
+                    for (int i = 0; i < len; ++i) {
+                        ((int*) cv.data)[i] = byteData[i];
+                    }
+                    free(byteData);
+                    break;
+                }
+                default:
+                    fatalError("updateJObject: unexpected type");
+            }
+        } else {
+            // not the same array: this could happen if temporary vector got re-used for re-allocated copy.
+            // If the user now attempts at accessing a previously acquired data pointer, it's an error anyway,
+            // We invalidate the native "mirror", it's not reflecting the same jobject, anymore and if user now
+            // attempts to get the data pointer, she should get the right one -- for the new array, not the old one.
+#if TRACE_NATIVE_ARRAYS
+            fprintf(traceFile, "updateNativeArray(x=%p, t=%p, ix=%d, type=%d): data in Java have changed, invalidating the cached pointer.\n", cv.obj, cv.data, index, cv.type);
+#endif
+            nativeArrayTable[i].obj = NULL;
         }
-        addNativeArray(thisenv, x, type, jArray, data);
     }
-    return data;
 }
 
+// Updates the Java counterpart object with the contents of the native array and
+// releases the native array. Use updateJObject to only update the java counterpart,
+// but do not release.
 static void releaseNativeArray(JNIEnv *env, int i) {
     NativeArrayElem cv = nativeArrayTable[i];
 #if TRACE_NATIVE_ARRAYS
-               fprintf(traceFile, "releaseNativeArray(x=%p, ix=%d, freedata=%d)\n", cv.obj, i, freedata);
+    fprintf(traceFile, "releaseNativeArray(x=%p, ix=%d, type=%d)\n", cv.obj, i, cv.type);
 #endif
     if (cv.obj != NULL) {
         assert(isValidJNIRef(env, cv.obj));
@@ -383,8 +505,9 @@ static void releaseNativeArray(JNIEnv *env, int i) {
                 }
 
             }
+            // note: internalData is used only as temp array here, no need to honor "mode"
             (*env)->ReleaseByteArrayElements(env, byteArray, internalData, 0);
-                    free(data); // was malloc'ed in addNativeArray
+            free(data); // was malloc'ed in addNativeArray
             break;
         }
 
@@ -409,14 +532,16 @@ static void releaseNativeArray(JNIEnv *env, int i) {
 
         }
         default:
-            fatalError("releaseNativeArray type");
+            fatalError("updateManagedVector type");
         }
         // update complete status
         (*env)->CallStaticVoidMethod(env, JNIUpCallsRFFIImplClass, setCompleteMethodID, cv.obj, complete);
 
-        // free up the slot
         nativeArrayTable[i].obj = NULL;
     }
+#if TRACE_NATIVE_ARRAYS
+    fprintf(traceFile, "updateManagedVector(x=%p, ix=%d): DONE\n", cv.obj, i);
+#endif
 }
 
 static SEXP findCachedGlobalRef(JNIEnv *env, SEXP obj) {
@@ -524,6 +649,7 @@ void *unimplemented(char *msg) {
     strcpy(buf, "unimplemented ");
     strcat(buf, msg);
     (*thisenv)->FatalError(thisenv, buf);
+    return NULL;
 }
 
 void fatalError(char *msg) {
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
index 91bd2d985dbb01555cf035768c4fbae852351c25..077dad811e2b06169583d995213ae93b62309083 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/jni/rffiutils.h
@@ -71,12 +71,21 @@ jmp_buf *getErrorJmpBuf();
 // the data as a C array
 void *getNativeArray(JNIEnv *env, SEXP x, SEXPTYPE type);
 // Rare case where an operation changes the internal
-// data and thus the old C array should be invalidated
+// data and thus the old C array should be invalidated,
+// unlike updateJObjects this really frees the native array.
 void invalidateNativeArray(JNIEnv *env, SEXP oldObj);
 // Should be called before up calling to arbitrary code, e.g. Rf_eval,
-// to copy back the arrays into their Java counterparts
+// to copy back the arrays into their Java counterparts. The native arrays
+// are not freed and stay around.
+void updateJObjects(JNIEnv *env);
+// Should be called after up calling to arbitrary code, e.g. Rf_eval,
+// to copy back the java side arrays into their native counterparts.
 void updateNativeArrays(JNIEnv *env);
 
+
+// Copies back the array to the Java counterpart
+void updateJObject(JNIEnv *env, SEXP obj);
+
 SEXP addGlobalRef(JNIEnv *env, SEXP obj, int permanent);
 
 void init_utils(JNIEnv *env, jobject upCallsInstance);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c b/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c
index 4ed4a0dcf2474cf871d25907b58d5a460c3a9063..fbc776789592fb6d000f9128bf94ce572e88e5a3 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/stats_fft.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -28,7 +28,7 @@ typedef Rboolean (*fft_work)(double *a, int nseg, int n, int nspn, int isn,
 		  double *work, int *iwork);
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Stats_native_1fft_1factor(JNIEnv *env, jclass c, jlong address,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Stats_native_1fft_1factor(JNIEnv *env, jclass c, jlong address,
 		jint n, jintArray jpmaxf, jintArray jpmaxp) {
 	fft_factor f = (fft_factor) address;
 	int *pmaxf = (*env)->GetPrimitiveArrayCritical(env, jpmaxf, NULL);
@@ -39,7 +39,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Stats_native_1fft_1factor(JNIEnv
 }
 
 JNIEXPORT int JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Stats_native_1fft_1work(JNIEnv *env, jclass c, jlong address,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Stats_native_1fft_1work(JNIEnv *env, jclass c, jlong address,
 		jdoubleArray ja, int nseg, int n, int nsps, int isn, jdoubleArray jwork, jintArray jiwork) {
 	fft_work f = (fft_work) address;
 	double *a = (*env)->GetPrimitiveArrayCritical(env, ja, NULL);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c
index fd510c9e56eaa4985c9067a574bf6a2b092415ed..dda2cf2db82235b6a5f98b925f49cb7a7c5d5d87 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/userrng_rffi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -29,27 +29,27 @@ typedef int* (*call_nSeed)(void);
 typedef int* (*call_seeds)(void);
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nativeInit(JNIEnv *env, jclass c, jlong address, jint seed) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1UserRng_nativeInit(JNIEnv *env, jclass c, jlong address, jint seed) {
 	call_init f = (call_init) address;
 	f(seed);
 }
 
 JNIEXPORT double JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nativeRand(JNIEnv *env, jclass c, jlong address) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1UserRng_nativeRand(JNIEnv *env, jclass c, jlong address) {
 	call_rand f = (call_rand) address;
 	double* dp = f();
 	return *dp;
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nativeNSeed(JNIEnv *env, jclass c, jlong address) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1UserRng_nativeNSeed(JNIEnv *env, jclass c, jlong address) {
 	call_nSeed f = (call_nSeed) address;
 	int *pn = f();
 	return *pn;
 }
 
 JNIEXPORT void JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1UserRng_nativeSeeds(JNIEnv *env, jclass c, jlong address, jintArray seedsArray) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1UserRng_nativeSeeds(JNIEnv *env, jclass c, jlong address, jintArray seedsArray) {
 	call_seeds f = (call_seeds) address;
 	int *pseeds = f();
 	int seedslen = (*env)->GetArrayLength(env, seedsArray);
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/variables.c b/com.oracle.truffle.r.native/fficall/src/jni/variables.c
index c66739f886fa1eb5d9f4820d5b4666255645367e..1af98efddf3776ed4fe0d4f17f04a39cfcaf9615 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/variables.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/variables.c
@@ -50,6 +50,7 @@ static SEXP R_BaseSymbol_static;
 static SEXP R_Bracket2Symbol_static;   /* "[[" */
 static SEXP R_BracketSymbol_static;    /* "[" */
 static SEXP R_BraceSymbol_static;      /* "{" */
+static SEXP R_DoubleColonSymbol_static; /* "::" */
 static SEXP R_ClassSymbol_static;     /* "class" */
 static SEXP R_DeviceSymbol_static;     /* ".Device" */
 static SEXP R_DevicesSymbol_static;     /* ".Devices" */
@@ -182,6 +183,10 @@ SEXP FASTR_R_BraceSymbol() {
     return R_BraceSymbol_static;
 }
 
+SEXP FASTR_R_DoubleColonSymbol() {
+    return R_DoubleColonSymbol_static;
+}
+
 SEXP FASTR_R_Bracket2Symbol() {
     return R_Bracket2Symbol_static;
 }
@@ -371,6 +376,8 @@ void init_variables(JNIEnv *env, jobjectArray initialValues) {
 					R_BracketSymbol_static = ref;
 				} else if (strcmp(nameChars, "R_BraceSymbol") == 0) {
 					R_BraceSymbol_static = ref;
+				} else if (strcmp(nameChars, "R_DoubleColonSymbol") == 0) {
+					R_DoubleColonSymbol_static = ref;
 				} else if (strcmp(nameChars, "R_ClassSymbol") == 0) {
 					R_ClassSymbol_static = ref;
 				} else if (strcmp(nameChars, "R_DeviceSymbol") == 0) {
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c b/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c
index e6bbec4c6cd08089bc7f3eea81a57198a064c21f..ffde19de4d11b1204a8929518249fc83eac2f877 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/zip_rffi.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -23,11 +23,11 @@
 
 #include <rffiutils.h>
 
-extern int compress(char *dest, long *destlen, char *source, long *sourcelen);
-extern int uncompress(char *dest, long *destlen, char *source, long *sourcelen);
+extern int compress(char *dest, long *destlen, char *source, long sourcelen);
+extern int uncompress(char *dest, long *destlen, char *source, long sourcelen);
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Zip_native_1compress(JNIEnv *env, jclass c,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Zip_native_1compress(JNIEnv *env, jclass c,
 		jbyteArray jdest, jlong destlen, jbyteArray jsource, jlong sourcelen) {
     char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL);
     char *source = (*env)->GetPrimitiveArrayCritical(env, jsource, NULL);
@@ -38,7 +38,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Zip_native_1compress(JNIEnv *env,
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1Zip_native_1uncompress(JNIEnv *env, jclass c,
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1Zip_native_1uncompress(JNIEnv *env, jclass c,
 		jbyteArray jdest, jlong destlen, jbyteArray jsource, jlong sourcelen) {
     char *dest = (*env)->GetPrimitiveArrayCritical(env, jdest, NULL);
     char *source = (*env)->GetPrimitiveArrayCritical(env, jsource, NULL);
diff --git a/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c b/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c
index fb7783eb30615359e3632ba3c9ddc86300a9fad2..b313815395ca29ab8d4e1a8f03c247cfee66d721 100644
--- a/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c
+++ b/com.oracle.truffle.r.native/fficall/src/jniboot/jniboot.c
@@ -36,7 +36,7 @@ static void initUnsatisfiedLinkError(JNIEnv *env) {
 }
 
 JNIEXPORT jlong JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlopen(JNIEnv *env, jclass c, jstring jpath, jboolean local, jboolean now) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1DLL_native_1dlopen(JNIEnv *env, jclass c, jstring jpath, jboolean local, jboolean now) {
     const char *path = (*env)->GetStringUTFChars(env, jpath, NULL);
     int flags = (local ? RTLD_LOCAL : RTLD_GLOBAL) | (now ? RTLD_NOW : RTLD_LAZY);
     void *handle = dlopen(path, flags);
@@ -51,7 +51,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlopen(JNIEnv *env, j
 }
 
 JNIEXPORT jlong JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlsym(JNIEnv *env, jclass c, jlong handle, jstring jsymbol) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1DLL_native_1dlsym(JNIEnv *env, jclass c, jlong handle, jstring jsymbol) {
     const char *symbol = (*env)->GetStringUTFChars(env, jsymbol, NULL);
     void *address = dlsym((void *)handle, symbol);
     if (address == NULL) {
@@ -67,7 +67,7 @@ Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlsym(JNIEnv *env, jc
 }
 
 JNIEXPORT jint JNICALL
-Java_com_oracle_truffle_r_runtime_ffi_jni_JNI_1DLL_native_1dlclose(JNIEnv *env, jclass c, jlong handle) {
+Java_com_oracle_truffle_r_ffi_impl_jni_JNI_1DLL_native_1dlclose(JNIEnv *env, jclass c, jlong handle) {
     int rc = dlclose((void *)handle);
     return rc;
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rdynload_fastr.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rdynload_fastr.h
new file mode 100644
index 0000000000000000000000000000000000000000..22be14a8c138534f96c0701c2c414cbd0f94ef94
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rdynload_fastr.h
@@ -0,0 +1,142 @@
+/*
+ * 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.
+ */
+#include <rffiutils.h>
+#include <Rdynload.h>
+
+// The implementation must implement:
+// void *ensure_function(void *fun)
+
+typedef void (*call_registerRoutines)(DllInfo *dllInfo, int nstOrd, int num, long routines);
+typedef int (*call_useDynamicSymbols)(DllInfo *dllInfo, Rboolean value);
+typedef void * (*call_setDotSymbolValues)(DllInfo *dllInfo, char *name, void *fun, int numArgs);
+typedef int (*call_forceSymbols)(DllInfo *dllInfo, Rboolean value);
+typedef int (*call_registerCCallable)(const char *pkgname, const char *name, void *fun);
+typedef void* (*call_getCCallable)(const char *pkgname, const char *name);
+
+#define registerRoutines_x 0
+#define setDotSymbolValues_x 1
+#define useDynamicSymbols_x 2
+#define forceSymbols_x 3
+#define registerCCallable_x 4
+#define getCCallable_x 5
+#define CALLBACK_TABLE_SIZE 6
+
+// Must match ordinal value for DLL.NativeSymbolType
+#define C_NATIVE_TYPE 0
+#define CALL_NATIVE_TYPE 1
+#define FORTRAN_NATIVE_TYPE 2
+#define EXTERNAL_NATIVE_TYPE 3
+
+int
+R_registerRoutines(DllInfo *info, const R_CMethodDef * const croutines,
+		   const R_CallMethodDef * const callRoutines,
+		   const R_FortranMethodDef * const fortranRoutines,
+		   const R_ExternalMethodDef * const externalRoutines) {
+	int num;
+	if (croutines) {
+		for(num = 0; croutines[num].name != NULL; num++) {;}
+		//printf("R_registerRoutines %p,%d,%d,%p\n", info, C_NATIVE_TYPE, num, croutines);
+		((call_registerRoutines) dynload_callbacks[registerRoutines_x])(info, C_NATIVE_TYPE, num, (long) croutines);
+	}
+	if (callRoutines) {
+		for(num = 0; callRoutines[num].name != NULL; num++) {;}
+		//printf("R_registerRoutines %p,%d,%d,%p\n", info, CALL_NATIVE_TYPE, num, callRoutines);
+		((call_registerRoutines) dynload_callbacks[registerRoutines_x])(info, CALL_NATIVE_TYPE, num, (long) callRoutines);
+	}
+	if (fortranRoutines) {
+		for(num = 0; fortranRoutines[num].name != NULL; num++) {;}
+		//printf("R_registerRoutines %p,%p,%d,%d,%p\n", info, FORTRAN_NATIVE_TYPE, num, fortranRoutines);
+		((call_registerRoutines) dynload_callbacks[registerRoutines_x])(info, FORTRAN_NATIVE_TYPE, num, (long) fortranRoutines);
+	}
+	if (externalRoutines) {
+		for(num = 0; externalRoutines[num].name != NULL; num++) {;}
+		//printf("R_registerRoutines %p,%d,%d,%p\n", info, EXTERNAL_NATIVE_TYPE, num, externalRoutines);
+		((call_registerRoutines) dynload_callbacks[registerRoutines_x])(info, EXTERNAL_NATIVE_TYPE, num, (long) externalRoutines);
+	}
+    return 1;
+}
+
+Rboolean R_useDynamicSymbols(DllInfo *dllInfo, Rboolean value) {
+	//printf("R_useDynamicSymbols %p %d %p\n", dllInfo, value);
+	return ((call_useDynamicSymbols) dynload_callbacks[useDynamicSymbols_x])(dllInfo, value);
+}
+
+Rboolean R_forceSymbols(DllInfo *dllInfo, Rboolean value) {
+	//printf("R_forceSymbols %p %d\n", dllInfo, value);
+	return ((call_forceSymbols) dynload_callbacks[forceSymbols_x])(dllInfo, value);
+}
+
+
+void *Rdynload_setSymbol(DllInfo *info, int nstOrd, long routinesAddr, int index) {
+	const char *name;
+	void * fun;
+	int numArgs;
+	switch (nstOrd) {
+	case C_NATIVE_TYPE: {
+		R_CMethodDef *croutines = (R_CMethodDef *) routinesAddr;
+		name = croutines[index].name;
+		fun = croutines[index].fun;
+		numArgs = croutines[index].numArgs;
+		break;
+	}
+	case CALL_NATIVE_TYPE: {
+		R_CallMethodDef *callRoutines = (R_CallMethodDef *) routinesAddr;
+		name = callRoutines[index].name;
+		fun = callRoutines[index].fun;
+		numArgs = callRoutines[index].numArgs;
+		break;
+	}
+	case FORTRAN_NATIVE_TYPE: {
+		R_FortranMethodDef * fortranRoutines = (R_FortranMethodDef *) routinesAddr;
+		name = fortranRoutines[index].name;
+		fun = fortranRoutines[index].fun;
+		numArgs = fortranRoutines[index].numArgs;
+		break;
+	}
+	case EXTERNAL_NATIVE_TYPE: {
+		R_ExternalMethodDef * externalRoutines = (R_ExternalMethodDef *) routinesAddr;
+		name = externalRoutines[index].name;
+		fun = externalRoutines[index].fun;
+		numArgs = externalRoutines[index].numArgs;
+		break;
+	}
+	}
+	//printf("call_setDotSymbolValues %p, %s, %p, %d\n", info, name, fun, numArgs);
+	void *result = ((call_setDotSymbolValues) dynload_callbacks[setDotSymbolValues_x])(info, ensure_string(name), ensure_fun(fun), numArgs);
+	return result;
+}
+
+void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr) {
+	//printf("R_RegisterCCallable %s %s %p\n", package, name, fptr);
+	((call_registerCCallable) dynload_callbacks[registerCCallable_x])(ensure_string(package), ensure_string(name), ensure_fun((void *)fptr));
+}
+
+DL_FUNC R_GetCCallable(const char *package, const char *name) {
+	//printf("R_GetCCallable %s %s %p\n", package, name);
+	return ((call_getCCallable) dynload_callbacks[getCCallable_x])(ensure_string(package), ensure_string(name));
+}
+
+DL_FUNC R_FindSymbol(char const *name, char const *pkg,
+		     R_RegisteredNativeSymbol *symbol) {
+    return unimplemented("R_FindSymbol");
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..916a6d0a4be19b603150d698a09baca6a51243b6
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/Rinternals_truffle_common.h
@@ -0,0 +1,1106 @@
+/*
+ * 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
+ * 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.
+ */
+
+/* This file is "included" by the corresponding Rinternals.c in the
+   truffle_nfi and truffle_llvm directories.
+   The implementation must define the following five functions:
+
+   SEXP checkRef(SEXP x)
+     Checks for 'x' being "handle" and returns the canionical handle.
+
+   SEXP newObjectHandle(SEXP x)
+
+   void releaseObjectHandle(SEXP x)
+
+   char *ensure_truffle_chararray_n(const char *x, int n)
+     Ensures that the sequence of 'n' bytes starting at 'x' is in the
+     appropriate representation for the implementation.
+
+   void *ensure_string(const char *x)
+     Ensures that (on the Java side of the upcall) x, which must be null-terminated,
+     appears as a java.lang.String
+
+   Any of these functions could be the identity function.
+*/
+
+// R_GlobalEnv et al are not a variables in FASTR as they are RContext specific
+SEXP FASTR_R_GlobalEnv() {
+	return ((call_R_GlobalEnv) callbacks[R_GlobalEnv_x])();
+}
+
+SEXP FASTR_R_BaseEnv() {
+	return ((call_R_BaseEnv) callbacks[R_BaseEnv_x])();
+}
+
+SEXP FASTR_R_BaseNamespace() {
+	return ((call_R_BaseNamespace) callbacks[R_BaseNamespace_x])();
+}
+
+SEXP FASTR_R_NamespaceRegistry() {
+	return ((call_R_NamespaceRegistry) callbacks[R_NamespaceRegistry_x])();
+}
+
+CTXT FASTR_GlobalContext() {
+	return ((call_R_GlobalContext) callbacks[R_GlobalContext_x])();
+}
+
+Rboolean FASTR_R_Interactive() {
+	return (int) ((call_R_Interactive) callbacks[R_Interactive_x])();
+}
+
+SEXP CAR(SEXP e) {
+	return checkRef(((call_CAR) callbacks[CAR_x])(e));
+}
+
+SEXP CDR(SEXP e) {
+	return checkRef(((call_CDR) callbacks[CDR_x])(e));
+}
+
+int LENGTH(SEXP x) {
+	return ((call_LENGTH) callbacks[LENGTH_x])(x);
+}
+
+SEXP Rf_ScalarString(SEXP value) {
+	return checkRef(((call_Rf_ScalarString) callbacks[Rf_ScalarString_x])(value));
+}
+
+SEXP Rf_mkString(const char *s) {
+	return ScalarString(Rf_mkChar(s));
+}
+
+void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho) {
+	((call_Rf_gsetVar) callbacks[Rf_gsetVar_x])(symbol, value, rho);
+}
+
+SEXP Rf_coerceVector(SEXP x, SEXPTYPE mode) {
+	return checkRef(((call_Rf_coerceVector) callbacks[Rf_coerceVector_x])(x, mode));
+}
+
+SEXP Rf_cons(SEXP car, SEXP cdr) {
+	return checkRef(((call_Rf_cons) callbacks[Rf_cons_x])(car, cdr));
+}
+
+SEXP Rf_GetOption1(SEXP tag) {
+	return checkRef(((call_Rf_GetOption1) callbacks[Rf_GetOption1_x])(tag));
+}
+
+SEXP Rf_mkChar(const char *x) {
+	return Rf_mkCharLenCE(x, strlen(x), CE_NATIVE);
+}
+
+SEXP Rf_mkCharCE(const char *x, cetype_t y) {
+	return Rf_mkCharLenCE(x, strlen(x), y);
+}
+
+SEXP Rf_mkCharLen(const char *x, int y) {
+	return Rf_mkCharLenCE(x, y, CE_NATIVE);
+}
+
+SEXP Rf_mkCharLenCE(const char *x, int len, cetype_t enc) {
+	return checkRef(((call_Rf_mkCharLenCE) callbacks[Rf_mkCharLenCE_x])(ensure_truffle_chararray_n(x, len), len, enc));
+}
+
+#define BUFSIZE 8192
+
+static int Rvsnprintf(char *buf, size_t size, const char  *format, va_list ap)
+{
+    int val;
+    val = vsnprintf(buf, size, format, ap);
+    buf[size-1] = '\0';
+    return val;
+}
+
+
+void Rf_errorcall(SEXP x, const char *format, ...) {
+	unimplemented("Rf_errorcall");
+}
+
+void Rf_warningcall(SEXP x, const char *format, ...) {
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	((call_Rf_warningcall) callbacks[Rf_warningcall_x])(x, ensure_string(buf));
+}
+
+void Rf_warning(const char *format, ...) {
+	char buf[8192];
+	va_list(ap);
+	va_start(ap, format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	((call_Rf_warning) callbacks[Rf_warning_x])(ensure_string(buf));
+}
+
+void Rprintf(const char *format, ...) {
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	((call_Rprintf) callbacks[Rprintf_x])(ensure_string(buf));
+}
+
+void Rf_error(const char *format, ...) {
+	// This is a bit tricky. The usual error handling model in Java is "throw RError.error(...)" but
+	// RError.error does quite a lot of stuff including potentially searching for R condition handlers
+	// and, if it finds any, does not return, but throws a different exception than RError.
+	// We definitely need to exit the FFI call and we certainly cannot return to our caller.
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	((call_Rf_error) callbacks[Rf_error_x])(ensure_string(buf));
+	// Should not reach here
+	unimplemented("Rf_error");
+}
+
+
+/*
+  REprintf is used by the error handler do not add
+  anything unless you're sure it won't
+  cause problems
+*/
+void REprintf(const char *format, ...)
+{
+	// TODO: determine correct target for this message
+	char buf[8192];
+	va_list(ap);
+	va_start(ap,format);
+	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
+	va_end(ap);
+	// TODO
+}
+
+void Rvprintf(const char *format, va_list args) {
+	unimplemented("Rvprintf");
+}
+void REvprintf(const char *format, va_list args) {
+	unimplemented("REvprintf");
+}
+
+
+SEXP Rf_ScalarInteger(int value) {
+	return checkRef(((call_Rf_ScalarInteger) callbacks[Rf_ScalarInteger_x])(value));
+}
+
+SEXP Rf_ScalarReal(double value) {
+	return checkRef(((call_Rf_ScalarReal) callbacks[Rf_ScalarDouble_x])(value));
+}
+
+SEXP Rf_ScalarLogical(int value) {
+	return checkRef(((call_Rf_ScalarLogical) callbacks[Rf_ScalarLogical_x])(value));
+}
+
+SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) {
+    if (allocator != NULL) {
+  	    unimplemented("RF_allocVector with custom allocator");
+	    return NULL;
+    }
+    return checkRef(((call_Rf_allocVector) callbacks[Rf_allocVector_x])(t, len));
+}
+
+SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) {
+	return checkRef(((call_Rf_allocArray) callbacks[Rf_allocArray_x])(t, dims));
+}
+
+SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) {
+	return unimplemented("Rf_alloc3DArray");
+}
+
+SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) {
+	return checkRef(((call_Rf_allocMatrix) callbacks[Rf_allocMatrix_x])(mode, nrow, ncol));
+}
+
+SEXP Rf_allocList(int x) {
+	unimplemented("Rf_allocList)");
+	return NULL;
+}
+
+SEXP Rf_allocSExp(SEXPTYPE t) {
+	return unimplemented("Rf_allocSExp");
+}
+
+void Rf_defineVar(SEXP symbol, SEXP value, SEXP rho) {
+	((call_Rf_defineVar) callbacks[Rf_defineVar_x])(symbol, value, rho);
+}
+
+void Rf_setVar(SEXP x, SEXP y, SEXP z) {
+    unimplemented("Rf_setVar");
+}
+
+SEXP Rf_dimgets(SEXP x, SEXP y) {
+	return unimplemented("Rf_dimgets");
+}
+
+SEXP Rf_dimnamesgets(SEXP x, SEXP y) {
+	return unimplemented("Rf_dimnamesgets");
+}
+
+SEXP Rf_eval(SEXP expr, SEXP env) {
+	return checkRef(((call_Rf_eval) callbacks[Rf_eval_x])(expr, env));
+}
+
+SEXP Rf_findFun(SEXP symbol, SEXP rho) {
+	return checkRef(((call_Rf_findFun) callbacks[Rf_findFun_x])(symbol, rho));
+}
+
+SEXP Rf_findVar(SEXP sym, SEXP rho) {
+	return checkRef(((call_Rf_findVar) callbacks[Rf_findVar_x])(sym, rho));
+}
+
+SEXP Rf_findVarInFrame(SEXP rho, SEXP sym) {
+	return checkRef(((call_Rf_findVarInFrame) callbacks[Rf_findVarInFrame_x])(rho, sym));
+}
+
+SEXP Rf_findVarInFrame3(SEXP rho, SEXP sym, Rboolean b) {
+	return checkRef(((call_Rf_findVarInFrame3) callbacks[Rf_findVarInFrame3_x])(rho, sym, b));
+}
+
+SEXP Rf_getAttrib(SEXP vec, SEXP name) {
+	SEXP result = ((call_Rf_getAttrib) callbacks[Rf_getAttrib_x])(vec, name);
+//	printf("Rf_getAttrib: %p\n", result);
+	return result;
+}
+
+SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) {
+	return checkRef(((call_Rf_setAttrib) callbacks[Rf_setAttrib_x])(vec, name, val));
+}
+
+SEXP Rf_duplicate(SEXP x) {
+	return checkRef(((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 1));
+}
+
+SEXP Rf_shallow_duplicate(SEXP x) {
+	return checkRef(((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 0));
+}
+
+R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
+	return (R_xlen_t) ((call_Rf_any_duplicated) callbacks[Rf_any_duplicated_x])(x, from_last);
+}
+
+SEXP Rf_duplicated(SEXP x, Rboolean y) {
+	unimplemented("Rf_duplicated");
+	return NULL;
+}
+
+SEXP Rf_applyClosure(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b) {
+	return unimplemented("Rf_applyClosure");
+}
+
+void Rf_copyMostAttrib(SEXP x, SEXP y) {
+	unimplemented("Rf_copyMostAttrib");
+}
+
+void Rf_copyVector(SEXP x, SEXP y) {
+	unimplemented("Rf_copyVector");
+}
+
+int Rf_countContexts(int x, int y) {
+	return (int) unimplemented("Rf_countContexts");
+}
+
+Rboolean Rf_inherits(SEXP x, const char * klass) {
+	return (Rboolean) ((call_Rf_inherits) callbacks[Rf_inherits_x])(x, ensure_string(klass));
+}
+
+Rboolean Rf_isObject(SEXP s) {
+	unimplemented("Rf_isObject");
+	return FALSE;
+}
+
+void Rf_PrintValue(SEXP x) {
+	unimplemented("Rf_PrintValue");
+}
+
+SEXP Rf_install(const char *name) {
+	return checkRef(((call_Rf_install) callbacks[Rf_install_x])(ensure_string(name)));
+}
+
+SEXP Rf_installChar(SEXP charsxp) {
+	return checkRef(((call_Rf_installChar) callbacks[Rf_installChar_x])(charsxp));
+}
+
+Rboolean Rf_isNull(SEXP s) {
+	return (Rboolean) ((call_Rf_isNull) callbacks[Rf_isNull_x])(s);
+}
+
+Rboolean Rf_isString(SEXP s) {
+	return (Rboolean) ((call_Rf_isString) callbacks[Rf_isString_x])(s);
+}
+
+Rboolean R_cycle_detected(SEXP s, SEXP child) {
+	unimplemented("R_cycle_detected");
+	return 0;
+}
+
+cetype_t Rf_getCharCE(SEXP x) {
+    // unimplemented("Rf_getCharCE");
+    // TODO: real implementation
+    return CE_NATIVE;
+}
+
+const char *Rf_reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst) {
+	// TODO proper implementation
+	return x;
+}
+
+int Rf_ncols(SEXP x) {
+	return (int) ((call_Rf_ncols) callbacks[Rf_ncols_x])(x);
+}
+
+int Rf_nrows(SEXP x) {
+	return (int) ((call_Rf_nrows) callbacks[Rf_nrows_x])(x);
+}
+
+
+SEXP Rf_protect(SEXP x) {
+	return x;
+}
+
+void Rf_unprotect(int x) {
+}
+
+void R_ProtectWithIndex(SEXP x, PROTECT_INDEX *y) {
+	//
+}
+
+void R_Reprotect(SEXP x, PROTECT_INDEX y) {
+	//
+}
+
+
+void Rf_unprotect_ptr(SEXP x) {
+	//
+}
+
+
+void R_FlushConsole(void) {
+	// ignored
+}
+
+void R_ProcessEvents(void) {
+	unimplemented("R_ProcessEvents");
+}
+
+// Tools package support, not in public API
+SEXP R_NewHashedEnv(SEXP parent, SEXP size) {
+	return checkRef(((call_R_NewHashedEnv) callbacks[R_NewHashedEnv_x])(parent, size));
+}
+
+SEXP Rf_classgets(SEXP vec, SEXP klass) {
+	return checkRef(((call_Rf_classgets) callbacks[Rf_classgets_x])(vec, klass));
+}
+
+const char *Rf_translateChar(SEXP x) {
+	// TODO: proper implementation
+	const char *result = CHAR(x);
+	return result;
+}
+
+const char *Rf_translateChar0(SEXP x) {
+	// TODO: proper implementation
+	const char *result = CHAR(x);
+	return result;
+}
+
+const char *Rf_translateCharUTF8(SEXP x) {
+	// TODO: proper implementation
+	const char *result = CHAR(x);
+	return result;
+}
+
+SEXP Rf_lengthgets(SEXP x, R_len_t y) {
+	return checkRef(((call_Rf_lengthgets) callbacks[Rf_lengthgets_x])(x, y));
+}
+
+SEXP Rf_xlengthgets(SEXP x, R_xlen_t y) {
+	return unimplemented("Rf_xlengthgets");
+}
+
+SEXP R_lsInternal(SEXP env, Rboolean all) {
+	return R_lsInternal3(env, all, TRUE);
+}
+
+SEXP R_lsInternal3(SEXP env, Rboolean all, Rboolean sorted) {
+	return checkRef(((call_R_lsInternal3) callbacks[R_lsInternal3_x])(env, all, sorted));
+}
+
+SEXP Rf_namesgets(SEXP x, SEXP y) {
+	return checkRef(((call_Rf_namesgets) callbacks[Rf_namesgets_x])(x, y));
+}
+
+SEXP TAG(SEXP e) {
+	return checkRef(((call_TAG) callbacks[TAG_x])(e));
+}
+
+SEXP PRINTNAME(SEXP e) {
+	return checkRef(((call_PRINTNAME) callbacks[PRINTNAME_x])(e));
+}
+
+
+SEXP CAAR(SEXP e) {
+    unimplemented("CAAR");
+    return NULL;
+}
+
+SEXP CDAR(SEXP e) {
+    unimplemented("CDAR");
+    return NULL;
+}
+
+SEXP CADR(SEXP e) {
+	return checkRef(((call_CADR) callbacks[CADR_x])(e));
+}
+
+SEXP CDDR(SEXP e) {
+	return checkRef(((call_CDDR) callbacks[CDDR_x])(e));
+}
+
+SEXP CDDDR(SEXP e) {
+    unimplemented("CDDDR");
+    return NULL;
+}
+
+SEXP CADDR(SEXP e) {
+	return checkRef(((call_CADDR) callbacks[CADDR_x])(e));
+}
+
+SEXP CADDDR(SEXP e) {
+    unimplemented("CADDDR");
+    return NULL;
+}
+
+SEXP CAD4R(SEXP e) {
+    unimplemented("CAD4R");
+    return NULL;
+}
+
+int MISSING(SEXP x){
+    unimplemented("MISSING");
+    return 0;
+}
+
+void SET_MISSING(SEXP x, int v) {
+    unimplemented("SET_MISSING");
+}
+
+void SET_TAG(SEXP x, SEXP y) {
+	((call_SET_TAG) callbacks[SET_TAG_x])(x, y);
+}
+
+SEXP SETCAR(SEXP x, SEXP y) {
+	return checkRef(((call_SETCAR) callbacks[SETCAR_x])(x, y));
+}
+
+SEXP SETCDR(SEXP x, SEXP y) {
+	return checkRef(((call_SETCDR) callbacks[SETCDR_x])(x, y));
+}
+
+SEXP SETCADR(SEXP x, SEXP y) {
+	return checkRef(((call_SETCADR) callbacks[SETCADR_x])(x, y));
+}
+
+SEXP SETCADDR(SEXP x, SEXP y) {
+    unimplemented("SETCADDR");
+    return NULL;
+}
+
+SEXP SETCADDDR(SEXP x, SEXP y) {
+    unimplemented("SETCADDDR");
+    return NULL;
+}
+
+SEXP SETCAD4R(SEXP e, SEXP y) {
+    unimplemented("SETCAD4R");
+    return NULL;
+}
+
+SEXP FORMALS(SEXP x) {
+    return unimplemented("FORMALS");
+}
+
+SEXP BODY(SEXP x) {
+	return unimplemented("BODY");
+}
+
+SEXP CLOENV(SEXP x) {
+	return unimplemented("CLOENV");
+}
+
+int RDEBUG(SEXP x) {
+	return ((call_RDEBUG) callbacks[RDEBUG_x])(x);
+}
+
+int RSTEP(SEXP x) {
+	return ((call_RSTEP) callbacks[RSTEP_x])(x);
+}
+
+int RTRACE(SEXP x) {
+	unimplemented("RTRACE");
+    return 0;
+}
+
+void SET_RDEBUG(SEXP x, int v) {
+	((call_SET_RDEBUG) callbacks[SET_RDEBUG_x])(x, v);
+}
+
+void SET_RSTEP(SEXP x, int v) {
+	((call_SET_RSTEP) callbacks[SET_RSTEP_x])(x, v);
+}
+
+void SET_RTRACE(SEXP x, int v) {
+    unimplemented("SET_RTRACE");
+}
+
+void SET_FORMALS(SEXP x, SEXP v) {
+    unimplemented("SET_FORMALS");
+}
+
+void SET_BODY(SEXP x, SEXP v) {
+    unimplemented("SET_BODY");
+}
+
+void SET_CLOENV(SEXP x, SEXP v) {
+    unimplemented("SET_CLOENV");
+}
+
+SEXP SYMVALUE(SEXP x) {
+	return checkRef(((call_SYMVALUE) callbacks[SYMVALUE_x])(x));
+}
+
+SEXP INTERNAL(SEXP x) {
+	return unimplemented("INTERNAL");
+}
+
+int DDVAL(SEXP x) {
+	unimplemented("DDVAL");
+    return 0;
+}
+
+void SET_DDVAL(SEXP x, int v) {
+    unimplemented("SET_DDVAL");
+}
+
+void SET_SYMVALUE(SEXP x, SEXP v) {
+	((call_SET_SYMVALUE) callbacks[SET_SYMVALUE_x])(x, v);
+}
+
+void SET_INTERNAL(SEXP x, SEXP v) {
+    unimplemented("SET_INTERNAL");
+}
+
+SEXP FRAME(SEXP x) {
+	return unimplemented("FRAME");
+}
+
+SEXP ENCLOS(SEXP x) {
+	return checkRef(((call_ENCLOS) callbacks[ENCLOS_x])(x));
+}
+
+SEXP HASHTAB(SEXP x) {
+	return unimplemented("HASHTAB");
+}
+
+int ENVFLAGS(SEXP x) {
+	unimplemented("ENVFLAGS");
+    return 0;
+}
+
+void SET_ENVFLAGS(SEXP x, int v) {
+	unimplemented("SET_ENVFLAGS");
+}
+
+void SET_FRAME(SEXP x, SEXP v) {
+    unimplemented("SET_FRAME");
+}
+
+void SET_ENCLOS(SEXP x, SEXP v) {
+	unimplemented("SET_ENCLOS");
+}
+
+void SET_HASHTAB(SEXP x, SEXP v) {
+	unimplemented("SET_HASHTAB");
+}
+
+SEXP PRCODE(SEXP x) {
+	return checkRef(((call_PRCODE) callbacks[PRCODE_x])(x));
+}
+
+SEXP PRENV(SEXP x) {
+	return checkRef(((call_PRENV) callbacks[PRENV_x])(x));
+}
+
+SEXP PRVALUE(SEXP x) {
+	return checkRef(((call_PRVALUE) callbacks[PRVALUE_x])(x));
+}
+
+int PRSEEN(SEXP x) {
+	return ((call_PRSEEN) callbacks[PRSEEN_x])(x);
+}
+
+void SET_PRSEEN(SEXP x, int v) {
+    unimplemented("SET_PRSEEN");
+}
+
+void SET_PRENV(SEXP x, SEXP v) {
+    unimplemented("SET_PRENV");
+}
+
+void SET_PRVALUE(SEXP x, SEXP v) {
+    unimplemented("SET_PRVALUE");
+}
+
+void SET_PRCODE(SEXP x, SEXP v) {
+    unimplemented("SET_PRCODE");
+}
+
+int TRUELENGTH(SEXP x){
+    unimplemented("unimplemented");
+    return 0;
+}
+
+
+void SETLENGTH(SEXP x, int v){
+    unimplemented("SETLENGTH");
+}
+
+
+void SET_TRUELENGTH(SEXP x, int v){
+    unimplemented("SET_TRUELENGTH");
+}
+
+
+R_xlen_t XLENGTH(SEXP x){
+    // xlength seems to be used for long vectors (no such thing in FastR at the moment)
+    return LENGTH(x);
+}
+
+
+R_xlen_t XTRUELENGTH(SEXP x){
+	unimplemented("XTRUELENGTH");
+	return 0;
+}
+
+
+int IS_LONG_VEC(SEXP x){
+	unimplemented("IS_LONG_VEC");
+	return 0;
+}
+
+
+int LEVELS(SEXP x){
+	unimplemented("LEVELS");
+	return 0;
+}
+
+
+int SETLEVELS(SEXP x, int v){
+	unimplemented("SETLEVELS");
+	return 0;
+}
+
+Rcomplex *COMPLEX(SEXP x){
+	return (Rcomplex*) unimplemented("COMPLEX");
+}
+
+SEXP STRING_ELT(SEXP x, R_xlen_t i) {
+	return checkRef(((call_STRING_ELT) callbacks[STRING_ELT_x])(x, i));
+}
+
+
+SEXP VECTOR_ELT(SEXP x, R_xlen_t i){
+	return checkRef(((call_VECTOR_ELT) callbacks[VECTOR_ELT_x])(x, i));
+}
+
+void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v){
+    ((call_SET_STRING_ELT) callbacks[SET_STRING_ELT_x])(x, i, v);
+}
+
+
+SEXP SET_VECTOR_ELT(SEXP x, R_xlen_t i, SEXP v){
+	return checkRef(((call_SET_VECTOR_ELT) callbacks[SET_VECTOR_ELT_x])(x, i, v));
+}
+
+SEXP *STRING_PTR(SEXP x){
+	unimplemented("STRING_PTR");
+	return NULL;
+}
+
+
+SEXP * NORET VECTOR_PTR(SEXP x){
+	unimplemented("VECTOR_PTR");
+}
+
+SEXP Rf_asChar(SEXP x){
+	return checkRef(((call_Rf_asChar) callbacks[Rf_asChar_x])(x));
+}
+
+SEXP Rf_PairToVectorList(SEXP x){
+	return checkRef(((call_Rf_PairToVectorList) callbacks[Rf_PairToVectorList_x])(x));
+}
+
+SEXP Rf_VectorToPairList(SEXP x){
+	return unimplemented("Rf_VectorToPairList");
+}
+
+SEXP Rf_asCharacterFactor(SEXP x){
+	unimplemented("Rf_VectorToPairList");
+	return NULL;
+}
+
+int Rf_asLogical(SEXP x){
+	return ((call_Rf_asLogical) callbacks[Rf_asLogical_x])(x);
+}
+
+int Rf_asInteger(SEXP x) {
+	return ((call_Rf_asInteger) callbacks[Rf_asInteger_x])(x);
+}
+
+double Rf_asReal(SEXP x) {
+	return ((call_Rf_asReal) callbacks[Rf_asReal_x])(x);
+}
+
+Rcomplex Rf_asComplex(SEXP x){
+	unimplemented("Rf_asComplex");
+	Rcomplex c; return c;
+}
+
+int TYPEOF(SEXP x) {
+	return (int) ((call_TYPEOF) callbacks[TYPEOF_x])(x);
+}
+
+SEXP ATTRIB(SEXP x){
+    return ((call_ATTRIB) callbacks[ATTRIB_x])(x);
+}
+
+int OBJECT(SEXP x){
+	return (int) ((call_OBJECT) callbacks[OBJECT_x])(x);
+}
+
+int MARK(SEXP x){
+    unimplemented("MARK");
+    return 0;
+}
+
+int NAMED(SEXP x){
+	return (int) ((call_NAMED) callbacks[NAMED_x])(x);
+}
+
+int REFCNT(SEXP x){
+    unimplemented("REFCNT");
+    return 0;
+}
+
+void SET_OBJECT(SEXP x, int v){
+    unimplemented("SET_OBJECT");
+}
+
+void SET_TYPEOF(SEXP x, int v){
+    unimplemented("SET_TYPEOF");
+}
+
+SEXP SET_TYPEOF_FASTR(SEXP x, int v){
+	return checkRef(((call_SET_TYPEOF_FASTR) callbacks[SET_TYPEOF_FASTR_x])(x, v));
+}
+
+void SET_NAMED(SEXP x, int v){
+    unimplemented("SET_NAMED");
+}
+
+void SET_ATTRIB(SEXP x, SEXP v){
+    unimplemented("SET_ATTRIB");
+}
+
+void DUPLICATE_ATTRIB(SEXP to, SEXP from){
+	((call_DUPLICATE_ATTRIB) callbacks[DUPLICATE_ATTRIB_x])(to, from);
+}
+
+void R_qsort_I  (double *v, int *II, int i, int j) {
+	unimplemented("R_qsort_I");
+}
+
+void R_qsort_int_I(int *iv, int *II, int i, int j) {
+	unimplemented("R_qsort_int_I");
+}
+
+R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
+	return (R_len_t) unimplemented("R_BadLongVector");
+}
+
+int IS_S4_OBJECT(SEXP x) {
+	return (int) ((call_IS_S4_OBJECT) callbacks[IS_S4_OBJECT_x])(x);
+}
+
+void SET_S4_OBJECT(SEXP x) {
+	((call_SET_S4_OBJECT) callbacks[SET_S4_OBJECT_x])(x);
+}
+
+void UNSET_S4_OBJECT(SEXP x) {
+	((call_UNSET_S4_OBJECT) callbacks[UNSET_S4_OBJECT_x])(x);
+}
+
+Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
+	return (Rboolean) unimplemented("R_ToplevelExec");
+}
+
+SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data,
+		       void (*cleanfun)(void *), void *cleandata) {
+	return unimplemented("R_ExecWithCleanup");
+}
+
+/* Environment and Binding Features */
+void R_RestoreHashCount(SEXP rho) {
+	unimplemented("R_RestoreHashCount");
+}
+
+Rboolean R_IsPackageEnv(SEXP rho) {
+	unimplemented("R_IsPackageEnv");
+}
+
+SEXP R_PackageEnvName(SEXP rho) {
+	return unimplemented("R_PackageEnvName");
+}
+
+SEXP R_FindPackageEnv(SEXP info) {
+	return unimplemented("R_FindPackageEnv");
+}
+
+Rboolean R_IsNamespaceEnv(SEXP rho) {
+	return (Rboolean) unimplemented("R_IsNamespaceEnv");
+}
+
+SEXP R_FindNamespace(SEXP info) {
+	return checkRef(((call_R_FindNamespace) callbacks[R_FindNamespace_x])(info));
+}
+
+SEXP R_NamespaceEnvSpec(SEXP rho) {
+	return unimplemented("R_NamespaceEnvSpec");
+}
+
+void R_LockEnvironment(SEXP env, Rboolean bindings) {
+	unimplemented("R_LockEnvironment");
+}
+
+Rboolean R_EnvironmentIsLocked(SEXP env) {
+	unimplemented("");
+}
+
+void R_LockBinding(SEXP sym, SEXP env) {
+	unimplemented("R_LockBinding");
+}
+
+void R_unLockBinding(SEXP sym, SEXP env) {
+	unimplemented("R_unLockBinding");
+}
+
+void R_MakeActiveBinding(SEXP sym, SEXP fun, SEXP env) {
+	unimplemented("R_MakeActiveBinding");
+}
+
+Rboolean R_BindingIsLocked(SEXP sym, SEXP env) {
+	return (Rboolean) ((call_R_BindingIsLocked) callbacks[R_BindingIsLocked_x])(sym, env);
+}
+
+Rboolean R_BindingIsActive(SEXP sym, SEXP env) {
+    // TODO: for now, I believe all bindings are false
+    return (Rboolean)0;
+}
+
+Rboolean R_HasFancyBindings(SEXP rho) {
+	return (Rboolean) unimplemented("R_HasFancyBindings");
+}
+
+Rboolean Rf_isS4(SEXP x) {
+    return IS_S4_OBJECT(x);
+}
+
+SEXP Rf_asS4(SEXP x, Rboolean b, int i) {
+	unimplemented("Rf_asS4");
+}
+
+static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) {
+	unimplemented("R_tryEvalInternal");
+}
+
+SEXP R_tryEval(SEXP x, SEXP y, int *ErrorOccurred) {
+	return R_tryEvalInternal(x, y, ErrorOccurred, 0);
+}
+
+SEXP R_tryEvalSilent(SEXP x, SEXP y, int *ErrorOccurred) {
+	return R_tryEvalInternal(x, y, ErrorOccurred, 1);
+}
+
+double R_atof(const char *str) {
+	unimplemented("R_atof");
+	return 0;
+}
+
+double R_strtod(const char *c, char **end) {
+	unimplemented("R_strtod");
+	return 0;
+}
+
+SEXP R_PromiseExpr(SEXP x) {
+	return checkRef(((call_R_PromiseExpr) callbacks[R_PromiseExpr_x])(x));
+}
+
+SEXP R_ClosureExpr(SEXP x) {
+	return unimplemented("R_ClosureExpr");
+}
+
+SEXP R_forceAndCall(SEXP e, int n, SEXP rho) {
+	return unimplemented("R_forceAndCall");
+}
+
+SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot) {
+	return checkRef(((call_R_MakeExternalPtr) callbacks[R_MakeExternalPtr_x])(p, tag, prot));
+}
+
+void *R_ExternalPtrAddr(SEXP s) {
+	return ((call_R_ExternalPtrAddr) callbacks[R_ExternalPtrAddr_x])(s);
+}
+
+SEXP R_ExternalPtrTag(SEXP s) {
+	return checkRef(((call_R_ExternalPtrTag) callbacks[R_ExternalPtrTag_x])(s));
+}
+
+SEXP R_ExternalPtrProtected(SEXP s) {
+	return checkRef(((call_R_ExternalPtrProtected) callbacks[R_ExternalPtrProtected_x])(s));
+}
+
+void R_SetExternalPtrAddr(SEXP s, void *p) {
+	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p);
+}
+
+void R_SetExternalPtrTag(SEXP s, SEXP tag) {
+	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, tag);
+}
+
+void R_SetExternalPtrProtected(SEXP s, SEXP p) {
+	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p);
+}
+
+void R_ClearExternalPtr(SEXP s) {
+	R_SetExternalPtrAddr(s, NULL);
+}
+
+void R_RegisterFinalizer(SEXP s, SEXP fun) {
+	// TODO implement, but not fail for now
+}
+void R_RegisterCFinalizer(SEXP s, R_CFinalizer_t fun) {
+	// TODO implement, but not fail for now
+}
+
+void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit) {
+	// TODO implement, but not fail for now
+
+}
+
+void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit) {
+	// TODO implement, but not fail for now
+}
+
+void R_RunPendingFinalizers(void) {
+	// TODO implement, but not fail for now
+}
+
+SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit) {
+	unimplemented("R_MakeWeakRef");
+}
+
+SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit) {
+	unimplemented("R_MakeWeakRefC");
+}
+
+SEXP R_WeakRefKey(SEXP w) {
+	unimplemented("R_WeakRefKey");
+}
+
+SEXP R_WeakRefValue(SEXP w) {
+	unimplemented("R_WeakRefValue");
+}
+
+void R_RunWeakRefFinalizer(SEXP w) {
+	// TODO implement, but not fail for now
+}
+
+SEXP R_do_slot(SEXP obj, SEXP name) {
+	return checkRef(((call_R_do_slot) callbacks[R_do_slot_x])(obj, name));
+}
+
+SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
+	return checkRef(((call_R_do_slot_assign) callbacks[R_do_slot_assign_x])(obj, name, value));
+}
+
+int R_has_slot(SEXP obj, SEXP name) {
+	return (int) unimplemented("R_has_slot");
+}
+
+SEXP R_do_MAKE_CLASS(const char *what) {
+	return checkRef(((call_R_do_MAKE_CLASS) callbacks[R_do_MAKE_CLASS_x])(what));
+}
+
+SEXP R_getClassDef (const char *what) {
+	return unimplemented("R_getClassDef");
+}
+
+SEXP R_do_new_object(SEXP class_def) {
+	return checkRef(((call_R_do_new_object) callbacks[R_do_new_object_x])(class_def));
+}
+
+static SEXP nfiGetMethodsNamespace() {
+    return checkRef(((call_R_MethodsNamespace) callbacks[R_MethodsNamespace_x])());
+}
+
+int R_check_class_etc (SEXP x, const char **valid) {
+	return R_check_class_etc_helper(x, valid, nfiGetMethodsNamespace);
+}
+
+SEXP R_PreserveObject_FASTR(SEXP x) {
+	return newObjectHandle(x);
+}
+
+void R_ReleaseObject(SEXP x) {
+	releaseObjectHandle(x);
+}
+
+void R_dot_Last(void) {
+	unimplemented("R_dot_Last");
+}
+
+
+Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
+	return (Rboolean) ((call_R_compute_identical) callbacks[R_compute_identical_x])(x, y, flags);
+}
+
+void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
+	((call_Rf_copyListMatrix) callbacks[Rf_copyListMatrix_x])(s, t, byrow);
+}
+
+void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
+	((call_Rf_copyMatrix) callbacks[Rf_copyMatrix_x])(s, t, byrow);
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/appl_rffi.c
similarity index 55%
rename from com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c
rename to com.oracle.truffle.r.native/fficall/src/truffle_common/appl_rffi.c
index 5ebdbc607dac1ec9eea0b17891b24be47328121f..f54ca8877376e9c2364ffa94b07e260a34f41354 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/appl_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/appl_rffi.c
@@ -26,15 +26,35 @@
 extern void dqrdc2_(double *x, int *ldx, int *n, int *p, double *tol, int *rank, double *qraux, int* pivot, double *work);
 extern void dqrcf_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *b, int* info);
 extern void dqrls_(double *x, int *n, int *p, double *y, int *ny, double *tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work);
+extern void dqrqty_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *qty);
+extern void dqrqy_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *qy);
+extern void dqrrsd_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *rsd);
+extern void dqrxb_(double *x, int *n, int *k, double *qraux, double *y, int *ny, double *xb);
 
-void call_dqrdc2(double *x, int ldx, int n, int p, double tol, int *rank, double *qraux, int* pivot, double *work) {
+void call_appl_dqrdc2(double *x, int ldx, int n, int p, double tol, int *rank, double *qraux, int* pivot, double *work) {
 	dqrdc2_(x, &ldx, &n, &p, &tol, rank, qraux, pivot, work);
 }
 
-void call_dqrcf(double *x, int n, int k, double *qraux, double *y, int ny, double *b, int* info) {
+void call_appl_dqrcf(double *x, int n, int k, double *qraux, double *y, int ny, double *b, int* info) {
 	dqrcf_(x, &n, &k, qraux, y, &ny, b, info);
 }
 
-void call_dqrls(double *x, int n, int p, double *y, int ny, double tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work) {
+void call_appl_dqrls(double *x, int n, int p, double *y, int ny, double tol, double *b, double *rsd, double *qty, int *k, int *jpvt, double *qraux, double *work) {
 	dqrls_(x, &n, &p, y, &ny, &tol, b, rsd, qty, k, jpvt, qraux, work);
 }
+
+void call_appl_dqrqty(double *x, int n, int k, double *qraux, double *y, int ny, double *qty) {
+	dqrqty_(x, &n, &k, qraux, y, &ny, qty);
+}
+
+void call_appl_dqrqy(double *x, int n, int k, double *qraux, double *y, int ny, double *qy) {
+	dqrqy_(x, &n, &k, qraux, y, &ny, qy);
+}
+
+void call_appl_dqrrsd(double *x, int n, int k, double *qraux, double *y, int ny, double *rsd) {
+	dqrrsd_(x, &n, &k, qraux, y, &ny, rsd);
+}
+
+void call_appl_dqrxb(double *x, int n, int k, double *qraux, double *y, int ny, double *xb) {
+	dqrxb_(x, &n, &k, qraux, y, &ny, xb);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.h
new file mode 100644
index 0000000000000000000000000000000000000000..72cd777fbce41e2be9027ef5dbd82e174b6cec16
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/base_rffi.h
@@ -0,0 +1,76 @@
+/*
+ * 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
+ * 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.
+ */
+#include <rffiutils.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <glob.h>
+#include <sys/utsname.h>
+#include <errno.h>
+
+
+void call_base_uname(void (*call_uname_setfields)(char *sysname, char *release, char *version, char *machine, char *nodename)) {
+	struct utsname name;
+
+	uname(&name);
+	call_uname_setfields(ensure_string(name.sysname), ensure_string(name.release), ensure_string(name.version),
+			ensure_string(name.machine), ensure_string(name.nodename));
+}
+
+int errfunc(const char* path, int error) {
+	return 0;
+}
+
+void call_base_glob(void *closure, char *pattern) {
+	void (*call_addpath)(void *path) = closure;
+
+	glob_t globstruct;
+	int rc = glob(pattern, 0, errfunc, &globstruct);
+	if (rc == 0) {
+		int i;
+		for (i = 0; i < globstruct.gl_pathc; i++) {
+			char *path = globstruct.gl_pathv[i];
+			call_addpath(ensure_string(path));
+		}
+	}
+}
+
+void call_base_readlink(void (*call_setresult)(void *link, int cerrno), char *path) {
+	char *link = NULL;
+	int cerrno = 0;
+    char buf[4096];
+    int len = readlink(path, buf, 4096);
+    if (len == -1) {
+    	cerrno = errno;
+    } else {
+    	buf[len] = 0;
+    	link = buf;
+    }
+	call_setresult(ensure_string(link), cerrno);
+}
+
+void call_base_strtol(void (*call_setresult)(long result, int cerrno), char *s, int base) {
+    long rc = strtol(s, NULL, base);
+	call_setresult(rc, errno);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/caccess/caccess.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/caccess.c
similarity index 100%
rename from com.oracle.truffle.r.native/fficall/src/caccess/caccess.c
rename to com.oracle.truffle.r.native/fficall/src/truffle_common/caccess.c
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/lapack_rffi.c
similarity index 75%
rename from com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c
rename to com.oracle.truffle.r.native/fficall/src/truffle_common/lapack_rffi.c
index 17d0589252ae023aebe08722a207ec989f4a4746..e543efacf88654ecfabdae7fa4b30c020e984685 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/lapack_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/lapack_rffi.c
@@ -25,7 +25,7 @@
 
 extern void ilaver_(int *major, int *minor, int *patch);
 
-void call_ilaver(int* version) {
+void call_lapack_ilaver(int* version) {
 	int major;
 	int minor;
 	int patch;
@@ -37,7 +37,7 @@ void call_ilaver(int* version) {
 
 extern int dgeev_(char *jobVL, char *jobVR, int *n, double *a, int *lda, double *wr, double *wi, double *vl, int *ldvl, double *vr, int *ldvr, double *work, int *lwork, int *info);
 
-int call_dgeev(char jobVL, char jobVR, int n, double *a, int lda, double *wr, double *wi, double *vl, int ldvl, double *vr, int ldvr, double *work, int lwork) {
+int call_lapack_dgeev(char jobVL, char jobVR, int n, double *a, int lda, double *wr, double *wi, double *vl, int ldvl, double *vr, int ldvr, double *work, int lwork) {
     int info;
     dgeev_(&jobVL, &jobVR, &n, a, &lda, wr, wi, vl, &ldvl, vr, &ldvr, work, &lwork, &info);
     return info;
@@ -46,7 +46,7 @@ int call_dgeev(char jobVL, char jobVR, int n, double *a, int lda, double *wr, do
 extern int dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau, double *work, int *lwork, int *info);
 
 
-int call_dgeqp3(int m, int n, double *a, int lda, int *jpvt, double *tau, double *work, int lwork) {
+int call_lapack_dgeqp3(int m, int n, double *a, int lda, int *jpvt, double *tau, double *work, int lwork) {
     int info;
     dgeqp3_(&m, &n, a, &lda, jpvt, tau, work, &lwork, &info);
     return info;
@@ -54,7 +54,7 @@ int call_dgeqp3(int m, int n, double *a, int lda, int *jpvt, double *tau, double
 
 extern int dormqr_(char *side, char *trans, int *m, int *n, int *k, double *a, int *lda, double *tau, double *c, int *ldc, double *work, int *lwork, int *info);
 
-int call_dormqr(char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, double *work, int lwork) {
+int call_lapack_dormqr(char side, char trans, int m, int n, int k, double *a, int lda, double *tau, double *c, int ldc, double *work, int lwork) {
     int info;
     dormqr_(&side, &trans, &m, &n, &k, a, &lda, tau, c, &ldc, work, &lwork, &info);
     return info;
@@ -63,7 +63,7 @@ int call_dormqr(char side, char trans, int m, int n, int k, double *a, int lda,
 extern int dtrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs, double *a, int *lda, double *b, int *ldb, int *info);
 
 
-int call_dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double *a, int lda, double *b, int ldb) {
+int call_lapack_dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double *a, int lda, double *b, int ldb) {
     int info;
     dtrtrs_(&uplo, &trans, &diag, &n, &nrhs, a, &lda, b, &ldb, &info);
     return info;
@@ -71,7 +71,7 @@ int call_dtrtrs(char uplo, char trans, char diag, int n, int nrhs, double *a, in
 
 extern int dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
 
-int call_dgetrf(int m, int n, double *a, int lda, int *ipiv) {
+int call_lapack_dgetrf(int m, int n, double *a, int lda, int *ipiv) {
     int info;
     dgetrf_(&m, &n, a, &lda, ipiv, &info);
     return info;
@@ -79,7 +79,7 @@ int call_dgetrf(int m, int n, double *a, int lda, int *ipiv) {
 
 extern int dpotrf_(char *uplo, int *n, double *a, int *lda, int *info);
 
-int call_dpotrf(char uplo, int n, double *a, int lda) {
+int call_lapack_dpotrf(char uplo, int n, double *a, int lda) {
     int info;
     dpotrf_(&uplo, &n, a, &lda, &info);
     return info;
@@ -87,7 +87,7 @@ int call_dpotrf(char uplo, int n, double *a, int lda) {
 
 extern int dpotri_(char *uplo, int *n, double *a, int *lda, int *info);
 
-int call_dpotri(char uplo, int n, double *a, int lda) {
+int call_lapack_dpotri(char uplo, int n, double *a, int lda) {
     int info;
     dpotri_(&uplo, &n, a, &lda, &info);
     return info;
@@ -95,7 +95,7 @@ int call_dpotri(char uplo, int n, double *a, int lda) {
 
 extern int dpstrf_(char *uplo, int *n, double *a, int *lda, int *piv, int *rank, double *tol, double *work, int *info);
 
-int call_dpstrf(char uplo, int n, double *a, int lda, int *piv, int *rank, double tol, double *work) {
+int call_lapack_dpstrf(char uplo, int n, double *a, int lda, int *piv, int *rank, double tol, double *work) {
     int info;
     dpstrf_(&uplo, &n, a, &lda, piv, rank, &tol, work, &info);
     return info;
@@ -103,7 +103,7 @@ int call_dpstrf(char uplo, int n, double *a, int lda, int *piv, int *rank, doubl
 
 extern int dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b, int *ldb, int *info);
 
-int call_dgesv(int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb) {
+int call_lapack_dgesv(int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ldb) {
     int info;
     dgesv_(&n, &nrhs, a, &lda, ipiv, b, &ldb, &info);
     return info;
@@ -111,14 +111,14 @@ int call_dgesv(int n, int nrhs, double *a, int lda, int *ipiv, double *b, int ld
 
 extern double dlange_(char *norm, int *m, int *n, double *a, int *lda, double *work);
 
-double call_dlange(char norm, int m, int n, double *a, int lda, double *work) {
+double call_lapack_dlange(char norm, int m, int n, double *a, int lda, double *work) {
     double info = dlange_(&norm, &m, &n, a, &lda, work);
     return info;
 }
 
 extern int dgecon_(char *norm, int *n, double *a, int *lda, double *anorm, double *rcond, double *work, int *iwork, int *info);
 
-int call_dgecon(char norm, int n, double *a, int lda, double anorm, double *rcond, double *work, int *iwork) {
+int call_lapack_dgecon(char norm, int n, double *a, int lda, double anorm, double *rcond, double *work, int *iwork) {
     int info;
     dgecon_(&norm, &n, a, &lda, &anorm, rcond, work, iwork, &info);
     return info;
@@ -127,7 +127,7 @@ int call_dgecon(char norm, int n, double *a, int lda, double anorm, double *rcon
 extern int dsyevr_(char *jobz, char *range, char *uplo, int *n, double* a, int *lda, double *vl, double *vu, int *il, int *iu, double *abstol, int* m, double* w,
                 double* z, int *ldz, int* isuppz, double* work, int *lwork, int* iwork, int *liwork, int* info);
 
-int call_dsyevr(char jobz, char range, char uplo, int n, double *a, int lda, double vl, double vu, int il, int iu, double abstol, int *m, double *w,
+int call_lapack_dsyevr(char jobz, char range, char uplo, int n, double *a, int lda, double vl, double vu, int il, int iu, double abstol, int *m, double *w,
 		                    double *z, int ldz, int *isuppz, double *work, int lwork, int *iwork, int liwork) {
     int info;
     dsyevr_(&jobz, &range, &uplo, &n, a, &lda, &vl, &vu, &il, &iu, &abstol, m, w,
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_common/misc_rffi.c
similarity index 100%
rename from com.oracle.truffle.r.native/fficall/src/truffle_nfi/misc_rffi.c
rename to com.oracle.truffle.r.native/fficall/src/truffle_common/misc_rffi.c
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_common/pcre_rffi.h b/com.oracle.truffle.r.native/fficall/src/truffle_common/pcre_rffi.h
new file mode 100644
index 0000000000000000000000000000000000000000..0b20885465dd5f22ce35bd777247b17662c5cb95
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_common/pcre_rffi.h
@@ -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.
+ */
+#include <rffiutils.h>
+
+#define PCRE_INFO_CAPTURECOUNT       2
+#define PCRE_INFO_NAMEENTRYSIZE      7
+#define PCRE_INFO_NAMECOUNT          8
+#define PCRE_INFO_NAMETABLE          9
+
+extern char *pcre_maketables();
+extern void *pcre_compile(char *pattern, int options, char **errorMessage, int *errOffset, char *tables);
+extern int  pcre_exec(void *code, void *extra, char* subject, int subjectLength, int startOffset, int options, int *ovector, int ovecSize);
+int pcre_fullinfo(void *code, void *extra, int what, void *where);
+extern void pcre_free(void *code);
+
+void call_pcre_compile(void (*makeresult)(long result, char *errMsg, int errOffset), char *pattern, int options, long tables) {
+	char *errorMessage;
+	int errOffset;
+	void *pcre_result = pcre_compile(pattern, options, &errorMessage, &errOffset, (char*) tables);
+	void *msg = NULL;
+	if (pcre_result == NULL) {
+		msg = ensure_string(errorMessage);
+	}	makeresult((long) pcre_result, msg, errOffset);
+}
+
+int call_pcre_getcapturecount(long code, long extra) {
+    int captureCount;
+	int rc = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_CAPTURECOUNT, &captureCount);
+    return rc < 0 ? rc : captureCount;
+}
+
+int call_pcre_getcapturenames(void (*setcapturename)(int i, char *name), long code, long extra) {
+    int nameCount;
+    int nameEntrySize;
+    char* nameTable;
+    int res;
+	res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMECOUNT, &nameCount);
+    if (res < 0) {
+        return res;
+    }
+    res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMEENTRYSIZE, &nameEntrySize);
+    if (res < 0) {
+        return res;
+    }
+	res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMETABLE, &nameTable);
+    if (res < 0) {
+        return res;
+    }
+    // from GNU R's grep.c
+	for(int i = 0; i < nameCount; i++) {
+	    char* entry = nameTable + nameEntrySize * i;
+	    int captureNum = (entry[0] << 8) + entry[1] - 1;
+	    setcapturename(captureNum, ensure_string(entry + 2));
+    }
+    return res;
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Makefile b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Makefile
index 99821495d2e45ace8ec7db91c0034b62688c4f92..3077166a29809953e1927d64f6e8198da6d4fcb8 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Makefile
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Makefile
@@ -21,13 +21,6 @@
 # questions.
 #
 
-# This compiles everything in this directory, plus all the code in ../common,
-# including the code referenced in common from GnuR, with the -DFASTR_LLVM flag.
-# This creates an object file with no compiled C/Fortan code, just the equivalent LLVM IR
-# Since, at present, the resulting shared library (libR) must include both the real and the dummy
-# object files, we have to avoid a name clash on the object file,which we achieve by appending
-# "_llvm" to the name of the object file. The wrapper compilers use this name to create the
-# symbol that is looked up to find the LLVM IR at runtime.
 
 # N.B. -g -O2 (which is the FFLAGS default from platform.mk) is currently suppressed
 # due to sulong limitations
@@ -51,40 +44,37 @@ GNUR_MAIN_C_FILES = colors.c devices.c engine.c format.c graphics.c plot.c plot3
 GNUR_MAIN_SRC = $(GNUR_HOME)/src/main
 
 GNUR_C_OBJECTS := $(addprefix $(OBJ)/, $(GNUR_APPL_C_FILES:.c=.o) $(GNUR_MAIN_C_FILES:.c=.o))
-LLVM_GNUR_C_OBJECTS := $(GNUR_C_OBJECTS:.o=_llvm.o)
-#$(info LLVM_GNUR_C_OBJECTS: $(LLVM_GNUR_C_OBJECTS))
 
 GNUR_F_OBJECTS := $(addprefix $(OBJ)/, $(notdir $(GNUR_APPL_F_FILES:.f=.o)))
-LLVM_GNUR_F_OBJECTS := $(GNUR_F_OBJECTS:.o=_llvm.o)
-#$(info LLVM_GNUR_F_OBJECTS: $(LLVM_GNUR_F_OBJECTS))
 
 C_HDRS := $(wildcard *.h)
 
 LOCAL_C_SOURCES := $(wildcard *.c) 
 COMMON_C_SOURCES := $(wildcard ../common/*.c)
-C_SOURCES := $(LOCAL_C_SOURCES) $(COMMON_C_SOURCES)
+TRUFFLE_COMMON_C_SOURCES := $(wildcard ../truffle_common/*.c)
+TRUFFLE_COMMON_H_SOURCES := $(wildcard ../truffle_common/*.h)
+C_SOURCES := $(LOCAL_C_SOURCES) $(COMMON_C_SOURCES) $(TRUFFLE_COMMON_C_SOURCES)
+#$(info C_SOURCES=$(C_SOURCES))
 LOCAL_C_OBJECTS := $(addprefix $(OBJ)/, $(LOCAL_C_SOURCES:.c=.o))
 COMMON_C_OBJECTS := $(addprefix $(OBJ)/, $(notdir $(COMMON_C_SOURCES:.c=.o)))
-C_OBJECTS := $(LOCAL_C_OBJECTS) $(COMMON_C_OBJECTS)
-LLVM_C_OBJECTS := $(C_OBJECTS:.o=_llvm.o)
-#$(info LLVM_C_OBJECTS=$(LLVM_C_OBJECTS))
+TRUFFLE_COMMON_C_OBJECTS := $(addprefix $(OBJ)/, $(notdir $(TRUFFLE_COMMON_C_SOURCES:.c=.o)))
+C_OBJECTS := $(LOCAL_C_OBJECTS) $(COMMON_C_OBJECTS) $(TRUFFLE_COMMON_C_OBJECTS)
+#$(info C_OBJECTS=$(C_OBJECTS))
 
 SULONG_DIR = $(abspath $(FASTR_R_HOME)/../sulong)
 
 SULONG_INCLUDES = -I$(SULONG_DIR)/include
-FFI_INCLUDES = -I$(TOPDIR)/include
-LOCAL_INCLUDES = -I . -I $(abspath ../include)
+FFI_INCLUDES = -I$(TOPDIR)/include -I$(TOPDIR)/include/R_ext
+LOCAL_INCLUDES = -I . -I $(abspath ../include) -I $(abspath ../common) 
 
 INCLUDES := $(LOCAL_INCLUDES) $(FFI_INCLUDES) $(SULONG_INCLUDES)
 
-CFLAGS := $(CFLAGS) -DFASTR_LLVM
-#FFLAGS := $(FFLAGS) -DFASTR_LLVM
-FFLAGS := -DFASTR_LLVM
+FFLAGS :=
 
 # uncomment to see exactly where headers are being read from
 #CFLAGS := $(CFLAGS) -H
 
-all: Makefile $(LLVM_C_OBJECTS) $(LLVM_GNUR_COBJECTS) $(LLVM_GNUR_F_OBJECTS)
+all: Makefile $(C_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS)
 
 $(C_OBJECTS): | $(OBJ)
 
@@ -95,19 +85,22 @@ $(GNUR_F_OBJECTS): | $(OBJ)
 $(OBJ):
 	mkdir -p $(OBJ)
 
-$(OBJ)/%_llvm.o: $(GNUR_APPL_SRC)/%.c
+$(OBJ)/%.o: $(GNUR_APPL_SRC)/%.c
 	$(CC) $(CFLAGS) $(INCLUDES) $(GNUR_HEADER_DEFS) $(SUPPRESS_WARNINGS) -c $< -o $@
 
-$(OBJ)/%_llvm.o: $(GNUR_MAIN_SRC)/%.c
+$(OBJ)/%.o: $(GNUR_MAIN_SRC)/%.c
 	$(CC) $(CFLAGS) $(INCLUDES) $(GNUR_HEADER_DEFS) $(SUPPRESS_WARNINGS) -c $< -o $@
 
-$(OBJ)/%_llvm.o: %.c $(FASTR_NATIVE_DIR)/include/Rinternals.h rffiutils.h
-	$(CC) $(CFLAGS) $(INCLUDES) $(GNUR_HEADER_DEFS) -I../variable_defs $(SUPPRESS_WARNINGS) -c $< -o $@
+$(OBJ)/%.o: %.c $(FASTR_NATIVE_DIR)/include/Rinternals.h rffiutils.h $(TRUFFLE_COMMON_H_SOURCES) ../common/rffi_upcallsindex.h
+	$(CC) $(CFLAGS) $(INCLUDES) $(GNUR_HEADER_DEFS) $(SUPPRESS_WARNINGS) -c $< -o $@
 
-$(OBJ)/%_llvm.o: ../common/%.c $(FASTR_NATIVE_DIR)/include/Rinternals.h
+$(OBJ)/%.o: ../common/%.c $(FASTR_NATIVE_DIR)/include/Rinternals.h
 	$(CC) $(CFLAGS) $(INCLUDES) $(GNUR_HEADER_DEFS) $(SUPPRESS_WARNINGS) -c $< -o $@
 
-$(OBJ)/%_llvm.o: $(GNUR_APPL_SRC)/%.f
+$(OBJ)/%.o: ../truffle_common/%.c 
+	$(CC) $(CFLAGS) $(INCLUDES) $(SUPPRESS_WARNINGS) -c $< -o $@
+
+$(OBJ)/%.o: $(GNUR_APPL_SRC)/%.f
 	$(F77) $(FFLAGS) $(FPICFLAGS) -c $< -o $@
 
 clean:
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c
new file mode 100644
index 0000000000000000000000000000000000000000..352ca45ce1e124a6d5a1c519da1714cf37497664
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c
@@ -0,0 +1,117 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995-2015, The R Core Team
+ * Copyright (c) 2003, The R Foundation
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+#include <rffiutils.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define T_MEM_TABLE_INITIAL_SIZE 0
+// The table of transient objects that have been allocated dur the current FFI call
+static void **tMemTable;
+// hwm of tMemTable
+static int tMemTableIndex;
+static int tMemTableLength;
+
+void *R_chk_calloc(size_t nelem, size_t elsize);
+
+// Memory that is auto-reclaimed across FFI calls
+char *R_alloc(size_t n, int size) {
+    void *p = R_chk_calloc(n, size);
+    if (tMemTableIndex >= tMemTableLength) {
+	int newLength = 2 * tMemTableLength;
+	void *newtMemTable = malloc(sizeof(void*) * newLength);
+	if (newtMemTable == NULL) {
+	    fatalError("malloc failure");
+	}
+	memcpy(newtMemTable, tMemTable, tMemTableLength * sizeof(void*));
+	free(tMemTable);
+	tMemTable = newtMemTable;
+	tMemTableLength = newLength;
+    }
+    tMemTable[tMemTableIndex] = p;
+    return (char*) p;
+}
+
+char* S_alloc(long n, int size) {
+	char *p = R_alloc(n, size);
+	memset(p, 0, n);
+	return p;
+}
+
+char* S_realloc(char *p, long a, long b, int size) {
+	return unimplemented("S_realloc");
+}
+
+void allocExit() {
+    int i;
+    for (i = 0; i < tMemTableIndex; i++) {
+	free(tMemTable[i]);
+    }
+}
+
+void *R_chk_calloc(size_t nelem, size_t elsize) {
+    void *p;
+#ifndef HAVE_WORKING_CALLOC
+    if (nelem == 0)
+	return (NULL);
+#endif
+    p = calloc(nelem, elsize);
+    if (!p) /* problem here is that we don't have a format for size_t. */
+	error(_("'Calloc' could not allocate memory (%.0f of %u bytes)"),
+		(double) nelem, elsize);
+    return (p);
+}
+
+void *R_chk_realloc(void *ptr, size_t size) {
+    void *p;
+    /* Protect against broken realloc */
+    if(ptr) p = realloc(ptr, size); else p = malloc(size);
+    if(!p)
+	error(_("'Realloc' could not re-allocate memory (%.0f bytes)"),
+	      (double) size);
+    return(p);
+}
+
+void R_chk_free(void *ptr) {
+    if(ptr) {
+	    free(ptr);
+    }
+}
+
+int VMAX_MAGIC = 1234;
+
+void* vmaxget(void) {
+//    unimplemented("vmaxget");
+    // ignored
+    return &VMAX_MAGIC;
+}
+
+void vmaxset(const void * x) {
+//    unimplemented("vmaxget");
+    if (x != &VMAX_MAGIC) {
+	unimplemented("vmaxset with different value");
+    }
+}
+
+void R_gc(void) {
+    unimplemented("R_gc");
+}
+
+int R_gc_running() {
+    unimplemented("R_gc_running");
+    return 0;
+}
+
+SEXP Rf_allocS4Object() {
+	unimplemented("Rf_allocS4Object unimplemented");
+	return NULL;
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/README.md b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/README.md
index 8ed7f6488940a668caaa87bc059f8e7c9f9fc579..3b2ad0add58a0ce18ea51ddb396b571ac707875e 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/README.md
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/README.md
@@ -1,2 +1,2 @@
 The C code in this directory is never compiled by the standard C compiler to create compiled object code.
-It is compiled solely to create LLVM IR which is interpreted at runtime. This is controlled by the -DFASTR_LLVM "compiler" flag.
+It is compiled solely to create LLVM IR which is interpreted at runtime.
\ No newline at end of file
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c
index 5898757681b0d2fce70c0ae8b228210c281684a8..19dc2dca73536e16273a0163a318e1c7ceae20da 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c
@@ -12,111 +12,23 @@
 
 // Registering routines from loaded shared libraries - LLVM variant
 
-#include <R_ext/Rdynload.h>
 #include <truffle.h>
 #include <rffiutils.h>
 
-// Must match ordinal value for DLL.NativeSymbolType
-#define C_NATIVE_TYPE 0
-#define CALL_NATIVE_TYPE 1
-#define FORTRAN_NATIVE_TYPE 2
-#define EXTERNAL_NATIVE_TYPE 3
+static void **dynload_callbacks = NULL;
 
-#define IMPORT_PKG_INIT() void *obj = truffle_import_cached("_fastr_rffi_pkginit")
-
-int
-R_registerRoutines(DllInfo *info, const R_CMethodDef * const croutines,
-		   const R_CallMethodDef * const callRoutines,
-		   const R_FortranMethodDef * const fortranRoutines,
-		   const R_ExternalMethodDef * const externalRoutines) {
-	IMPORT_PKG_INIT();
-	int num;
-	if (croutines) {
-		for(num = 0; croutines[num].name != NULL; num++) {;}
-		truffle_invoke(obj, "registerRoutines", info, C_NATIVE_TYPE, num, (long) croutines);
-	}
-	if (callRoutines) {
-		for(num = 0; callRoutines[num].name != NULL; num++) {;}
-		truffle_invoke(obj, "registerRoutines", info, CALL_NATIVE_TYPE, num, (long) callRoutines);
-	}
-	if (fortranRoutines) {
-		for(num = 0; fortranRoutines[num].name != NULL; num++) {;}
-		truffle_invoke(obj, "registerRoutines", info, FORTRAN_NATIVE_TYPE, num, (long) fortranRoutines);
-	}
-	if (externalRoutines) {
-		for(num = 0; externalRoutines[num].name != NULL; num++) {;}
-		truffle_invoke(obj, "registerRoutines", info, EXTERNAL_NATIVE_TYPE, num, (long) externalRoutines);
-	}
-    return 1;
+void *ensure_fun(void *fun) {
+	void *r = truffle_address_to_function(fun);
+	return r;
 }
 
-void *PkgInit_setSymbol(int nstOrd, long routinesAddr, int index) {
-	const char *name;
-	void *fun;
-	int numArgs;
+#include "../truffle_common/Rdynload_fastr.h"
 
-	switch (nstOrd) {
-	case C_NATIVE_TYPE: {
-		R_CMethodDef *croutines = (R_CMethodDef *) routinesAddr;
-		name = croutines[index].name;
-		fun = croutines[index].fun;
-		numArgs = croutines[index].numArgs;
-		break;
-	}
-	case CALL_NATIVE_TYPE: {
-		R_CallMethodDef *callRoutines = (R_CallMethodDef *) routinesAddr;
-		name = callRoutines[index].name;
-		fun = callRoutines[index].fun;
-		numArgs = callRoutines[index].numArgs;
-		break;
-	}
-	case FORTRAN_NATIVE_TYPE: {
-		R_FortranMethodDef * fortranRoutines = (R_FortranMethodDef *) routinesAddr;
-		name = fortranRoutines[index].name;
-		fun = fortranRoutines[index].fun;
-		numArgs = fortranRoutines[index].numArgs;
-		break;
-	}
-	case EXTERNAL_NATIVE_TYPE: {
-		R_ExternalMethodDef * externalRoutines = (R_ExternalMethodDef *) routinesAddr;
-		name = externalRoutines[index].name;
-		fun = externalRoutines[index].fun;
-		numArgs = externalRoutines[index].numArgs;
-		break;
-	}
+void Rdynload_addCallback(int index, void* callback) {
+	if (dynload_callbacks == NULL) {
+		dynload_callbacks = truffle_managed_malloc(CALLBACK_TABLE_SIZE * sizeof(void*));
 	}
-	void *nameString = truffle_read_string(name);
-	void *fundesc = truffle_address_to_function(fun);
-	IMPORT_PKG_INIT();
-	void *result = truffle_invoke(obj, "createDotSymbol", nameString, fundesc, numArgs);
-	return result;
+	dynload_callbacks[index] = callback;
 }
 
-void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr) {
-	void *packageString = truffle_read_string(package);
-	void *nameString = truffle_read_string(name);
-	IMPORT_PKG_INIT();
-	truffle_invoke(obj, "registerCCallable", packageString, nameString, (long) fptr);
-}
-
-Rboolean R_useDynamicSymbols(DllInfo *dllInfo, Rboolean value) {
-	IMPORT_PKG_INIT();
-	return truffle_invoke_i(obj, "useDynamicSymbols", dllInfo, value);
-}
-
-Rboolean R_forceSymbols(DllInfo *dllInfo, Rboolean value) {
-	IMPORT_PKG_INIT();
-	return truffle_invoke_i(obj, "forceSymbols", dllInfo, value);
-}
-
-DL_FUNC R_GetCCallable(const char *package, const char *name) {
-	unimplemented("R_GetCCallable");
-	return NULL;
-}
-
-DL_FUNC R_FindSymbol(char const *name, char const *pkg,
-		     R_RegisteredNativeSymbol *symbol) {
-    unimplemented("R_FindSymbol");
-    return NULL;
-}
 
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rinternals.c
index db953ec45718afe03c0a084dbe838bc399c77bd2..8d45b717ff440a384b5b5ae27002749f81be0a19 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rinternals.c
@@ -21,1104 +21,92 @@
  * questions.
  */
 
+#include <Rinterface.h>
 #include <rffiutils.h>
+#include <Rinternals_common.h>
 #include <truffle.h>
+#include "../common/rffi_upcalls.h"
 
 // Most everything in RInternals.h
 
-static char *ensure_truffle_chararray(const char *x);
-static char *ensure_truffle_chararray_n(const char *x, int n);
+#define INTERNAL_UPCALLS_TABLE_SIZE UPCALLS_TABLE_SIZE + 2
+#define bytesToNativeCharArray_x UPCALLS_TABLE_SIZE
+#define charSXPToNativeCharArray_x UPCALLS_TABLE_SIZE + 1
 
-SEXP Rf_ScalarInteger(int value) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "Rf_ScalarInteger", value);
-}
-
-SEXP Rf_ScalarReal(double value) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "Rf_ScalarDouble", value);
-}
-
-SEXP Rf_ScalarString(SEXP value) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "Rf_ScalarString", value);
-}
-
-SEXP Rf_ScalarLogical(int value) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "Rf_ScalarLogical", value);
-}
-
-SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) {
-    if (allocator != NULL) {
-	    return unimplemented("RF_allocVector with custom allocator");
-    }
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "Rf_allocateVector", t, len);
-}
-
-SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) {
-	return unimplemented("Rf_allocArray");
-}
-
-SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) {
-	return unimplemented("Rf_alloc3DArray");
-}
-
-SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) {
-	return unimplemented("Rf_allocMatrix");
-}
-
-SEXP Rf_allocList(int x) {
-	return unimplemented("Rf_allocList)");
-}
-
-SEXP Rf_allocSExp(SEXPTYPE t) {
-	return unimplemented("Rf_allocSExp");
-}
-
-SEXP Rf_cons(SEXP car, SEXP cdr) {
-	return unimplemented("Rf_cons");
-}
-
-void Rf_defineVar(SEXP symbol, SEXP value, SEXP rho) {
-	unimplemented("Rf_defineVar");
-}
-
-void Rf_setVar(SEXP x, SEXP y, SEXP z) {
-    unimplemented("Rf_setVar");
-}
-
-SEXP Rf_dimgets(SEXP x, SEXP y) {
-	return unimplemented("Rf_dimgets");
-}
-
-SEXP Rf_dimnamesgets(SEXP x, SEXP y) {
-	return unimplemented("Rf_dimnamesgets");
-}
-
-SEXP Rf_eval(SEXP expr, SEXP env) {
-	return unimplemented("Rf_eval");
-}
-
-SEXP Rf_findFun(SEXP symbol, SEXP rho) {
-	return unimplemented("Rf_findFun");
-}
-
-SEXP Rf_findVar(SEXP symbol, SEXP rho) {
-	IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "Rf_findVar", symbol, rho);
-}
-
-SEXP Rf_findVarInFrame(SEXP symbol, SEXP rho) {
-	return unimplemented("Rf_findVarInFrame");
-}
-
-SEXP Rf_getAttrib(SEXP vec, SEXP name) {
-	return unimplemented("Rf_getAttrib");
-}
-
-SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) {
-	return unimplemented("Rf_setAttrib");
-}
-
-SEXP Rf_duplicate(SEXP x) {
-	IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "Rf_duplicate", x, 1);
-}
-
-SEXP Rf_shallow_duplicate(SEXP x) {
-	IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "Rf_duplicate", x, 0);
-}
-
-R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
-	return (R_xlen_t) unimplemented("Rf_any_duplicated");
-}
-
-SEXP Rf_duplicated(SEXP x, Rboolean y) {
-	return unimplemented("Rf_duplicated");
-}
-
-SEXP Rf_applyClosure(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b) {
-	return unimplemented("Rf_applyClosure");
-}
-
-void Rf_copyMostAttrib(SEXP x, SEXP y) {
-	unimplemented("Rf_copyMostAttrib");
-}
-
-void Rf_copyVector(SEXP x, SEXP y) {
-	unimplemented("Rf_copyVector");
-}
-
-Rboolean Rf_inherits(SEXP x, const char * klass) {
-	unimplemented("Rf_inherits");
-	return FALSE;
-}
-
-Rboolean Rf_isReal(SEXP x) {
-    return TYPEOF(x) == REALSXP;
-}
-
-Rboolean Rf_isSymbol(SEXP x) {
-    return TYPEOF(x) == SYMSXP;
-}
-
-Rboolean Rf_isComplex(SEXP x) {
-    return TYPEOF(x) == CPLXSXP;
-}
-
-Rboolean Rf_isEnvironment(SEXP x) {
-    return TYPEOF(x) == ENVSXP;
-}
-
-Rboolean Rf_isExpression(SEXP x) {
-    return TYPEOF(x) == EXPRSXP;
-}
-
-Rboolean Rf_isLogical(SEXP x) {
-    return TYPEOF(x) == LGLSXP;
-}
-
-Rboolean Rf_isObject(SEXP s) {
-	unimplemented("Rf_isObject");
-	return FALSE;
-}
-
-void Rf_PrintValue(SEXP x) {
-	unimplemented("Rf_PrintValue");
-}
-
-SEXP Rf_install(const char *name) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "Rf_install", ensure_truffle_chararray(name));
-}
-
-SEXP Rf_installChar(SEXP charsxp) {
-	return unimplemented("Rf_installChar");
-}
+typedef char* (*call_bytesToNativeCharArray)(SEXP e);
+typedef char* (*call_charSXPToNativeCharArray)(SEXP e);
+typedef char* (*call_R_Home)();
 
-Rboolean Rf_isNull(SEXP s) {
-	IMPORT_CALLHELPER();
-	return (Rboolean) truffle_invoke_i(obj, "Rf_isNull", s);
-}
-
-Rboolean Rf_isString(SEXP s) {
-	IMPORT_CALLHELPER();
-	return (Rboolean) truffle_invoke_i(obj, "Rf_isString", s);
-}
+void **callbacks = NULL;
 
-Rboolean R_cycle_detected(SEXP s, SEXP child) {
-	return (Rboolean) unimplemented("R_cycle_detected");
+void Rinternals_addCallback(int index, void *callback) {
+	if (callbacks == NULL) {
+		callbacks = truffle_managed_malloc(INTERNAL_UPCALLS_TABLE_SIZE * sizeof(void*));
+	}
+//	printf("setting callback %d\n", index);
+	callbacks[index] = callback;
 }
 
-cetype_t Rf_getCharCE(SEXP x) {
-    // unimplemented("Rf_getCharCE");
-    // TODO: real implementation
-    return CE_NATIVE;
+SEXP checkRef(SEXP x) {
+	return x;
 }
 
-static char *ensure_truffle_chararray(const char *x) {
+static char *ensure_truffle_chararray_n(const char *x, int n) {
 	if (truffle_is_truffle_object(x)) {
 		return x;
 	} else {
-		IMPORT_CALLHELPER();
-		return truffle_invoke(obj, "bytesToNativeCharArray", truffle_read_bytes(x));
+		return ((call_bytesToNativeCharArray) callbacks[bytesToNativeCharArray_x])(truffle_read_n_bytes(x, n));
 	}
 }
 
-char *ensure_truffle_chararray_n(const char *x, int n) {
+char *ensure_truffle_chararray(const char *x) {
 	if (truffle_is_truffle_object(x)) {
-		return x;
+		return (char *)x;
 	} else {
-		IMPORT_CALLHELPER();
-		return truffle_invoke(obj, "bytesToNativeCharArray", truffle_read_n_bytes(x, n));
+		return ((call_bytesToNativeCharArray) callbacks[bytesToNativeCharArray_x])(truffle_read_n_bytes(x, strlen(x)));
 	}
 }
 
-SEXP Rf_mkCharLenCE_truffle(const char *x, cetype_t enc) {
-	// Assumes x is a NativeCharArray
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "Rf_mkCharLenCE", x, enc);
-}
-
-SEXP Rf_mkChar(const char *x) {
-	return Rf_mkCharLenCE_truffle(ensure_truffle_chararray(x), CE_NATIVE);
-}
-
-SEXP Rf_mkCharCE(const char *x, cetype_t y) {
-	return Rf_mkCharLenCE_truffle(ensure_truffle_chararray(x), y);
-}
-
-SEXP Rf_mkCharLen(const char *x, int y) {
-	return Rf_mkCharLenCE(x, y, CE_NATIVE);
-}
-
-SEXP Rf_mkCharLenCE(const char *x, int len, cetype_t enc) {
-	return Rf_mkCharLenCE_truffle(ensure_truffle_chararray_n(x, len), enc);
-}
-
-const char *Rf_reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst) {
-	// TODO proper implementation
-	return x;
-}
-
-SEXP Rf_mkString(const char *s) {
-	return ScalarString(Rf_mkChar(s));
-}
-
-int Rf_ncols(SEXP x) {
-	unimplemented("Rf_ncols");
-	return 0;
+void *ensure_string(const char *x) {
+	return truffle_read_string(x);
 }
 
-int Rf_nrows(SEXP x) {
-	unimplemented("Rf_nrows");
-	return 0;
-}
-
-
-SEXP Rf_protect(SEXP x) {
+static SEXP newObjectHandle(SEXP x) {
 	return x;
 }
 
-void Rf_unprotect(int x) {
-	// TODO perhaps we can use this
-}
-
-void R_ProtectWithIndex(SEXP x, PROTECT_INDEX *y) {
-
-}
-
-void R_Reprotect(SEXP x, PROTECT_INDEX y) {
-
-}
-
-
-void Rf_unprotect_ptr(SEXP x) {
-	// TODO perhaps we can use this
-}
-
-#define BUFSIZE 8192
-
-static int Rvsnprintf(char *buf, size_t size, const char  *format, va_list ap)
-{
-    int val;
-    val = vsnprintf(buf, size, format, ap);
-    buf[size-1] = '\0';
-    return val;
-}
-
-
-void Rf_error(const char *format, ...) {
-	// This is a bit tricky. The usual error handling model in Java is "throw RError.error(...)" but
-	// RError.error does quite a lot of stuff including potentially searching for R condition handlers
-	// and, if it finds any, does not return, but throws a different exception than RError.
-	// We definitely need to exit the FFI call and we certainly cannot return to our caller.
-	// So we call CallRFFIHelper.Rf_error to throw the RError exception. When the pending
-	// exception (whatever it is) is observed by JNI, the call to Rf_error will return where we do a
-	// non-local transfer of control back to the entry point (which will cleanup).
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	unimplemented("Rf_error");
-}
-
-void Rf_errorcall(SEXP x, const char *format, ...) {
-	unimplemented("Rf_errorcall");
-}
-
-void Rf_warningcall(SEXP x, const char *format, ...) {
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	unimplemented("Rf_warningcall");
-
-}
-
-void Rf_warning(const char *format, ...) {
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	unimplemented("Rf_warning");
-
-}
-
-void Rprintf(const char *format, ...) {
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	void *str = truffle_read_string(buf);
-	IMPORT_CALLHELPER();
-	truffle_invoke(obj, "printf", str);
-}
-
-/*
-  REprintf is used by the error handler do not add
-  anything unless you're sure it won't
-  cause problems
-*/
-void REprintf(const char *format, ...)
-{
-	// TODO: determine correct target for this message
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	unimplemented("REprintf");
-
-}
-
-void Rvprintf(const char *format, va_list args) {
-	unimplemented("Rvprintf");
-}
-void REvprintf(const char *format, va_list args) {
-	unimplemented("REvprintf");
-}
-
-void R_FlushConsole(void) {
-	// ignored
-}
-
-void R_ProcessEvents(void) {
-	unimplemented("R_ProcessEvents");
-}
-
-// Tools package support, not in public API
-
-SEXP R_NewHashedEnv(SEXP parent, SEXP size) {
-	return unimplemented("R_NewHashedEnv");
-}
-
-SEXP Rf_classgets(SEXP x, SEXP y) {
-	return unimplemented("Rf_classgets");
-}
-
-const char *Rf_translateChar(SEXP x) {
-//	unimplemented("Rf_translateChar");
-	// TODO: proper implementation
-	const char *result = CHAR(x);
-//	printf("translateChar: '%s'\n", result);
-	return result;
-}
-
-const char *Rf_translateChar0(SEXP x) {
-	unimplemented("Rf_translateChar0");
-	return NULL;
-}
-
-const char *Rf_translateCharUTF8(SEXP x) {
-	unimplemented("Rf_translateCharUTF8");
-	return NULL;
-}
-
-SEXP R_FindNamespace(SEXP info) {
-	return unimplemented("R_FindNamespace");
-}
-
-SEXP Rf_lengthgets(SEXP x, R_len_t y) {
-	return unimplemented("Rf_lengthgets");
-}
-
-SEXP Rf_xlengthgets(SEXP x, R_xlen_t y) {
-	return unimplemented("Rf_xlengthgets");
-
-}
-
-SEXP Rf_namesgets(SEXP x, SEXP y) {
-	return unimplemented("Rf_namesgets");
-}
-
-SEXP GetOption1(SEXP tag){
-	return unimplemented("GetOption1");
-}
-
-SEXP GetOption(SEXP tag, SEXP rho) {
-    return GetOption1(tag);
-}
-
-int GetOptionCutoff(void)
-{
-    int w;
-    w = asInteger(GetOption1(install("deparse.cutoff")));
-    if (w == NA_INTEGER || w <= 0) {
-	warning(_("invalid 'deparse.cutoff', used 60"));
-	w = 60;
-    }
-    return w;
-}
-
-#define R_MIN_WIDTH_OPT		10
-#define R_MAX_WIDTH_OPT		10000
-#define R_MIN_DIGITS_OPT	0
-#define R_MAX_DIGITS_OPT	22
-
-int GetOptionWidth(void)
-{
-    int w;
-    w = asInteger(GetOption1(install("width")));
-    if (w < R_MIN_WIDTH_OPT || w > R_MAX_WIDTH_OPT) {
-	warning(_("invalid printing width, used 80"));
-	return 80;
-    }
-    return w;
-}
-
-int GetOptionDigits(void)
-{
-    int d;
-    d = asInteger(GetOption1(install("digits")));
-    if (d < R_MIN_DIGITS_OPT || d > R_MAX_DIGITS_OPT) {
-	warning(_("invalid printing digits, used 7"));
-	return 7;
-    }
-    return d;
+static void releaseObjectHandle(SEXP x) {
 }
 
-Rboolean Rf_GetOptionDeviceAsk(void)
-{
-    int ask;
-    ask = asLogical(GetOption1(install("device.ask.default")));
-    if(ask == NA_LOGICAL) {
-	warning(_("invalid value for \"device.ask.default\", using FALSE"));
-	return FALSE;
-    }
-    return ask != 0;
+char *FASTR_R_Home() {
+	return ((call_R_Home) callbacks[R_Home_x])();
 }
 
-void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho) {
-	unimplemented("Rf_gsetVar");
-}
-
-SEXP TAG(SEXP e) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "TAG", e);
-}
-
-SEXP PRINTNAME(SEXP e) {
-	return unimplemented("PRINTNAME");
-}
-
-SEXP CAR(SEXP e) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "CAR", e);
-}
-
-SEXP CDR(SEXP e) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "CDR", e);
-}
-
-SEXP CAAR(SEXP e) {
-    unimplemented("CAAR");
-    return NULL;
-}
-
-SEXP CDAR(SEXP e) {
-    unimplemented("CDAR");
-    return NULL;
-}
-
-SEXP CADR(SEXP e) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "CADR", e);
-}
-
-SEXP CDDR(SEXP e) {
-	return unimplemented("CDDR");
-}
-
-SEXP CDDDR(SEXP e) {
-    unimplemented("CDDDR");
-    return NULL;
-}
-
-SEXP CADDR(SEXP e) {
-    unimplemented("CADDR");
-    return NULL;
-}
-
-SEXP CADDDR(SEXP e) {
-    unimplemented("CADDDR");
-    return NULL;
-}
-
-SEXP CAD4R(SEXP e) {
-    unimplemented("CAD4R");
-    return NULL;
-}
-
-int MISSING(SEXP x){
-    unimplemented("MISSING");
-    return 0;
-}
-
-void SET_MISSING(SEXP x, int v) {
-    unimplemented("SET_MISSING");
-}
-
-void SET_TAG(SEXP x, SEXP y) {
-	unimplemented("SET_TAG");
-}
-
-SEXP SETCAR(SEXP x, SEXP y) {
-	return unimplemented("SETCAR");
-}
-
-SEXP SETCDR(SEXP x, SEXP y) {
-	return unimplemented("SETCDR");
-}
-
-SEXP SETCADR(SEXP x, SEXP y) {
-    unimplemented("SETCADR");
-    return NULL;
-}
-
-SEXP SETCADDR(SEXP x, SEXP y) {
-    unimplemented("SETCADDR");
-    return NULL;
-}
-
-SEXP SETCADDDR(SEXP x, SEXP y) {
-    unimplemented("SETCADDDR");
-    return NULL;
-}
-
-SEXP SETCAD4R(SEXP e, SEXP y) {
-    unimplemented("SETCAD4R");
-    return NULL;
-}
-
-SEXP FORMALS(SEXP x) {
-    return unimplemented("FORMALS");
-}
-
-SEXP BODY(SEXP x) {
-	return unimplemented("BODY");
-}
-
-SEXP CLOENV(SEXP x) {
-	return unimplemented("CLOENV");
-}
 
-int RDEBUG(SEXP x) {
-    unimplemented("RDEBUG");
-    return 0;
-}
-
-int RSTEP(SEXP x) {
-	unimplemented("RSTEP");
-    return 0;
-}
-
-int RTRACE(SEXP x) {
-	unimplemented("RTRACE");
-    return 0;
-}
-
-void SET_RDEBUG(SEXP x, int v) {
-    unimplemented("SET_RDEBUG");
-}
-
-void SET_RSTEP(SEXP x, int v) {
-    unimplemented("SET_RSTEP");
-}
-
-void SET_RTRACE(SEXP x, int v) {
-    unimplemented("SET_RTRACE");
-}
-
-void SET_FORMALS(SEXP x, SEXP v) {
-    unimplemented("SET_FORMALS");
-}
-
-void SET_BODY(SEXP x, SEXP v) {
-    unimplemented("SET_BODY");
-}
-
-void SET_CLOENV(SEXP x, SEXP v) {
-    unimplemented("SET_CLOENV");
-}
-
-SEXP SYMVALUE(SEXP x) {
-	return unimplemented("SYMVALUE");
-}
-
-SEXP INTERNAL(SEXP x) {
-	return unimplemented("INTERNAL");
-}
-
-int DDVAL(SEXP x) {
-	unimplemented("DDVAL");
-    return 0;
-}
-
-void SET_DDVAL(SEXP x, int v) {
-    unimplemented("SET_DDVAL");
-}
-
-void SET_SYMVALUE(SEXP x, SEXP v) {
-    unimplemented("SET_SYMVALUE");
-}
-
-void SET_INTERNAL(SEXP x, SEXP v) {
-    unimplemented("SET_INTERNAL");
-}
-
-
-SEXP FRAME(SEXP x) {
-	return unimplemented("FRAME");
-}
-
-SEXP ENCLOS(SEXP x) {
-	return unimplemented("ENCLOS");
-}
-
-SEXP HASHTAB(SEXP x) {
-	return unimplemented("HASHTAB");
-}
-
-int ENVFLAGS(SEXP x) {
-	unimplemented("ENVFLAGS");
-    return 0;
-}
-
-void SET_ENVFLAGS(SEXP x, int v) {
-	unimplemented("SET_ENVFLAGS");
-}
-
-void SET_FRAME(SEXP x, SEXP v) {
-    unimplemented("SET_FRAME");
-}
-
-void SET_ENCLOS(SEXP x, SEXP v) {
-	unimplemented("SET_ENCLOS");
-}
-
-void SET_HASHTAB(SEXP x, SEXP v) {
-	unimplemented("SET_HASHTAB");
-}
-
-
-SEXP PRCODE(SEXP x) {
-	return unimplemented("PRCODE");
-}
-
-SEXP PRENV(SEXP x) {
-	unimplemented("PRENV");
-    return 0;
-}
-
-SEXP PRVALUE(SEXP x) {
-	return unimplemented("PRVALUE");
-}
-
-int PRSEEN(SEXP x) {
-	return (int) unimplemented("PRSEEN");
-}
-
-void SET_PRSEEN(SEXP x, int v) {
-    unimplemented("SET_PRSEEN");
-}
-
-void SET_PRENV(SEXP x, SEXP v) {
-    unimplemented("SET_PRENV");
-}
-
-void SET_PRVALUE(SEXP x, SEXP v) {
-    unimplemented("SET_PRVALUE");
-}
-
-void SET_PRCODE(SEXP x, SEXP v) {
-    unimplemented("SET_PRCODE");
-}
-
-int LENGTH(SEXP x) {
-	IMPORT_CALLHELPER();
-    return truffle_invoke_i(obj, "LENGTH", x);
-}
-
-int TRUELENGTH(SEXP x){
-    unimplemented("unimplemented");
-    return 0;
-}
-
-
-void SETLENGTH(SEXP x, int v){
-    unimplemented("SETLENGTH");
-}
-
-
-void SET_TRUELENGTH(SEXP x, int v){
-    unimplemented("SET_TRUELENGTH");
-}
-
-
-R_xlen_t XLENGTH(SEXP x){
-    // xlength seems to be used for long vectors (no such thing in FastR at the moment)
-    return LENGTH(x);
-}
-
-
-R_xlen_t XTRUELENGTH(SEXP x){
-	unimplemented("XTRUELENGTH");
-	return 0;
-}
-
-
-int IS_LONG_VEC(SEXP x){
-	unimplemented("IS_LONG_VEC");
-	return 0;
-}
-
-
-int LEVELS(SEXP x){
-	unimplemented("LEVELS");
-	return 0;
-}
-
-
-int SETLEVELS(SEXP x, int v){
-	unimplemented("SETLEVELS");
-	return 0;
-}
+#include <string.h>
+#include "../truffle_common/Rinternals_truffle_common.h"
 
 int *LOGICAL(SEXP x){
-	IMPORT_CALLHELPER();
-	return (int*) truffle_invoke(obj, "LOGICAL", x);
+	return (int*) ((call_INTEGER) callbacks[LOGICAL_x])(x);
 }
 
 int *INTEGER(SEXP x){
-	IMPORT_CALLHELPER();
-	return (int*) truffle_invoke(obj, "INTEGER", x);
+	return (int*) ((call_INTEGER) callbacks[INTEGER_x])(x);
 }
 
 
 Rbyte *RAW(SEXP x){
-	IMPORT_CALLHELPER();
-	return (int*) truffle_invoke(obj, "RAW", x);
+	return (Rbyte *) ((call_INTEGER) callbacks[REAL_x])(x);
 }
 
 
 double *REAL(SEXP x){
-	IMPORT_CALLHELPER();
-	return (double*) truffle_invoke(obj, "REAL", x);
-}
-
-
-Rcomplex *COMPLEX(SEXP x){
-	return (Rcomplex*) unimplemented("COMPLEX");
+	return (double*) ((call_INTEGER) callbacks[INTEGER_x])(x);
 }
 
 
-SEXP STRING_ELT(SEXP x, R_xlen_t i){
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "STRING_ELT", x, i);
-}
-
-
-SEXP VECTOR_ELT(SEXP x, R_xlen_t i){
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "VECTOR_ELT", x, i);
-}
-
-void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v){
-	IMPORT_CALLHELPER();
-	truffle_invoke(obj, "SET_STRING_ELT", x, i, v);
-}
-
-
-SEXP SET_VECTOR_ELT(SEXP x, R_xlen_t i, SEXP v){
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "SET_VECTOR_ELT", x, i, v);
-}
-
-
-SEXP *STRING_PTR(SEXP x){
-	return unimplemented("STRING_PTR");
-}
-
-
-SEXP *VECTOR_PTR(SEXP x){
-	return unimplemented("VECTOR_PTR");
-}
-
-SEXP Rf_asChar(SEXP x){
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "Rf_asChar", x);
-}
-
-SEXP Rf_PairToVectorList(SEXP x){
-	return unimplemented("Rf_PairToVectorList");
-}
-
-SEXP Rf_VectorToPairList(SEXP x){
-	return unimplemented("Rf_VectorToPairList");
-}
-
-SEXP Rf_asCharacterFactor(SEXP x){
-	return unimplemented("Rf_VectorToPairList");
-}
-
-int Rf_asLogical(SEXP x){
-	return (int) unimplemented("Rf_asLogical");
-}
-
-int Rf_asInteger(SEXP x) {
-	IMPORT_CALLHELPER();
-    return truffle_invoke_i(obj, "Rf_asInteger", x);
-}
-
-Rcomplex Rf_asComplex(SEXP x){
-	unimplemented("Rf_asLogical");
-	Rcomplex c; return c;
-}
-
-int TYPEOF(SEXP x) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke_i(obj, "TYPEOF", x);
-}
-
-SEXP ATTRIB(SEXP x){
-    unimplemented("ATTRIB");
-    return NULL;
-}
-
-int OBJECT(SEXP x){
-	return (int) unimplemented("OBJECT");
-}
-
-int MARK(SEXP x){
-    return (int) unimplemented("MARK");
-}
-
-int NAMED(SEXP x){
-	IMPORT_CALLHELPER();
-	return truffle_invoke_i(obj, "NAMED", x);
-}
-
-int REFCNT(SEXP x){
-	return (int) unimplemented("REFCNT");
-}
-
-void SET_OBJECT(SEXP x, int v){
-    unimplemented("SET_OBJECT");
-}
-
-void SET_TYPEOF(SEXP x, int v){
-    unimplemented("SET_TYPEOF");
-}
-
-SEXP SET_TYPEOF_FASTR(SEXP x, int v){
-	return unimplemented("SET_TYPEOF_FASTR");
-}
-
-void SET_NAMED(SEXP x, int v){
-    unimplemented("SET_NAMED");
-}
-
-void SET_ATTRIB(SEXP x, SEXP v){
-    unimplemented("SET_ATTRIB");
-}
-
-void DUPLICATE_ATTRIB(SEXP to, SEXP from){
-	unimplemented("DUPLICATE_ATTRIB");
-}
-
-char *dgettext(const char *domainname, const char *msgid) {
-	printf("dgettext: '%s'\n", msgid);
-	return (char*) msgid;
-}
-
-char *dngettext(const char *domainname, const char *msgid, const char * msgid_plural, unsigned long int n) {
-    printf("dngettext: singular - '%s' ; plural - '%s'\n", msgid, msgid_plural);
-    return (char*) (n == 1 ? msgid : msgid_plural);
-}
-
 const char *R_CHAR(SEXP charsxp) {
-	IMPORT_CALLHELPER();
-	return (char *)truffle_invoke(obj, "charSXPToNativeCharArray", charsxp);
-}
-
-void *(R_DATAPTR)(SEXP x) {
-    unimplemented("R_DATAPTR");
-	return NULL;
-}
-
-void R_qsort_I  (double *v, int *II, int i, int j) {
-	unimplemented("R_qsort_I");
-}
-
-void R_qsort_int_I(int *iv, int *II, int i, int j) {
-	unimplemented("R_qsort_int_I");
-}
-
-R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
-	return (R_len_t) unimplemented("R_BadLongVector");
-}
-
-int IS_S4_OBJECT(SEXP x) {
-	return (int) unimplemented("IS_S4_OBJECT");
-}
-
-void SET_S4_OBJECT(SEXP x) {
-	unimplemented("SET_S4_OBJECT");
-}
-void UNSET_S4_OBJECT(SEXP x) {
-	unimplemented("UNSET_S4_OBJECT");
-}
-
-Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
-	return (Rboolean) unimplemented("R_ToplevelExec");
-}
-
-SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data,
-		       void (*cleanfun)(void *), void *cleandata) {
-	return unimplemented("R_ExecWithCleanup");
-}
-
-SEXP R_tryEval(SEXP x, SEXP y, int *z) {
-	return unimplemented("R_tryEval");
+	return ((call_charSXPToNativeCharArray) callbacks[charSXPToNativeCharArray_x])(charsxp);
 }
 
-SEXP R_tryEvalSilent(SEXP x, SEXP y, int *z) {
-	return unimplemented("R_tryEvalSilent");
-}
-
-double R_atof(const char *str) {
-	unimplemented("R_atof");
-	return 0;
-}
-
-double R_strtod(const char *c, char **end) {
-	unimplemented("R_strtod");
-	return 0;
-}
-
-SEXP R_PromiseExpr(SEXP x) {
-	return unimplemented("R_PromiseExpr");
-}
 
-SEXP R_ClosureExpr(SEXP x) {
-	return unimplemented("R_ClosureExpr");
-}
-
-SEXP R_forceAndCall(SEXP e, int n, SEXP rho) {
-	return unimplemented("R_forceAndCall");
-}
-
-SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot) {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "R_MakeExternalPtr", (long) p, tag, prot);
-}
-
-void *R_ExternalPtrAddr(SEXP s) {
-	IMPORT_CALLHELPER();
-	return (void*) truffle_invoke_l(obj, "R_ExternalPtrAddr", s);
-}
-
-SEXP R_ExternalPtrTag(SEXP s) {
-	return unimplemented("R_ExternalPtrTag");
-}
-
-SEXP R_ExternalPtrProt(SEXP s) {
-	return unimplemented("R_ExternalPtrProt");
-}
-
-void R_SetExternalPtrAddr(SEXP s, void *p) {
-	unimplemented("R_SetExternalPtrAddr");
-}
-
-void R_SetExternalPtrTag(SEXP s, SEXP tag) {
-	unimplemented("R_SetExternalPtrTag");
-}
-
-void R_SetExternalPtrProt(SEXP s, SEXP p) {
-	unimplemented("R_SetExternalPtrProt");
-}
-
-void R_ClearExternalPtr(SEXP s) {
-	R_SetExternalPtrAddr(s, NULL);
-}
-
-void R_RegisterFinalizer(SEXP s, SEXP fun) {
-	// TODO implement, but not fail for now
-}
-void R_RegisterCFinalizer(SEXP s, R_CFinalizer_t fun) {
-	// TODO implement, but not fail for now
-}
-
-void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit) {
-	// TODO implement, but not fail for now
-
-}
-
-void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit) {
-	// TODO implement, but not fail for now
-}
-
-void R_RunPendingFinalizers(void) {
-	// TODO implement, but not fail for now
-}
-
-SEXP R_do_slot(SEXP obj, SEXP name) {
-	return unimplemented("R_do_slot");
-}
-
-SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
-	return unimplemented("R_do_slot_assign");
-}
-
-int R_has_slot(SEXP obj, SEXP name) {
-	return (int) unimplemented("R_has_slot");
-}
-
-SEXP R_do_MAKE_CLASS(const char *what) {
-	return unimplemented("R_do_MAKE_CLASS");
-}
-
-SEXP R_getClassDef (const char *what) {
-	return unimplemented("R_getClassDef");
-}
-
-SEXP R_do_new_object(SEXP class_def) {
-	return unimplemented("R_do_new_object");
-}
-
-int R_check_class_and_super(SEXP x, const char **valid, SEXP rho) {
-	return (int) unimplemented("R_check_class_and_super");
-}
-
-int R_check_class_etc (SEXP x, const char **valid) {
-	return (int) unimplemented("R_check_class_etc");
-}
-
-SEXP R_PreserveObject(SEXP x) {
-	return unimplemented("R_PreserveObject");
-}
-
-void R_ReleaseObject(SEXP x) {
-	unimplemented("R_ReleaseObject");
-}
-
-Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
-	return (Rboolean) unimplemented("R_compute_identical");
-}
-
-void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
-	unimplemented("Rf_copyListMatrix");
-}
-
-void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
-	unimplemented("Rf_copyMatrix");
-}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/base_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..78d7aaddeb3aaf57610a063c3ba8b63421de25e3
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/base_rffi.c
@@ -0,0 +1,69 @@
+/*
+ * 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
+ * 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.
+ */
+#include <rffiutils.h>
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <glob.h>
+#include <sys/utsname.h>
+#include <errno.h>
+#include <rffiutils.h>
+
+#include "../truffle_common/base_rffi.h"
+
+int call_base_getpid() {
+	return getpid();
+}
+
+int call_base_getwd(char *buf, int len) {
+	char *r = getcwd(buf, len);
+	if (r == NULL) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+int call_base_setwd(char *dir) {
+	return chdir(dir);
+}
+
+int call_base_mkdir(char *dir, int mode) {
+	return mkdir(dir, mode);
+}
+
+int call_base_mkdtemp(char *template) {
+	char *r = mkdtemp(template);
+	if (r == NULL) {
+		return 0;
+	} else {
+		return 1;
+	}
+}
+
+
+int call_base_chmod(char *path, int mode) {
+	int rc = chmod(path, mode);
+	return rc;
+}
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/call_dlopen.c
similarity index 52%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java
rename to com.oracle.truffle.r.native/fficall/src/truffle_llvm/call_dlopen.c
index 6d044539546c64e6d2b97ca0d994e6c2db852bc1..d37ff6d11559458bfa9b8397d115107dfb61d79e 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/Utils.java
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/call_dlopen.c
@@ -20,26 +20,33 @@
  * 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.r.runtime.RRuntime;
+/*
+ * This is a wrapper to the native dlopen/dlclose calls. The wrapper allows it to be called through the LLVM
+ * RFFI machinery, and that takes care of the actual native call.
+ *
+ * In an LLVM build, this is only used in very special circumstances, namely when a native library
+ * for which no LLVM is available must be loaded, e.g., by the R dyn.load call. It must be separate
+ * because the DLLRFFI implementation in an LLVM build, expects, by default, that dlopen will open
+ * a library containing LLVM.
+ */
+
+#include <rffiutils.h>
+#include <stdio.h>
+#include <dlfcn.h>
+#include <errno.h>
+
+long call_dlopen(void *callback(char *result), char *path, int local, int now) {
+	int flags = (local ? RTLD_LOCAL : RTLD_GLOBAL) | (now ? RTLD_NOW : RTLD_LAZY);
+	void *handle = dlopen(path, flags);
+	if (handle == NULL) {
+		int cerrno = errno;
+		char *error = dlerror();
+	    callback(error);
+	}
+	return (long) handle;
+}
 
-class Utils {
-    static Object javaToRPrimitive(Object valueObj) {
-        Object value = valueObj;
-        if (value instanceof Short) {
-            value = (int) ((Short) value).shortValue();
-        } else if (value instanceof Float) {
-            float floatValue = ((Float) value).floatValue();
-            value = new Double(floatValue);
-        } else if (value instanceof Boolean) {
-            boolean booleanValue = ((Boolean) value).booleanValue();
-            value = booleanValue ? RRuntime.LOGICAL_TRUE : RRuntime.LOGICAL_FALSE;
-        } else if (value instanceof Character) {
-            value = (int) ((Character) value).charValue();
-        } else if (value instanceof Byte) {
-            value = (int) ((Byte) value).byteValue();
-        }
-        return value;
-    }
+int call_dlclose(void *handle) {
+	return dlclose(handle);
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/pcre_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/pcre_rffi.c
new file mode 100644
index 0000000000000000000000000000000000000000..170bfeaeeb0ecb4f05934bc5cb23db41cf0f5213
--- /dev/null
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/pcre_rffi.c
@@ -0,0 +1,25 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995, 1996  Robert Gentleman and Ross Ihaka
+ * Copyright (c) 1997-2015,  The R Core Team
+ * Copyright (c) 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+#include <rffiutils.h>
+
+#include "../truffle_common/pcre_rffi.h"
+
+char *call_pcre_maketables() {
+	return pcre_maketables();
+}
+
+int call_pcre_exec(long code, long extra, char *subject, int subjectLength, int startOffset, int options, int *ovectorElems, int ovectorLen) {
+	int rc = pcre_exec((void *) code, (void *) extra, (char *) subject, subjectLength, startOffset, options,
+			ovectorElems, ovectorLen);
+	return rc;
+}
+
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/rffiutils.c
index bc39a9ebed13c9b4c21b54f6558f4231ee1a6813..99ead1d2b3fdb76f26b71295679a6b1d44e4430d 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/rffiutils.c
@@ -24,9 +24,10 @@
 
 SEXP unimplemented(char *name) {
 	printf("unimplemented %s\n", name);
-	void *nameString = truffle_read_string(name);
-	void *obj = truffle_import_cached("_fastr_rffi_call");
-	void *result = truffle_invoke(obj, "unimplemented", nameString);
-	return result;
+	exit(1);
 }
 
+void fatalError(char *msg) {
+	printf("faatal error %s\n", msg);
+    exit(1);
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/rffiutils.h
index 2a380ccc847e663f248294608b6566ddf88e9d21..5306705e335e4a94b1e9c23bf016f0518a3a20a0 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/rffiutils.h
@@ -29,8 +29,9 @@
 #include <Rinternals.h>
 #include <truffle.h>
 
-#define IMPORT_CALLHELPER() void *obj = truffle_import_cached("_fastr_rffi_callhelper")
-
+char *ensure_truffle_chararray(const char *x);
+void *ensure_string(const char *x);
+void *ensure_fun(void *fun);
 SEXP unimplemented(char *name);
 
 #endif /* RFFIUTILS_H */
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/variables.c b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/variables.c
index f41cc549341b79624a2dcb02fff13a97918baef8..5ae5023e69f867c84e68d9d1a47ed165152692b1 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/variables.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/variables.c
@@ -21,7 +21,7 @@
  * questions.
  */
 #include <rffiutils.h>
-#include <variables.h>
+#include "../common/rffi_variablesindex.h"
 
 // Arith.h
 double R_NaN;		/* IEEE NaN */
@@ -30,211 +30,155 @@ double R_NegInf;	/* IEEE -Inf */
 double R_NaReal;	/* NA_REAL: IEEE */
 int R_NaInt;	/* NA_INTEGER:= INT_MIN currently */
 
-// R_GlobalEnv et al are not a variables in FASTR as they are RContext specific
-SEXP FASTR_R_GlobalEnv() {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "R_GlobalEnv");
-}
-
-SEXP FASTR_R_BaseEnv() {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "R_BaseEnv");
-}
-
-SEXP FASTR_R_BaseNamespace() {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "R_BaseNamespace");
-}
-
-SEXP FASTR_R_NamespaceRegistry() {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "R_NamespaceRegistry");
-}
-
-Rboolean FASTR_R_Interactive() {
-	IMPORT_CALLHELPER();
-	return (Rboolean) truffle_invoke_i(obj, "R_Interactive");
-}
-
-char *FASTR_R_Home() {
-	IMPORT_CALLHELPER();
-	return (char *) truffle_invoke(obj, "R_Home");
-}
-
-// Callbacks because cannot store TruffleObjects in memory (currently)
+static void **variables = NULL;
 
 SEXP FASTR_R_NilValue() {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "R_NilValue");
-
+	return (SEXP) variables[R_NilValue_x];
 }
 
 SEXP FASTR_R_UnboundValue() {
-	IMPORT_CALLHELPER();
-	return truffle_invoke(obj, "R_UnboundValue");
+	return variables[R_UnboundValue_x];
 }
 
 SEXP FASTR_R_EmptyEnv() {
-	IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_EmptyEnv");
+    return variables[R_EmptyEnv_x];
 }
 
 SEXP FASTR_R_MissingArg() {
-    IMPORT_CALLHELPER();
-    return Truffle_Invoke(Obj, "R_MissingArg");
+    return variables[R_MissingArg_x];
 }
 
 SEXP FASTR_R_BaseSymbol() {
-    IMPORT_CALLHELPER();
-    Return Truffle_Invoke(Obj, "R_BaseSymbol");
+    return variables[R_BaseSymbol_x];
 }
 
 SEXP FASTR_R_BraceSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_BraceSymbol");
+    return variables[R_BraceSymbol_x];
 }
 
 SEXP FASTR_R_Bracket2Symbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_Bracket2Symbol");
+    return variables[R_Bracket2Symbol_x];
 }
 
 SEXP FASTR_R_BracketSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_BracketSymbol");
+    return variables[R_BracketSymbol_x];
 }
 
 SEXP FASTR_R_ClassSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_ClassSymbol");
+    return variables[R_ClassSymbol_x];
 }
 
 SEXP FASTR_R_DeviceSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_DeviceSymbol");
+    return variables[R_DeviceSymbol_x];
+}
+
+SEXP FASTR_R_DevicesSymbol() {
+    return variables[R_DevicesSymbol_x];
 }
 
 SEXP FASTR_R_DimNamesSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_DimNamesSymbol");
+    return variables[R_DimNamesSymbol_x];
 }
 
 SEXP FASTR_R_DimSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_DimSymbol");
+    return variables[R_DimSymbol_x];
 }
 
 SEXP FASTR_R_DollarSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_DollarSymbol");
+    return variables[R_DollarSymbol_x];
 }
 
 SEXP FASTR_R_DotsSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_DotsSymbol");
+    return variables[R_DotsSymbol_x];
 }
 
 SEXP FASTR_R_DropSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_DropSymbol");
+    return variables[R_DropSymbol_x];
 }
 
 SEXP FASTR_R_LastvalueSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_LastvalueSymbol");
+    return variables[R_LastvalueSymbol_x];
 }
 
 SEXP FASTR_R_LevelsSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_LevelsSymbol");
+    return variables[R_LevelsSymbol_x];
 }
 
 SEXP FASTR_R_ModeSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_ModeSymbol");
+    return variables[R_ModeSymbol_x];
 }
 
 SEXP FASTR_R_NaRmSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_NaRmSymbol");
+    return variables[R_NaRmSymbol_x];
 }
 
 SEXP FASTR_R_NameSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_NameSymbol");
+    return variables[R_NameSymbol_x];
 }
 
 SEXP FASTR_R_NamesSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_NamesSymbol");
+    return variables[R_NamesSymbol_x];
 }
 
 SEXP FASTR_R_NamespaceEnvSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_NamespaceEnvSymbol");
+    return variables[R_NamespaceEnvSymbol_x];
 }
 
 SEXP FASTR_R_PackageSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_PackageSymbol");
+    return variables[R_PackageSymbol_x];
 }
 
 SEXP FASTR_R_QuoteSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_QuoteSymbol");
+    return variables[R_QuoteSymbol_x];
 }
 
 SEXP FASTR_R_RowNamesSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_RowNamesSymbol");
+    return variables[R_RowNamesSymbol_x];
 }
 
 SEXP FASTR_R_SeedsSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_SeedsSymbol");
+    return variables[R_SeedsSymbol_x];
 }
 
 SEXP FASTR_R_SourceSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_SourceSymbol");
+    return variables[R_SourceSymbol_x];
 }
 
 SEXP FASTR_R_TspSymbol() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_TspSymbol");
+    return variables[R_TspSymbol_x];
 }
 
 SEXP FASTR_R_dot_defined() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_dot_defined");
+    return variables[R_dot_defined_x];
 }
 
 SEXP FASTR_R_dot_Method() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_dot_Method");
+    return variables[R_dot_Method_x];
 }
 
 SEXP FASTR_R_dot_target() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_dot_target");
+    return variables[R_dot_target_x];
 }
 
 SEXP FASTR_R_NaString() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_NaString");
+    return variables[R_NaString_x];
 }
 
 SEXP FASTR_R_BlankString() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_BlankString");
+    return variables[R_BlankString_x];
 }
 
 SEXP FASTR_R_BlankScalarString() {
-    IMPORT_CALLHELPER();
-    return truffle_invoke(obj, "R_BlankScalarString");
+    return variables[R_BlankScalarString_x];
 }
 
+SEXP FASTR_R_SrcrefSymbol() {
+    return variables[R_SrcrefSymbol_x];
+}
 
+SEXP FASTR_R_SrcfileSymbol() {
+    return variables[R_SrcfileSymbol_x];
+}
 void Call_initvar_double(int index, double value) {
 	switch (index) {
     case R_NaN_x: R_NaN = value; break;
@@ -250,4 +194,11 @@ void Call_initvar_int(int index, int value) {
 	}
 }
 
+void Call_initvar_obj(int index, void *value) {
+	if (variables == NULL) {
+		variables = truffle_managed_malloc(VARIABLES_TABLE_SIZE * sizeof(void*));
+	}
+	variables[index] = value;
+}
+
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RContextUpCallsRFFI.java b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/zip_rffi.c
similarity index 68%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RContextUpCallsRFFI.java
rename to com.oracle.truffle.r.native/fficall/src/truffle_llvm/zip_rffi.c
index ab6621014ff9c789c161a5640fa6522b3799b75d..026aff63a047d7eb2fe57a867ebe32fb857158ca 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RContextUpCallsRFFI.java
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_llvm/zip_rffi.c
@@ -20,25 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.runtime.ffi;
+#include <rffiutils.h>
 
-/**
- * The following functions are global variables in the standard R FFI. However, owing to the support
- * for virtual R sessions (see .fastr.context) in FastR they are remapped as functions.
- */
-
-public interface RContextUpCallsRFFI {
-    // Checkstyle: stop method name check
-    Object R_GlobalContext();
-
-    Object R_GlobalEnv();
-
-    Object R_BaseEnv();
+extern int compress(char *dest, long *destlen, char *source, long sourcelen);
+extern int uncompress(char *dest, long *destlen, char *source, long sourcelen);
 
-    Object R_BaseNamespace();
-
-    Object R_NamespaceRegistry();
-
-    int R_Interactive();
+int call_zip_compress(char *dest, long destlen, char *source, long sourcelen) {
+	return compress(dest, &destlen, source, sourcelen);
+}
 
+int call_zip_uncompress(char *dest, long destlen, char *source, long sourcelen) {
+	return uncompress(dest, &destlen, source, sourcelen);
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
index 1d14ab2e86559cfad078f88b6148631c77925ad8..1e6384f5d00a3b93c624b0b527dc201bd512d3c6 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Makefile
@@ -32,8 +32,14 @@ OBJ = ../../lib
 
 C_HDRS := $(wildcard *.h)
 
-C_SOURCES = $(wildcard *.c)
-C_OBJECTS := $(patsubst %.c,$(OBJ)/%.o,$(C_SOURCES))
+LOCAL_C_SOURCES = $(wildcard *.c)
+TRUFFLE_COMMON_C_SOURCES := $(wildcard ../truffle_common/*.c)
+TRUFFLE_COMMON_H_SOURCES := $(wildcard ../truffle_common/*.h)
+C_SOURCES := $(LOCAL_C_SOURCES) $(TRUFFLE_COMMON_C_SOURCES)
+#$(info C_SOURCES=$(C_SOURCES))
+TRUFFLE_COMMON_C_OBJECTS := $(addprefix $(OBJ)/, $(notdir $(TRUFFLE_COMMON_C_SOURCES:.c=.o)))
+LOCAL_C_OBJECTS := $(patsubst %.c,$(OBJ)/%.o,$(LOCAL_C_SOURCES))
+C_OBJECTS := $(LOCAL_C_OBJECTS) $(TRUFFLE_COMMON_C_OBJECTS)
 #$(info C_OBJECTS=$(C_OBJECTS))
 
 FFI_INCLUDES = -I$(TOPDIR)/include -I$(TOPDIR)/include/R_ext
@@ -52,12 +58,18 @@ $(C_OBJECTS): | $(OBJ)
 $(OBJ):
 	mkdir -p $(OBJ)
 
-$(OBJ)/%.o: %.c $(TOPDIR)/include/Rinternals.h rffi_callbacksindex.h $(C_HDRS)
-	$(CC) $(CFLAGS) $(INCLUDES) -I../variable_defs -c $< -o $@
+$(OBJ)/%.o: %.c $(TOPDIR)/include/Rinternals.h rffiutils.h $(TRUFFLE_COMMON_H_SOURCES) ../common/rffi_upcallsindex.h $(C_HDRS)
+	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
+
+$(OBJ)/%.o: ../truffle_common/%.c $(TOPDIR)/include/Rinternals.h $(TRUFFLE_COMMON_H_SOURCES) ../common/rffi_upcallsindex.h $(C_HDRS)
+	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
 
 # for debugging, to see what's really being compiled
 $(OBJ)/%.E: %.c $(TOPDIR)/include/Rinternals.h
 	$(CC) -E $(CFLAGS) $(INCLUDES) -c $< > $@
 
+$(OBJ)/%.E: ../truffle_common/%.c $(TOPDIR)/include/Rinternals.h
+	$(CC) -E $(CFLAGS) $(INCLUDES) -c $< > $@
+
 clean:
 	rm -rf $(OBJ)
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeDoubleArray.java b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Random.c
similarity index 67%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeDoubleArray.java
rename to com.oracle.truffle.r.native/fficall/src/truffle_nfi/Random.c
index 1268562ed46d84e51cd5339a4be79ae64715b1a4..434bc3d5804cbcfc0dc3de170a003d3abca23cca 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeDoubleArray.java
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Random.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 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
@@ -20,19 +20,27 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+#include <rffiutils.h>
+#include "../common/rffi_upcalls.h"
 
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
+void GetRNGstate() {
+    ((call_GetRNGstate) callbacks[GetRNGstate_x])();
+}
 
-public class NativeDoubleArray extends NativeNACheck implements RTruffleObject {
-    public final double[] value;
+void PutRNGstate() {
+	((call_PutRNGstate) callbacks[PutRNGstate_x])();
+}
 
-    public NativeDoubleArray(Object obj, double[] value) {
-        super(obj);
-        this.value = value;
-    }
+double unif_rand() {
+	return ((call_unif_rand) callbacks[unif_rand_x])();
+}
+
+double norm_rand() {
+	unimplemented("norm_rand");
+	return 0;
+}
 
-    public NativeDoubleArray(double[] value) {
-        this(null, value);
-    }
+double exp_rand() {
+	unimplemented("exp_rand");
+	return 0;
 }
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
index 4a0ffaaae603d76c60e22df03ca9641d731431a9..685844bd897d2580568c0b6836ff7ff521984e11 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c
@@ -10,125 +10,20 @@
  * All rights reserved.
  */
 #include <rffiutils.h>
-#include <Rdynload.h>
-#include <stdio.h>
 
-static void (*call_registerRoutines)(DllInfo *dllInfo, int nstOrd, int num, long routines);
-static int (*call_useDynamicSymbols)(DllInfo *dllInfo, Rboolean value);
-static TruffleObject (*call_setDotSymbolValues)(DllInfo *dllInfo, char *name, long fun, int numArgs);
-static int (*call_forceSymbols)(DllInfo *dllInfo, Rboolean value);
+static void **dynload_callbacks;
 
-#define registerRoutines_x 0
-#define useDynamicSymbols_x 1
-#define setDotSymbolValues_x 2
-#define forceSymbols_x 3
-
-void Rdynload_init(int index, void* closure) {
-	newClosureRef(closure);
-	switch (index) {
-	case registerRoutines_x: call_registerRoutines = closure; break;
-	case useDynamicSymbols_x: call_useDynamicSymbols = closure; break;
-	case setDotSymbolValues_x: call_setDotSymbolValues = closure; break;
-	case forceSymbols_x: call_forceSymbols = closure; break;
-	}
+void *ensure_fun(void *fun) {
+	return fun;
 }
 
-// Must match ordinal value for DLL.NativeSymbolType
-#define C_NATIVE_TYPE 0
-#define CALL_NATIVE_TYPE 1
-#define FORTRAN_NATIVE_TYPE 2
-#define EXTERNAL_NATIVE_TYPE 3
+#include "../truffle_common/Rdynload_fastr.h"
 
-int
-R_registerRoutines(DllInfo *info, const R_CMethodDef * const croutines,
-		   const R_CallMethodDef * const callRoutines,
-		   const R_FortranMethodDef * const fortranRoutines,
-		   const R_ExternalMethodDef * const externalRoutines) {
-	int num;
-	if (croutines) {
-		for(num = 0; croutines[num].name != NULL; num++) {;}
-		//printf("R_registerRoutines %p,%d,%d,%p\n", info, C_NATIVE_TYPE, num, croutines);
-		call_registerRoutines(info, C_NATIVE_TYPE, num, (long) croutines);
-	}
-	if (callRoutines) {
-		for(num = 0; callRoutines[num].name != NULL; num++) {;}
-		//printf("R_registerRoutines %p,%d,%d,%p\n", info, CALL_NATIVE_TYPE, num, callRoutines);
-		call_registerRoutines(info, CALL_NATIVE_TYPE, num, (long) callRoutines);
-	}
-	if (fortranRoutines) {
-		for(num = 0; fortranRoutines[num].name != NULL; num++) {;}
-		//printf("R_registerRoutines %p,%p,%d,%d,%p\n", call_registerRoutines, info, FORTRAN_NATIVE_TYPE, num, fortranRoutines);
-		call_registerRoutines(info, FORTRAN_NATIVE_TYPE, num, (long) fortranRoutines);
+void Rdynload_init(TruffleEnv* env, int index, void* closure) {
+	(*env)->newClosureRef(env, closure);
+	if (dynload_callbacks == NULL) {
+		dynload_callbacks = malloc(CALLBACK_TABLE_SIZE * sizeof(void*));
 	}
-	if (externalRoutines) {
-		for(num = 0; externalRoutines[num].name != NULL; num++) {;}
-		//printf("R_registerRoutines %p,%d,%d,%p\n", info, EXTERNAL_NATIVE_TYPE, num, externalRoutines);
-		call_registerRoutines(info, EXTERNAL_NATIVE_TYPE, num, (long) externalRoutines);
-	}
-    return 1;
-}
-
-Rboolean R_useDynamicSymbols(DllInfo *dllInfo, Rboolean value) {
-	return call_useDynamicSymbols(dllInfo, value);
+	dynload_callbacks[index] = closure;
 }
 
-Rboolean R_forceSymbols(DllInfo *dllInfo, Rboolean value) {
-	return call_forceSymbols(dllInfo, value);
-}
-
-
-
-TruffleObject Rdynload_setSymbol(DllInfo *info, int nstOrd, long routinesAddr, int index) {
-	const char *name;
-	long fun;
-	int numArgs;
-	switch (nstOrd) {
-	case C_NATIVE_TYPE: {
-		R_CMethodDef *croutines = (R_CMethodDef *) routinesAddr;
-		name = croutines[index].name;
-		fun = (long) croutines[index].fun;
-		numArgs = croutines[index].numArgs;
-		break;
-	}
-	case CALL_NATIVE_TYPE: {
-		R_CallMethodDef *callRoutines = (R_CallMethodDef *) routinesAddr;
-		name = callRoutines[index].name;
-		fun = (long) callRoutines[index].fun;
-		numArgs = callRoutines[index].numArgs;
-		break;
-	}
-	case FORTRAN_NATIVE_TYPE: {
-		R_FortranMethodDef * fortranRoutines = (R_FortranMethodDef *) routinesAddr;
-		name = fortranRoutines[index].name;
-		fun = (long) fortranRoutines[index].fun;
-		numArgs = fortranRoutines[index].numArgs;
-		break;
-	}
-	case EXTERNAL_NATIVE_TYPE: {
-		R_ExternalMethodDef * externalRoutines = (R_ExternalMethodDef *) routinesAddr;
-		name = externalRoutines[index].name;
-		fun = (long) externalRoutines[index].fun;
-		numArgs = externalRoutines[index].numArgs;
-		break;
-	}
-	}
-	//printf("call_setDotSymbolValues %p, %s, %p, %d\n", info, name, fun, numArgs);
-	TruffleObject result = call_setDotSymbolValues(info, (char *)name, fun, numArgs);
-
-	return result;
-}
-
-extern SEXP unimplemented(char *fun);
-
-void R_RegisterCCallable(const char *package, const char *name, DL_FUNC fptr) {
-	// we ignore this for now
-}
-
-DL_FUNC R_GetCCallable(const char *package, const char *name) {
-	return unimplemented("R_GetCCallable");
-}
-
-DL_FUNC R_FindSymbol(char const *name, char const *pkg,
-		     R_RegisteredNativeSymbol *symbol) {
-    return unimplemented("R_FindSymbol");
-}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
index c60dc95c6a328c87e5577dd25a7f07028612d7ca..d611803139718e1ffc0af57d8aaa15f52806f599 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rembedded.c
@@ -22,6 +22,7 @@
  */
 #include <Rinterface.h>
 #include <rffiutils.h>
+#include "../common/rffi_upcalls.h"
 
 char *R_HomeDir(void) {
 	return ((call_R_HomeDir) callbacks[R_HomeDir_x])();
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
index b3005b14480ecd1a403b3fd1e25719a93b604fa4..f38558150ff6c24bdcd603cfcd736c30d720c4fd 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rinternals.c
@@ -22,13 +22,21 @@
  */
 #include <Rinterface.h>
 #include <rffiutils.h>
-#include <rffi_callbacks.h>
 #include <Rinternals_common.h>
+#include "../common/rffi_upcalls.h"
 
-void *callbacks[CALLBACK_TABLE_SIZE];
+void **callbacks = NULL;
 
-void Rinternals_addCallback(int index, void *closure) {
-	newClosureRef(closure);
+static TruffleContext* truffleContext = NULL;
+
+void Rinternals_addCallback(TruffleEnv* env, int index, void *closure) {
+    if (truffleContext == NULL) {
+        truffleContext = (*env)->getTruffleContext(env);
+    }
+	if (callbacks == NULL) {
+		callbacks = malloc(UPCALLS_TABLE_SIZE * sizeof(void*));
+	}
+	(*env)->newClosureRef(env, closure);
 	callbacks[index] = closure;
 }
 
@@ -36,6 +44,27 @@ static int* return_int;
 static double* return_double;
 static char* return_byte;
 
+char *ensure_truffle_chararray_n(const char *x, int n) {
+	return (char *) x;
+}
+
+void *ensure_string(const char * x) {
+	return (void *) x;
+}
+
+SEXP newObjectHandle(SEXP x) {
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
+	SEXP result = (*env)->newObjectRef(env, x);
+	return result;
+}
+
+void releaseObjectHandle(SEXP x) {
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
+	(*env)->releaseObjectRef(env, x);
+}
+
+#include "../truffle_common/Rinternals_truffle_common.h"
+
 long return_INTEGER_CREATE(int *value, int len) {
 	int* idata = malloc(len * sizeof(int));
 	memcpy(idata, value, len * sizeof(int));
@@ -79,39 +108,6 @@ void return_FREE(void *address) {
 //	free(address);
 }
 
-// R_GlobalEnv et al are not a variables in FASTR as they are RContext specific
-SEXP FASTR_R_GlobalEnv() {
-	return ((call_R_GlobalEnv) callbacks[R_GlobalEnv_x])();
-}
-
-SEXP FASTR_R_BaseEnv() {
-	return ((call_R_BaseEnv) callbacks[R_BaseEnv_x])();
-}
-
-SEXP FASTR_R_BaseNamespace() {
-	return ((call_R_BaseNamespace) callbacks[R_BaseNamespace_x])();
-}
-
-SEXP FASTR_R_NamespaceRegistry() {
-	return ((call_R_NamespaceRegistry) callbacks[R_NamespaceRegistry_x])();
-}
-
-CTXT FASTR_GlobalContext() {
-	return ((call_R_GlobalContext) callbacks[R_GlobalContext_x])();
-}
-
-Rboolean FASTR_R_Interactive() {
-	return (int) ((call_R_Interactive) callbacks[R_Interactive_x])();
-}
-
-SEXP CAR(SEXP e) {
-	return ((call_CAR) callbacks[CAR_x])(e);
-}
-
-SEXP CDR(SEXP e) {
-	return ((call_CDR) callbacks[CDR_x])(e);
-}
-
 int *INTEGER(SEXP x) {
 	((call_INTEGER) callbacks[INTEGER_x])(x);
 	return return_int;
@@ -132,1044 +128,8 @@ Rbyte *RAW(SEXP x) {
 		return (Rbyte *) return_byte;
 }
 
-int LENGTH(SEXP x) {
-	return ((call_LENGTH) callbacks[LENGTH_x])(x);
-}
-
 const char * R_CHAR(SEXP x) {
 	((call_R_CHAR) callbacks[R_CHAR_x])(x);
 	return return_byte;
 }
 
-SEXP Rf_ScalarString(SEXP value) {
-	return ((call_Rf_ScalarString) callbacks[Rf_ScalarString_x])(value);
-}
-
-SEXP Rf_mkChar(const char *x) {
-	return Rf_mkCharLenCE(x, strlen(x), CE_NATIVE);
-}
-
-SEXP Rf_mkCharCE(const char *x, cetype_t y) {
-	return Rf_mkCharLenCE(x, strlen(x), y);
-}
-
-SEXP Rf_mkCharLen(const char *x, int y) {
-	return Rf_mkCharLenCE(x, y, CE_NATIVE);
-}
-
-SEXP Rf_mkCharLenCE(const char *x, int len, cetype_t enc) {
-	return ((call_Rf_mkCharLenCE) callbacks[Rf_mkCharLenCE_x])(x,len, enc);
-}
-
-SEXP Rf_mkString(const char *s) {
-	return ScalarString(Rf_mkChar(s));
-}
-
-void Rf_gsetVar(SEXP symbol, SEXP value, SEXP rho) {
-	((call_Rf_gsetVar) callbacks[Rf_gsetVar_x])(symbol, value, rho);
-}
-
-SEXP Rf_coerceVector(SEXP x, SEXPTYPE mode) {
-	return ((call_Rf_coerceVector) callbacks[Rf_coerceVector_x])(x, mode);
-}
-
-SEXP Rf_cons(SEXP car, SEXP cdr) {
-	return ((call_Rf_cons) callbacks[Rf_cons_x])(car, cdr);
-}
-
-SEXP Rf_GetOption1(SEXP tag) {
-	return ((call_Rf_GetOption1) callbacks[Rf_GetOption1_x])(tag);
-}
-
-#define BUFSIZE 8192
-
-static int Rvsnprintf(char *buf, size_t size, const char  *format, va_list ap)
-{
-    int val;
-    val = vsnprintf(buf, size, format, ap);
-    buf[size-1] = '\0';
-    return val;
-}
-
-
-void Rf_error(const char *format, ...) {
-	// TODO fix this
-	// This is a bit tricky. The usual error handling model in Java is "throw RError.error(...)" but
-	// RError.error does quite a lot of stuff including potentially searching for R condition handlers
-	// and, if it finds any, does not return, but throws a different exception than RError.
-	// We definitely need to exit the FFI call and we certainly cannot return to our caller.
-	// So we call RFFIUpCallsObject.Rf_error to throw the RError exception. When the pending
-	// exception (whatever it is) is observed by JNI, the call to Rf_error will return where we do a
-	// non-local transfer of control back to the entry point (which will cleanup).
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	// This will set a pending exception (in JNI)
-	((call_Rf_error) callbacks[Rf_error_x])(buf);
-	// just transfer back which will cleanup and exit the entire JNI call
-//	longjmp(*getErrorJmpBuf(), 1);
-	// Should not reach here
-	unimplemented("Rf_error");
-}
-
-void Rf_errorcall(SEXP x, const char *format, ...) {
-	unimplemented("Rf_errorcall");
-}
-
-void Rf_warningcall(SEXP x, const char *format, ...) {
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	((call_Rf_warningcall) callbacks[Rf_warningcall_x])(x, buf);
-}
-
-void Rf_warning(const char *format, ...) {
-	char buf[8192];
-	va_list(ap);
-	va_start(ap, format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	((call_Rf_warning) callbacks[Rf_warning_x])(buf);
-}
-
-void Rprintf(const char *format, ...) {
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	((call_Rprintf) callbacks[Rprintf_x])(buf);
-}
-
-/*
-  REprintf is used by the error handler do not add
-  anything unless you're sure it won't
-  cause problems
-*/
-void REprintf(const char *format, ...)
-{
-	// TODO: determine correct target for this message
-	char buf[8192];
-	va_list(ap);
-	va_start(ap,format);
-	Rvsnprintf(buf, BUFSIZE - 1, format, ap);
-	va_end(ap);
-	// TODO
-}
-
-void Rvprintf(const char *format, va_list args) {
-	unimplemented("Rvprintf");
-}
-void REvprintf(const char *format, va_list args) {
-	unimplemented("REvprintf");
-}
-
-
-SEXP Rf_ScalarInteger(int value) {
-	return ((call_Rf_ScalarInteger) callbacks[Rf_ScalarInteger_x])(value);
-}
-
-SEXP Rf_ScalarReal(double value) {
-	return ((call_Rf_ScalarReal) callbacks[Rf_ScalarDouble_x])(value);
-}
-
-SEXP Rf_ScalarLogical(int value) {
-	return ((call_Rf_ScalarLogical) callbacks[Rf_ScalarLogical_x])(value);
-}
-
-SEXP Rf_allocVector3(SEXPTYPE t, R_xlen_t len, R_allocator_t* allocator) {
-    if (allocator != NULL) {
-  	    unimplemented("RF_allocVector with custom allocator");
-	    return NULL;
-    }
-    return ((call_Rf_allocVector) callbacks[Rf_allocVector_x])(t, len);
-}
-
-SEXP Rf_allocArray(SEXPTYPE t, SEXP dims) {
-	return ((call_Rf_allocArray) callbacks[Rf_allocArray_x])(t, dims);
-}
-
-SEXP Rf_alloc3DArray(SEXPTYPE t, int x, int y, int z) {
-	return unimplemented("Rf_alloc3DArray");
-}
-
-SEXP Rf_allocMatrix(SEXPTYPE mode, int nrow, int ncol) {
-	return ((call_Rf_allocMatrix) callbacks[Rf_allocMatrix_x])(mode, nrow, ncol);
-}
-
-SEXP Rf_allocList(int x) {
-	unimplemented("Rf_allocList)");
-	return NULL;
-}
-
-SEXP Rf_allocSExp(SEXPTYPE t) {
-	return unimplemented("Rf_allocSExp");
-}
-
-void Rf_defineVar(SEXP symbol, SEXP value, SEXP rho) {
-	((call_Rf_defineVar) callbacks[Rf_defineVar_x])(symbol, value, rho);
-}
-
-void Rf_setVar(SEXP x, SEXP y, SEXP z) {
-    unimplemented("Rf_setVar");
-}
-
-SEXP Rf_dimgets(SEXP x, SEXP y) {
-	return unimplemented("Rf_dimgets");
-}
-
-SEXP Rf_dimnamesgets(SEXP x, SEXP y) {
-	return unimplemented("Rf_dimnamesgets");
-}
-
-SEXP Rf_eval(SEXP expr, SEXP env) {
-	return ((call_Rf_eval) callbacks[Rf_eval_x])(expr, env);
-}
-
-SEXP Rf_findFun(SEXP symbol, SEXP rho) {
-	return ((call_Rf_findFun) callbacks[Rf_findFun_x])(symbol, rho);
-}
-
-SEXP Rf_findVar(SEXP sym, SEXP rho) {
-	return ((call_Rf_findVar) callbacks[Rf_findVar_x])(sym, rho);
-}
-
-SEXP Rf_findVarInFrame(SEXP rho, SEXP sym) {
-	return ((call_Rf_findVarInFrame) callbacks[Rf_findVarInFrame_x])(rho, sym);
-}
-
-SEXP Rf_findVarInFrame3(SEXP rho, SEXP sym, Rboolean b) {
-	return ((call_Rf_findVarInFrame3) callbacks[Rf_findVarInFrame3_x])(rho, sym, b);
-}
-
-SEXP Rf_getAttrib(SEXP vec, SEXP name) {
-	SEXP result = ((call_Rf_getAttrib) callbacks[Rf_getAttrib_x])(vec, name);
-//	printf("Rf_getAttrib: %p\n", result);
-	return result;
-}
-
-SEXP Rf_setAttrib(SEXP vec, SEXP name, SEXP val) {
-	return ((call_Rf_setAttrib) callbacks[Rf_setAttrib_x])(vec, name, val);
-}
-
-SEXP Rf_duplicate(SEXP x) {
-	return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 1);
-}
-
-SEXP Rf_shallow_duplicate(SEXP x) {
-	return ((call_Rf_duplicate) callbacks[Rf_duplicate_x])(x, 0);
-}
-
-R_xlen_t Rf_any_duplicated(SEXP x, Rboolean from_last) {
-	return (R_xlen_t) ((call_Rf_any_duplicated) callbacks[Rf_any_duplicated_x])(x, from_last);
-}
-
-SEXP Rf_duplicated(SEXP x, Rboolean y) {
-	unimplemented("Rf_duplicated");
-	return NULL;
-}
-
-SEXP Rf_applyClosure(SEXP x, SEXP y, SEXP z, SEXP a, SEXP b) {
-	return unimplemented("Rf_applyClosure");
-}
-
-void Rf_copyMostAttrib(SEXP x, SEXP y) {
-	unimplemented("Rf_copyMostAttrib");
-}
-
-void Rf_copyVector(SEXP x, SEXP y) {
-	unimplemented("Rf_copyVector");
-}
-
-int Rf_countContexts(int x, int y) {
-	return (int) unimplemented("Rf_countContexts");
-}
-
-Rboolean Rf_inherits(SEXP x, const char * klass) {
-	return (Rboolean) ((call_Rf_inherits) callbacks[Rf_inherits_x])(x, klass);
-}
-
-Rboolean Rf_isObject(SEXP s) {
-	unimplemented("Rf_isObject");
-	return FALSE;
-}
-
-void Rf_PrintValue(SEXP x) {
-	unimplemented("Rf_PrintValue");
-}
-
-SEXP Rf_install(const char *name) {
-	return ((call_Rf_install) callbacks[Rf_install_x])(name);
-}
-
-SEXP Rf_installChar(SEXP charsxp) {
-	return ((call_Rf_installChar) callbacks[Rf_installChar_x])(charsxp);
-}
-
-Rboolean Rf_isNull(SEXP s) {
-	return (Rboolean) ((call_Rf_isNull) callbacks[Rf_isNull_x])(s);
-}
-
-Rboolean Rf_isString(SEXP s) {
-	return (Rboolean) ((call_Rf_isString) callbacks[Rf_isString_x])(s);
-}
-
-Rboolean R_cycle_detected(SEXP s, SEXP child) {
-	unimplemented("R_cycle_detected");
-	return 0;
-}
-
-cetype_t Rf_getCharCE(SEXP x) {
-    // unimplemented("Rf_getCharCE");
-    // TODO: real implementation
-    return CE_NATIVE;
-}
-
-const char *Rf_reEnc(const char *x, cetype_t ce_in, cetype_t ce_out, int subst) {
-	// TODO proper implementation
-	return x;
-}
-
-int Rf_ncols(SEXP x) {
-	return (int) ((call_Rf_ncols) callbacks[Rf_ncols_x])(x);
-}
-
-int Rf_nrows(SEXP x) {
-	return (int) ((call_Rf_nrows) callbacks[Rf_nrows_x])(x);
-}
-
-
-SEXP Rf_protect(SEXP x) {
-	return x;
-}
-
-void Rf_unprotect(int x) {
-}
-
-void R_ProtectWithIndex(SEXP x, PROTECT_INDEX *y) {
-	//
-}
-
-void R_Reprotect(SEXP x, PROTECT_INDEX y) {
-	//
-}
-
-
-void Rf_unprotect_ptr(SEXP x) {
-	//
-}
-
-
-void R_FlushConsole(void) {
-	// ignored
-}
-
-void R_ProcessEvents(void) {
-	unimplemented("R_ProcessEvents");
-}
-
-// Tools package support, not in public API
-SEXP R_NewHashedEnv(SEXP parent, SEXP size) {
-	return ((call_R_NewHashedEnv) callbacks[R_NewHashedEnv_x])(parent, size);
-}
-
-SEXP Rf_classgets(SEXP vec, SEXP klass) {
-	return ((call_Rf_classgets) callbacks[Rf_classgets_x])(vec, klass);
-}
-
-const char *Rf_translateChar(SEXP x) {
-	// TODO: proper implementation
-	const char *result = CHAR(x);
-	return result;
-}
-
-const char *Rf_translateChar0(SEXP x) {
-	// TODO: proper implementation
-	const char *result = CHAR(x);
-	return result;
-}
-
-const char *Rf_translateCharUTF8(SEXP x) {
-	// TODO: proper implementation
-	const char *result = CHAR(x);
-	return result;
-}
-
-SEXP Rf_lengthgets(SEXP x, R_len_t y) {
-	return ((call_Rf_lengthgets) callbacks[Rf_lengthgets_x])(x, y);
-}
-
-SEXP Rf_xlengthgets(SEXP x, R_xlen_t y) {
-	return unimplemented("Rf_xlengthgets");
-}
-
-SEXP R_lsInternal(SEXP env, Rboolean all) {
-	return R_lsInternal3(env, all, TRUE);
-}
-
-SEXP R_lsInternal3(SEXP env, Rboolean all, Rboolean sorted) {
-	return ((call_R_lsInternal3) callbacks[R_lsInternal3_x])(env, all, sorted);
-}
-
-SEXP Rf_namesgets(SEXP x, SEXP y) {
-	return unimplemented("Rf_namesgets");
-}
-
-SEXP TAG(SEXP e) {
-	return ((call_TAG) callbacks[TAG_x])(e);
-}
-
-SEXP PRINTNAME(SEXP e) {
-	return ((call_PRINTNAME) callbacks[PRINTNAME_x])(e);
-}
-
-
-SEXP CAAR(SEXP e) {
-    unimplemented("CAAR");
-    return NULL;
-}
-
-SEXP CDAR(SEXP e) {
-    unimplemented("CDAR");
-    return NULL;
-}
-
-SEXP CADR(SEXP e) {
-	return ((call_CADR) callbacks[CADR_x])(e);
-}
-
-SEXP CDDR(SEXP e) {
-	return ((call_CDDR) callbacks[CDDR_x])(e);
-}
-
-SEXP CDDDR(SEXP e) {
-    unimplemented("CDDDR");
-    return NULL;
-}
-
-SEXP CADDR(SEXP e) {
-	return ((call_CADDR) callbacks[CADDR_x])(e);
-}
-
-SEXP CADDDR(SEXP e) {
-    unimplemented("CADDDR");
-    return NULL;
-}
-
-SEXP CAD4R(SEXP e) {
-    unimplemented("CAD4R");
-    return NULL;
-}
-
-int MISSING(SEXP x){
-    unimplemented("MISSING");
-    return 0;
-}
-
-void SET_MISSING(SEXP x, int v) {
-    unimplemented("SET_MISSING");
-}
-
-void SET_TAG(SEXP x, SEXP y) {
-	((call_SET_TAG) callbacks[SET_TAG_x])(x, y);
-}
-
-SEXP SETCAR(SEXP x, SEXP y) {
-	return ((call_SETCAR) callbacks[SETCAR_x])(x, y);
-}
-
-SEXP SETCDR(SEXP x, SEXP y) {
-	return ((call_SETCDR) callbacks[SETCDR_x])(x, y);
-}
-
-SEXP SETCADR(SEXP x, SEXP y) {
-	return ((call_SETCADR) callbacks[SETCADR_x])(x, y);
-}
-
-SEXP SETCADDR(SEXP x, SEXP y) {
-    unimplemented("SETCADDR");
-    return NULL;
-}
-
-SEXP SETCADDDR(SEXP x, SEXP y) {
-    unimplemented("SETCADDDR");
-    return NULL;
-}
-
-SEXP SETCAD4R(SEXP e, SEXP y) {
-    unimplemented("SETCAD4R");
-    return NULL;
-}
-
-SEXP FORMALS(SEXP x) {
-    return unimplemented("FORMALS");
-}
-
-SEXP BODY(SEXP x) {
-	return unimplemented("BODY");
-}
-
-SEXP CLOENV(SEXP x) {
-	return unimplemented("CLOENV");
-}
-
-int RDEBUG(SEXP x) {
-	return ((call_RDEBUG) callbacks[RDEBUG_x])(x);
-}
-
-int RSTEP(SEXP x) {
-	return ((call_RSTEP) callbacks[RSTEP_x])(x);
-}
-
-int RTRACE(SEXP x) {
-	unimplemented("RTRACE");
-    return 0;
-}
-
-void SET_RDEBUG(SEXP x, int v) {
-	((call_SET_RDEBUG) callbacks[SET_RDEBUG_x])(x, v);
-}
-
-void SET_RSTEP(SEXP x, int v) {
-	((call_SET_RSTEP) callbacks[SET_RSTEP_x])(x, v);
-}
-
-void SET_RTRACE(SEXP x, int v) {
-    unimplemented("SET_RTRACE");
-}
-
-void SET_FORMALS(SEXP x, SEXP v) {
-    unimplemented("SET_FORMALS");
-}
-
-void SET_BODY(SEXP x, SEXP v) {
-    unimplemented("SET_BODY");
-}
-
-void SET_CLOENV(SEXP x, SEXP v) {
-    unimplemented("SET_CLOENV");
-}
-
-SEXP SYMVALUE(SEXP x) {
-	return ((call_SYMVALUE) callbacks[SYMVALUE_x])(x);
-}
-
-SEXP INTERNAL(SEXP x) {
-	return unimplemented("INTERNAL");
-}
-
-int DDVAL(SEXP x) {
-	unimplemented("DDVAL");
-    return 0;
-}
-
-void SET_DDVAL(SEXP x, int v) {
-    unimplemented("SET_DDVAL");
-}
-
-void SET_SYMVALUE(SEXP x, SEXP v) {
-	((call_SET_SYMVALUE) callbacks[SET_SYMVALUE_x])(x, v);
-}
-
-void SET_INTERNAL(SEXP x, SEXP v) {
-    unimplemented("SET_INTERNAL");
-}
-
-SEXP FRAME(SEXP x) {
-	return unimplemented("FRAME");
-}
-
-SEXP ENCLOS(SEXP x) {
-	return ((call_ENCLOS) callbacks[ENCLOS_x])(x);
-}
-
-SEXP HASHTAB(SEXP x) {
-	return unimplemented("HASHTAB");
-}
-
-int ENVFLAGS(SEXP x) {
-	unimplemented("ENVFLAGS");
-    return 0;
-}
-
-void SET_ENVFLAGS(SEXP x, int v) {
-	unimplemented("SET_ENVFLAGS");
-}
-
-void SET_FRAME(SEXP x, SEXP v) {
-    unimplemented("SET_FRAME");
-}
-
-void SET_ENCLOS(SEXP x, SEXP v) {
-	unimplemented("SET_ENCLOS");
-}
-
-void SET_HASHTAB(SEXP x, SEXP v) {
-	unimplemented("SET_HASHTAB");
-}
-
-SEXP PRCODE(SEXP x) {
-	return ((call_PRCODE) callbacks[PRCODE_x])(x);
-}
-
-SEXP PRENV(SEXP x) {
-	return ((call_PRENV) callbacks[PRENV_x])(x);
-}
-
-SEXP PRVALUE(SEXP x) {
-	return ((call_PRVALUE) callbacks[PRVALUE_x])(x);
-}
-
-int PRSEEN(SEXP x) {
-	return ((call_PRSEEN) callbacks[PRSEEN_x])(x);
-}
-
-void SET_PRSEEN(SEXP x, int v) {
-    unimplemented("SET_PRSEEN");
-}
-
-void SET_PRENV(SEXP x, SEXP v) {
-    unimplemented("SET_PRENV");
-}
-
-void SET_PRVALUE(SEXP x, SEXP v) {
-    unimplemented("SET_PRVALUE");
-}
-
-void SET_PRCODE(SEXP x, SEXP v) {
-    unimplemented("SET_PRCODE");
-}
-
-int TRUELENGTH(SEXP x){
-    unimplemented("unimplemented");
-    return 0;
-}
-
-
-void SETLENGTH(SEXP x, int v){
-    unimplemented("SETLENGTH");
-}
-
-
-void SET_TRUELENGTH(SEXP x, int v){
-    unimplemented("SET_TRUELENGTH");
-}
-
-
-R_xlen_t XLENGTH(SEXP x){
-    // xlength seems to be used for long vectors (no such thing in FastR at the moment)
-    return LENGTH(x);
-}
-
-
-R_xlen_t XTRUELENGTH(SEXP x){
-	unimplemented("XTRUELENGTH");
-	return 0;
-}
-
-
-int IS_LONG_VEC(SEXP x){
-	unimplemented("IS_LONG_VEC");
-	return 0;
-}
-
-
-int LEVELS(SEXP x){
-	unimplemented("LEVELS");
-	return 0;
-}
-
-
-int SETLEVELS(SEXP x, int v){
-	unimplemented("SETLEVELS");
-	return 0;
-}
-
-Rcomplex *COMPLEX(SEXP x){
-	unimplemented("COMPLEX");
-	return NULL;
-}
-
-SEXP STRING_ELT(SEXP x, R_xlen_t i) {
-	return ((call_STRING_ELT) callbacks[STRING_ELT_x])(x, i);
-}
-
-
-SEXP VECTOR_ELT(SEXP x, R_xlen_t i){
-	return ((call_VECTOR_ELT) callbacks[VECTOR_ELT_x])(x, i);
-}
-
-void SET_STRING_ELT(SEXP x, R_xlen_t i, SEXP v){
-    ((call_SET_STRING_ELT) callbacks[SET_STRING_ELT_x])(x, i, v);
-}
-
-
-SEXP SET_VECTOR_ELT(SEXP x, R_xlen_t i, SEXP v){
-	return ((call_SET_VECTOR_ELT) callbacks[SET_VECTOR_ELT_x])(x, i, v);
-}
-
-SEXP *STRING_PTR(SEXP x){
-	unimplemented("STRING_PTR");
-	return NULL;
-}
-
-
-SEXP * NORET VECTOR_PTR(SEXP x){
-	unimplemented("VECTOR_PTR");
-}
-
-SEXP Rf_asChar(SEXP x){
-	return ((call_Rf_asChar) callbacks[Rf_asChar_x])(x);
-}
-
-SEXP Rf_PairToVectorList(SEXP x){
-	return ((call_Rf_PairToVectorList) callbacks[Rf_PairToVectorList_x])(x);
-}
-
-SEXP Rf_VectorToPairList(SEXP x){
-	return unimplemented("Rf_VectorToPairList");
-}
-
-SEXP Rf_asCharacterFactor(SEXP x){
-	unimplemented("Rf_VectorToPairList");
-	return NULL;
-}
-
-int Rf_asLogical(SEXP x){
-	return ((call_Rf_asLogical) callbacks[Rf_asLogical_x])(x);
-}
-
-int Rf_asInteger(SEXP x) {
-	return ((call_Rf_asInteger) callbacks[Rf_asInteger_x])(x);
-}
-
-double Rf_asReal(SEXP x) {
-	return ((call_Rf_asReal) callbacks[Rf_asReal_x])(x);
-}
-
-Rcomplex Rf_asComplex(SEXP x){
-	unimplemented("Rf_asLogical");
-	Rcomplex c; return c;
-}
-
-int TYPEOF(SEXP x) {
-	return (int) ((call_TYPEOF) callbacks[TYPEOF_x])(x);
-}
-
-SEXP ATTRIB(SEXP x){
-    unimplemented("ATTRIB");
-    return NULL;
-}
-
-int OBJECT(SEXP x){
-	return (int) ((call_OBJECT) callbacks[OBJECT_x])(x);
-}
-
-int MARK(SEXP x){
-    unimplemented("MARK");
-    return 0;
-}
-
-int NAMED(SEXP x){
-	return (int) ((call_NAMED) callbacks[NAMED_x])(x);
-}
-
-int REFCNT(SEXP x){
-    unimplemented("REFCNT");
-    return 0;
-}
-
-void SET_OBJECT(SEXP x, int v){
-    unimplemented("SET_OBJECT");
-}
-
-void SET_TYPEOF(SEXP x, int v){
-    unimplemented("SET_TYPEOF");
-}
-
-SEXP SET_TYPEOF_FASTR(SEXP x, int v){
-	return ((call_SET_TYPEOF_FASTR) callbacks[SET_TYPEOF_FASTR_x])(x, v);
-}
-
-void SET_NAMED(SEXP x, int v){
-    unimplemented("SET_NAMED");
-}
-
-void SET_ATTRIB(SEXP x, SEXP v){
-    unimplemented("SET_ATTRIB");
-}
-
-void DUPLICATE_ATTRIB(SEXP to, SEXP from){
-	((call_DUPLICATE_ATTRIB) callbacks[DUPLICATE_ATTRIB_x])(to, from);
-}
-
-void R_qsort_I  (double *v, int *II, int i, int j) {
-	unimplemented("R_qsort_I");
-}
-
-void R_qsort_int_I(int *iv, int *II, int i, int j) {
-	unimplemented("R_qsort_int_I");
-}
-
-R_len_t R_BadLongVector(SEXP x, const char *y, int z) {
-	return (R_len_t) unimplemented("R_BadLongVector");
-}
-
-int IS_S4_OBJECT(SEXP x) {
-	return (int) ((call_IS_S4_OBJECT) callbacks[IS_S4_OBJECT_x])(x);
-}
-
-void SET_S4_OBJECT(SEXP x) {
-	((call_SET_S4_OBJECT) callbacks[SET_S4_OBJECT_x])(x);
-}
-
-void UNSET_S4_OBJECT(SEXP x) {
-	((call_UNSET_S4_OBJECT) callbacks[UNSET_S4_OBJECT_x])(x);
-}
-
-Rboolean R_ToplevelExec(void (*fun)(void *), void *data) {
-	return (Rboolean) unimplemented("R_ToplevelExec");
-}
-
-SEXP R_ExecWithCleanup(SEXP (*fun)(void *), void *data,
-		       void (*cleanfun)(void *), void *cleandata) {
-	return unimplemented("R_ExecWithCleanup");
-}
-
-/* Environment and Binding Features */
-void R_RestoreHashCount(SEXP rho) {
-	unimplemented("R_RestoreHashCount");
-}
-
-Rboolean R_IsPackageEnv(SEXP rho) {
-	unimplemented("R_IsPackageEnv");
-}
-
-SEXP R_PackageEnvName(SEXP rho) {
-	return unimplemented("R_PackageEnvName");
-}
-
-SEXP R_FindPackageEnv(SEXP info) {
-	return unimplemented("R_FindPackageEnv");
-}
-
-Rboolean R_IsNamespaceEnv(SEXP rho) {
-	return (Rboolean) unimplemented("R_IsNamespaceEnv");
-}
-
-SEXP R_FindNamespace(SEXP info) {
-	return ((call_R_FindNamespace) callbacks[R_FindNamespace_x])(info);
-}
-
-SEXP R_NamespaceEnvSpec(SEXP rho) {
-	return unimplemented("R_NamespaceEnvSpec");
-}
-
-void R_LockEnvironment(SEXP env, Rboolean bindings) {
-	unimplemented("R_LockEnvironment");
-}
-
-Rboolean R_EnvironmentIsLocked(SEXP env) {
-	unimplemented("");
-}
-
-void R_LockBinding(SEXP sym, SEXP env) {
-	unimplemented("R_LockBinding");
-}
-
-void R_unLockBinding(SEXP sym, SEXP env) {
-	unimplemented("R_unLockBinding");
-}
-
-void R_MakeActiveBinding(SEXP sym, SEXP fun, SEXP env) {
-	unimplemented("R_MakeActiveBinding");
-}
-
-Rboolean R_BindingIsLocked(SEXP sym, SEXP env) {
-	return (Rboolean) ((call_R_BindingIsLocked) callbacks[R_BindingIsLocked_x])(sym, env);
-}
-
-Rboolean R_BindingIsActive(SEXP sym, SEXP env) {
-    // TODO: for now, I believe all bindings are false
-    return (Rboolean)0;
-}
-
-Rboolean R_HasFancyBindings(SEXP rho) {
-	return (Rboolean) unimplemented("R_HasFancyBindings");
-}
-
-Rboolean Rf_isS4(SEXP x) {
-    return IS_S4_OBJECT(x);
-}
-
-SEXP Rf_asS4(SEXP x, Rboolean b, int i) {
-	unimplemented("Rf_asS4");
-}
-
-static SEXP R_tryEvalInternal(SEXP x, SEXP y, int *ErrorOccurred, int silent) {
-	unimplemented("R_tryEvalInternal");
-}
-
-SEXP R_tryEval(SEXP x, SEXP y, int *ErrorOccurred) {
-	return R_tryEvalInternal(x, y, ErrorOccurred, 0);
-}
-
-SEXP R_tryEvalSilent(SEXP x, SEXP y, int *ErrorOccurred) {
-	return R_tryEvalInternal(x, y, ErrorOccurred, 1);
-}
-
-double R_atof(const char *str) {
-	unimplemented("R_atof");
-	return 0;
-}
-
-double R_strtod(const char *c, char **end) {
-	unimplemented("R_strtod");
-	return 0;
-}
-
-SEXP R_PromiseExpr(SEXP x) {
-	return ((call_R_PromiseExpr) callbacks[R_PromiseExpr_x])(x);
-}
-
-SEXP R_ClosureExpr(SEXP x) {
-	return unimplemented("R_ClosureExpr");
-}
-
-SEXP R_forceAndCall(SEXP e, int n, SEXP rho) {
-	return unimplemented("R_forceAndCall");
-}
-
-SEXP R_MakeExternalPtr(void *p, SEXP tag, SEXP prot) {
-	return ((call_R_MakeExternalPtr) callbacks[R_MakeExternalPtr_x])(p, tag, prot);
-}
-
-void *R_ExternalPtrAddr(SEXP s) {
-	return ((call_R_ExternalPtrAddr) callbacks[R_ExternalPtrAddr_x])(s);
-}
-
-SEXP R_ExternalPtrTag(SEXP s) {
-	return ((call_R_ExternalPtrTag) callbacks[R_ExternalPtrTag_x])(s);
-}
-
-SEXP R_ExternalPtrProtected(SEXP s) {
-	return ((call_R_ExternalPtrProtected) callbacks[R_ExternalPtrProtected_x])(s);
-}
-
-void R_SetExternalPtrAddr(SEXP s, void *p) {
-	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p);
-}
-
-void R_SetExternalPtrTag(SEXP s, SEXP tag) {
-	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, tag);
-}
-
-void R_SetExternalPtrProtected(SEXP s, SEXP p) {
-	((call_R_SetExternalPtrProtected) callbacks[R_SetExternalPtrProtected_x])(s, p);
-}
-
-void R_ClearExternalPtr(SEXP s) {
-	R_SetExternalPtrAddr(s, NULL);
-}
-
-void R_RegisterFinalizer(SEXP s, SEXP fun) {
-	// TODO implement, but not fail for now
-}
-void R_RegisterCFinalizer(SEXP s, R_CFinalizer_t fun) {
-	// TODO implement, but not fail for now
-}
-
-void R_RegisterFinalizerEx(SEXP s, SEXP fun, Rboolean onexit) {
-	// TODO implement, but not fail for now
-
-}
-
-void R_RegisterCFinalizerEx(SEXP s, R_CFinalizer_t fun, Rboolean onexit) {
-	// TODO implement, but not fail for now
-}
-
-void R_RunPendingFinalizers(void) {
-	// TODO implement, but not fail for now
-}
-
-SEXP R_MakeWeakRef(SEXP key, SEXP val, SEXP fin, Rboolean onexit) {
-	unimplemented("R_MakeWeakRef");
-}
-
-SEXP R_MakeWeakRefC(SEXP key, SEXP val, R_CFinalizer_t fin, Rboolean onexit) {
-	unimplemented("R_MakeWeakRefC");
-}
-
-SEXP R_WeakRefKey(SEXP w) {
-	unimplemented("R_WeakRefKey");
-}
-
-SEXP R_WeakRefValue(SEXP w) {
-	unimplemented("R_WeakRefValue");
-}
-
-void R_RunWeakRefFinalizer(SEXP w) {
-	// TODO implement, but not fail for now
-}
-
-SEXP R_do_slot(SEXP obj, SEXP name) {
-	return ((call_R_do_slot) callbacks[R_do_slot_x])(obj, name);
-}
-
-SEXP R_do_slot_assign(SEXP obj, SEXP name, SEXP value) {
-	return ((call_R_do_slot_assign) callbacks[R_do_slot_assign_x])(obj, name, value);
-}
-
-int R_has_slot(SEXP obj, SEXP name) {
-	return (int) unimplemented("R_has_slot");
-}
-
-SEXP R_do_MAKE_CLASS(const char *what) {
-	return ((call_R_do_MAKE_CLASS) callbacks[R_do_MAKE_CLASS_x])(what);
-}
-
-SEXP R_getClassDef (const char *what) {
-	return unimplemented("R_getClassDef");
-}
-
-SEXP R_do_new_object(SEXP class_def) {
-	return ((call_R_do_new_object) callbacks[R_do_new_object_x])(class_def);
-}
-
-static SEXP nfiGetMethodsNamespace() {
-    return ((call_R_MethodsNamespace) callbacks[R_MethodsNamespace_x])();
-}
-
-int R_check_class_etc (SEXP x, const char **valid) {
-	return R_check_class_etc_helper(x, valid, nfiGetMethodsNamespace);
-}
-
-SEXP R_PreserveObject(SEXP x) {
-	return newObjectRef(x);
-}
-
-void R_ReleaseObject(SEXP x) {
-	releaseObjectRef(x);
-}
-
-void R_dot_Last(void) {
-	unimplemented("R_dot_Last");
-}
-
-
-Rboolean R_compute_identical(SEXP x, SEXP y, int flags) {
-	return (Rboolean) ((call_R_compute_identical) callbacks[R_compute_identical_x])(x, y, flags);
-}
-
-void Rf_copyListMatrix(SEXP s, SEXP t, Rboolean byrow) {
-	((call_Rf_copyListMatrix) callbacks[Rf_copyListMatrix_x])(s, t, byrow);
-}
-
-void Rf_copyMatrix(SEXP s, SEXP t, Rboolean byrow) {
-	((call_Rf_copyMatrix) callbacks[Rf_copyMatrix_x])(s, t, byrow);
-}
-
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c
index f9ea65f0db4bdb5c3578d1bf2bc3b5854c719a7c..ce049485772734bbf33acd3edfd56a2093174985 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rmath.c
@@ -21,6 +21,7 @@
  * questions.
  */
 #include <rffiutils.h>
+#include "../common/rffi_upcalls.h"
 
 double Rf_dnorm(double a, double b, double c, int d) {
     unimplemented("Rf_dnorm");
@@ -59,23 +60,19 @@ void Rf_pnorm_both(double a, double * b, double * c, int d, int e) {
 }
 
 double Rf_dunif(double a, double b, double c, int d) {
-    unimplemented("Rf_dunif");
-    return 0;
+	return ((call_Rf_dunif) callbacks[Rf_dunif_x])(a, b, c, d);
 }
 
 double Rf_punif(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_punif");
-    return 0;
+	return ((call_Rf_punif) callbacks[Rf_punif_x])(a, b, c, d, e);
 }
 
 double Rf_qunif(double a, double b, double c, int d, int e) {
-    unimplemented("Rf_qunif");
-    return 0;
+	return ((call_Rf_qunif) callbacks[Rf_qunif_x])(a, b, c, d, e);
 }
 
 double Rf_runif(double a, double b) {
-    unimplemented("Rf_runif");
-    return 0;
+	return ((call_Rf_runif) callbacks[Rf_runif_x])(a, b);
 }
 
 double Rf_dgamma(double a, double b, double c, int d) {
@@ -678,8 +675,11 @@ double Rf_fprec(double a, double b) {
 }
 
 double Rf_fsign(double a, double b) {
-    unimplemented("Rf_fsign");
-    return 0;
+#ifdef IEEE_754
+    if (ISNAN(a) || ISNAN(b))
+	return a + b;
+#endif
+    return ((b >= 0) ? fabs(a) : -fabs(b));
 }
 
 double Rf_ftrunc(double a) {
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
index 93188c9e9e9b6d841ce639ad02e3772ab316eaf6..8d35f6e2cd65e1a86a51f9de166be2826e2fda31 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/base_rffi.c
@@ -28,44 +28,6 @@
 #include <glob.h>
 #include <sys/utsname.h>
 #include <errno.h>
+#include <rffiutils.h>
 
-
-void call_uname(void (*call_uname_setfields)(char *sysname, char *release, char *version, char *machine, char *nodename)) {
-	struct utsname name;
-
-	uname(&name);
-	call_uname_setfields(name.sysname, name.release, name.version, name.machine, name.nodename);
-}
-
-void call_glob(char *pattern, void *closure) {
-	void (*call_addpath)(char *path) = closure;
-
-	glob_t globstruct;
-	int rc = glob(pattern, 0, NULL, &globstruct);
-	if (rc == 0) {
-		int i;
-		for (i = 0; i < globstruct.gl_pathc; i++) {
-			char *path = globstruct.gl_pathv[i];
-			call_addpath(path);
-		}
-	}
-}
-
-void call_readlink(void (*call_setresult)(char *link, int cerrno), char *path) {
-	char *link = NULL;
-	int cerrno = 0;
-    char buf[4096];
-    int len = readlink(path, buf, 4096);
-    if (len == -1) {
-    	cerrno = errno;
-    } else {
-    	buf[len] = 0;
-    	link = buf;
-    }
-	call_setresult(link, cerrno);
-}
-
-void call_strtol(void (*call_setresult)(long result, int cerrno), char *s, int base) {
-    long rc = strtol(s, NULL, base);
-	call_setresult(rc, errno);
-}
+#include "../truffle_common/base_rffi.h"
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c
index 28be2cb058f1e36c093d08b4c7d4a8c07372324b..0a4acc6f2daa2d2c55d2097e64495ff4a538756a 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c
@@ -9,57 +9,5 @@
  *
  * All rights reserved.
  */
-#include <rffiutils.h>
 
-#define PCRE_INFO_CAPTURECOUNT       2
-#define PCRE_INFO_NAMEENTRYSIZE      7
-#define PCRE_INFO_NAMECOUNT          8
-#define PCRE_INFO_NAMETABLE          9
-
-//char *pcre_maketables();
-void *pcre_compile(char *pattern, int options, char **errorMessage, int *errOffset, char *tables);
-//int  pcre_exec(void *code, void *extra, char* subject, int subjectLength, int startOffset, int options, int *ovector, int ovecSize);
-int pcre_fullinfo(void *code, void *extra, int what, void *where);
-//void pcre_free(void *code);
-
-void call_compile(void *closure, char *pattern, int options, long tables) {
-	void (*call_makeresult)(long result, char *errMsg, int errOffset) = closure;
-	char *errorMessage;
-	int errOffset;
-	void *pcre_result = pcre_compile(pattern, options, &errorMessage, &errOffset, (char*) tables);
-	call_makeresult((long) pcre_result, errorMessage, errOffset);
-}
-
-int call_getcapturecount(long code, long extra) {
-    int captureCount;
-	int rc = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_CAPTURECOUNT, &captureCount);
-    return rc < 0 ? rc : captureCount;
-}
-
-int call_getcapturenames(void *closure, long code, long extra) {
-	void (*call_setcapturename)(int i, char *name) = closure;
-    int nameCount;
-    int nameEntrySize;
-    char* nameTable;
-    int res;
-	res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMECOUNT, &nameCount);
-    if (res < 0) {
-        return res;
-    }
-    res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMEENTRYSIZE, &nameEntrySize);
-    if (res < 0) {
-        return res;
-    }
-	res = pcre_fullinfo((void*) code, (void*) extra, PCRE_INFO_NAMETABLE, &nameTable);
-    if (res < 0) {
-        return res;
-    }
-    // from GNU R's grep.c
-	for(int i = 0; i < nameCount; i++) {
-	    char* entry = nameTable + nameEntrySize * i;
-	    int captureNum = (entry[0] << 8) + entry[1] - 1;
-	    call_setcapturename(captureNum, entry + 2);
-    }
-    return res;
-
-}
+#include "../truffle_common/pcre_rffi.h"
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h
deleted file mode 100644
index 0a457d98f0c486ff3797c96dbc47ac5b28473c69..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffi_callbacksindex.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2017, 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.
- */
-
-// TODO This file should be generated automatically from RFFIUpCallMethod.main
-
-#ifndef CALLBACKSINDEX_H
-#define CALLBACKSINDEX_H
-
-#define CADDR_x 0
-#define CADR_x 1
-#define CAR_x 2
-#define CDDR_x 3
-#define CDR_x 4
-#define DUPLICATE_ATTRIB_x 5
-#define ENCLOS_x 6
-#define GetRNGstate_x 7
-#define INTEGER_x 8
-#define IS_S4_OBJECT_x 9
-#define SET_S4_OBJECT_x 10
-#define UNSET_S4_OBJECT_x 11
-#define LENGTH_x 12
-#define LOGICAL_x 13
-#define NAMED_x 14
-#define OBJECT_x 15
-#define PRCODE_x 16
-#define PRENV_x 17
-#define PRINTNAME_x 18
-#define PRSEEN_x 19
-#define PRVALUE_x 20
-#define PutRNGstate_x 21
-#define RAW_x 22
-#define RDEBUG_x 23
-#define REAL_x 24
-#define RSTEP_x 25
-#define R_BaseEnv_x 26
-#define R_BaseNamespace_x 27
-#define R_BindingIsLocked_x 28
-#define R_CHAR_x 29
-#define R_CleanUp_x 30
-#define R_ExternalPtrAddr_x 31
-#define R_ExternalPtrProtected_x 32
-#define R_ExternalPtrTag_x 33
-#define R_FindNamespace_x 34
-#define R_GetConnection_x 35
-#define R_GlobalContext_x 36
-#define R_GlobalEnv_x 37
-#define R_HomeDir_x 38
-#define R_Interactive_x 39
-#define R_MakeExternalPtr_x 40
-#define R_MethodsNamespace_x 41
-#define R_NamespaceRegistry_x 42
-#define R_NewHashedEnv_x 43
-#define R_ParseVector_x 44
-#define R_PromiseExpr_x 45
-#define R_ReadConnection_x 46
-#define R_SetExternalPtrAddr_x 47
-#define R_SetExternalPtrProtected_x 48
-#define R_SetExternalPtrTag_x 49
-#define R_ToplevelExec_x 50
-#define R_WriteConnection_x 51
-#define R_compute_identical_x 52
-#define R_do_MAKE_CLASS_x 53
-#define R_do_new_object_x 54
-#define R_do_slot_x 55
-#define R_do_slot_assign_x 56
-#define R_getContextCall_x 57
-#define R_getContextEnv_x 58
-#define R_getContextFun_x 59
-#define R_getContextSrcRef_x 60
-#define R_getGlobalFunctionContext_x 61
-#define R_getParentFunctionContext_x 62
-#define R_insideBrowser_x 63
-#define R_isEqual_x 64
-#define R_isGlobal_x 65
-#define R_lsInternal3_x 66
-#define R_new_custom_connection_x 67
-#define R_tryEval_x 68
-#define Rf_GetOption1_x 69
-#define Rf_PairToVectorList_x 70
-#define Rf_ScalarDouble_x 71
-#define Rf_ScalarInteger_x 72
-#define Rf_ScalarLogical_x 73
-#define Rf_ScalarString_x 74
-#define Rf_allocArray_x 75
-#define Rf_allocMatrix_x 76
-#define Rf_allocVector_x 77
-#define Rf_any_duplicated_x 78
-#define Rf_asChar_x 79
-#define Rf_asInteger_x 80
-#define Rf_asLogical_x 81
-#define Rf_asReal_x 82
-#define Rf_classgets_x 83
-#define Rf_coerceVector_x 84
-#define Rf_cons_x 85
-#define Rf_copyListMatrix_x 86
-#define Rf_copyMatrix_x 87
-#define Rf_defineVar_x 88
-#define Rf_duplicate_x 89
-#define Rf_error_x 90
-#define Rf_eval_x 91
-#define Rf_findVar_x 92
-#define Rf_findVarInFrame_x 93
-#define Rf_findVarInFrame3_x 94
-#define Rf_findFun_x 95
-#define Rf_getAttrib_x 96
-#define Rf_gsetVar_x 97
-#define Rf_inherits_x 98
-#define Rf_install_x 99
-#define Rf_installChar_x 100
-#define Rf_isNull_x 101
-#define Rf_isString_x 102
-#define Rf_lengthgets_x 103
-#define Rf_mkCharLenCE_x 104
-#define Rf_ncols_x 105
-#define Rf_nrows_x 106
-#define Rf_setAttrib_x 107
-#define Rf_warning_x 108
-#define Rf_warningcall_x 109
-#define Rprintf_x 110
-#define SETCADR_x 111
-#define SETCAR_x 112
-#define SETCDR_x 113
-#define SET_RDEBUG_x 114
-#define SET_RSTEP_x 115
-#define SET_STRING_ELT_x 116
-#define SET_SYMVALUE_x 117
-#define SET_TAG_x 118
-#define SET_TYPEOF_FASTR_x 119
-#define SET_VECTOR_ELT_x 120
-#define STRING_ELT_x 121
-#define SYMVALUE_x 122
-#define TAG_x 123
-#define TYPEOF_x 124
-#define VECTOR_ELT_x 125
-#define getConnectionClassString_x 126
-#define getOpenModeString_x 127
-#define getSummaryDescription_x 128
-#define isSeekable_x 129
-#define unif_rand_x 130
-
-#define CALLBACK_TABLE_SIZE 131
-
-#endif // CALLBACKSINDEX_H
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c
index 26a0c8bd183b73432de034c3033bb6e4d87398ec..7e45c3b7b5164611720dde1f6cbda7cd34bc7c4e 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.c
@@ -21,9 +21,95 @@
  * questions.
  */
 #include <rffiutils.h>
+#include <trufflenfi.h>
 
 void* unimplemented(char *f) {
 	printf("unimplemented %s\n", f);
 	exit(1);
 }
 
+typedef struct globalRefTable_struct {
+    int permanent;
+    SEXP gref;         // The jobject (SEXP) global ref
+} GlobalRefElem;
+
+#define CACHED_GLOBALREFS_INITIAL_SIZE 64
+
+static GlobalRefElem *cachedGlobalRefs = NULL;
+static int cachedGlobalRefsHwm;
+static int cachedGlobalRefsLength;
+static TruffleContext* truffleContext;
+
+void init_utils(TruffleEnv* env) {
+	if (cachedGlobalRefs == NULL) {
+	    truffleContext = (*env)->getTruffleContext(env);
+		cachedGlobalRefs = calloc(CACHED_GLOBALREFS_INITIAL_SIZE, sizeof(GlobalRefElem));
+		cachedGlobalRefsLength = CACHED_GLOBALREFS_INITIAL_SIZE;
+		cachedGlobalRefsHwm = 0;
+	}
+}
+static SEXP findCachedGlobalRef(SEXP obj) {
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
+    for (int i = 0; i < cachedGlobalRefsHwm; i++) {
+        GlobalRefElem elem = cachedGlobalRefs[i];
+        if (elem.gref == NULL) {
+            continue;
+        }
+        if ((*env)->isSameObject(env, elem.gref, obj)) {
+            return elem.gref;
+        }
+    }
+    return NULL;
+}
+
+SEXP addGlobalRef(SEXP obj, int permanent) {
+    SEXP gref;
+    if (cachedGlobalRefsHwm >= cachedGlobalRefsLength) {
+        int newLength = cachedGlobalRefsLength * 2;
+        SEXP newCachedGlobalRefs = calloc(newLength, sizeof(GlobalRefElem));
+        if (newCachedGlobalRefs == NULL) {
+            fatalError("FFI global refs table expansion failure");
+        }
+        memcpy(newCachedGlobalRefs, cachedGlobalRefs, cachedGlobalRefsLength * sizeof(GlobalRefElem));
+        free(cachedGlobalRefs);
+        cachedGlobalRefs = newCachedGlobalRefs;
+        cachedGlobalRefsLength = newLength;
+    }
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
+    gref = (*env)->newObjectRef(env, obj);
+    cachedGlobalRefs[cachedGlobalRefsHwm].gref = gref;
+    cachedGlobalRefs[cachedGlobalRefsHwm].permanent = permanent;
+    cachedGlobalRefsHwm++;
+    return gref;
+}
+
+SEXP checkRef(SEXP obj) {
+    SEXP gref = findCachedGlobalRef(obj);
+    if (gref == NULL) {
+        return obj;
+    } else {
+        return gref;
+    }
+}
+
+SEXP createGlobalRef(SEXP obj, int permanent) {
+    SEXP gref = findCachedGlobalRef(obj);
+    if (gref == NULL) {
+        gref = addGlobalRef(obj, permanent);
+    }
+    return gref;
+}
+
+void releaseGlobalRef(SEXP obj) {
+    TruffleEnv* env = (*truffleContext)->getTruffleEnv(truffleContext);
+    for (int i = 0; i < cachedGlobalRefsHwm; i++) {
+        GlobalRefElem elem = cachedGlobalRefs[i];
+        if (elem.gref == NULL || elem.permanent) {
+            continue;
+        }
+        if ((*env)->isSameObject(env, elem.gref, obj)) {
+        	(*env)->releaseObjectRef(env, elem.gref);
+            cachedGlobalRefs[i].gref = NULL;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
index 9a6c701305586f600b76a88a3df7753a2c1f20f3..95a1896feb750f096b559d60fcf7aa9a46c67a61 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/rffiutils.h
@@ -27,14 +27,27 @@
 #include <string.h>
 #include <limits.h>
 #include <Rinternals.h>
-#include <rffi_callbacks.h>
 #include <trufflenfi.h>
 
 extern void init_memory();
+extern void init_utils(TruffleEnv* env);
+
+char *ensure_truffle_chararray(const char *x);
+void *ensure_string(const char *x);
+void *ensure_fun(void *fun);
 
 // use for an unimplemented API function
 void *unimplemented(char *msg) __attribute__((noreturn));
 // use for any fatal error
 void fatalError(char *msg) __attribute__((noreturn));
 
+// checks x against the list of global refs, returning the global version if x matches (IsSameObject)
+SEXP checkRef(SEXP x);
+// creates a global JNI global ref from x. If permanent is non-zero, calls to
+// releaseGlobalRef are ignored and the global ref persists for the entire execution
+// (used for the R global variables such as R_NilValue).
+SEXP createGlobalRef(SEXP x, int permanent);
+// release a previously created global ref
+void releaseGlobalRef(SEXP x);
+
 #endif
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
index a16e5c6a921b50c850bad242b11870c821fc39b7..ba69fa6144d8252eb229ccc76c8b9f9d21cced19 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
+++ b/com.oracle.truffle.r.native/fficall/src/truffle_nfi/variables.c
@@ -24,72 +24,22 @@
 #include <Rinterface.h>
 #include <trufflenfi.h>
 #include <rffiutils.h>
+#include "../common/rffi_variablesindex.h"
 
-// Indices into RFFIVariables enum
-// The commented out entries are not used as they are remapped
-// as functions and the name clashes with the callback index for that
-#define R_Home_x 0
-#define R_TempDir_x 1
-#define R_NilValue_x 2
-#define R_UnboundValue_x 3
-#define R_MissingArg_x 4
-//#define R_GlobalEnv_x 5
-#define R_EmptyEnv_x 6
-//#define R_BaseEnv_x 7
-//#define R_BaseNamespace_x 8
-//#define R_NamespaceRegistry_x 9
-#define R_Srcref_x 10
-#define R_Bracket2Symbol_x 11
-#define R_BracketSymbol_x 12
-#define R_BraceSymbol_x 13
-#define R_ClassSymbol_x 14
-#define R_DeviceSymbol_x 15
-#define R_DevicesSymbol_x 16
-#define R_DimNamesSymbol_x 17
-#define R_DimSymbol_x 18
-#define R_DollarSymbol_x 19
-#define R_DotsSymbol_x 20
-#define R_DropSymbol_x 21
-#define R_LastvalueSymbol_x 22
-#define R_LevelsSymbol_x 23
-#define R_ModeSymbol_x 24
-#define R_NameSymbol_x 25
-#define R_NamesSymbol_x 26
-#define R_NaRmSymbol_x 27
-#define R_PackageSymbol_x 28
-#define R_QuoteSymbol_x 29
-#define R_RowNamesSymbol_x 30
-#define R_SeedsSymbol_x 31
-#define R_SourceSymbol_x 32
-#define R_TspSymbol_x 33
-#define R_dot_defined_x 34
-#define R_dot_Method_x 35
-#define R_dot_target_x 36
-#define R_SrcrefSymbol_x 37
-#define R_SrcfileSymbol_x 38
-#define R_NaString_x 39
-#define R_NaN_x 40
-#define R_PosInf_x 41
-#define R_NegInf_x 42
-#define R_NaReal_x 43
-#define R_NaInt_x 44
-#define R_BlankString_x 45
-#define R_BlankScalarString_x 46
-#define R_BaseSymbol_x 47
-#define R_NamespaceEnvSymbol_x 48
-#define R_RestartToken_x 49
 
 static const char *R_Home_static;
 static const char *R_TempDir_static;
 static SEXP R_EmptyEnv_static;
 static SEXP R_Srcref_static;
 static SEXP R_NilValue_static;
+static SEXP R_NilValue_static2;
 static SEXP R_UnboundValue_static;
 static SEXP R_MissingArg_static;
 static SEXP R_BaseSymbol_static;
 static SEXP R_Bracket2Symbol_static;   /* "[[" */
 static SEXP R_BracketSymbol_static;    /* "[" */
 static SEXP R_BraceSymbol_static;      /* "{" */
+static SEXP R_DoubleColonSymbol_static;/* "::" */
 static SEXP R_ClassSymbol_static;     /* "class" */
 static SEXP R_DeviceSymbol_static;     /* ".Device" */
 static SEXP R_DevicesSymbol_static;     /* ".Devices" */
@@ -187,6 +137,10 @@ SEXP FASTR_R_BraceSymbol() {
     return R_BraceSymbol_static;
 }
 
+SEXP FASTR_R_DoubleColonSymbol() {
+    return R_DoubleColonSymbol_static;
+}
+
 SEXP FASTR_R_Bracket2Symbol() {
     return R_Bracket2Symbol_static;
 }
@@ -346,50 +300,51 @@ void Call_initvar_string(int index, char *value) {
 	}
 }
 
-void Call_initvar_obj(int index, void* value) {
+void Call_initvar_obj(TruffleEnv* env, int index, void* value) {
+	init_utils(env);
 	switch (index) {
-    case R_NilValue_x: R_NilValue_static = newObjectRef(value); break;
-    case R_UnboundValue_x: R_UnboundValue_static = newObjectRef(value); break;
-    case R_MissingArg_x: R_MissingArg_static = newObjectRef(value); break;
-//    case R_Srcref_x: R_Srcref_static = newObjectRef(value); break;
-    case R_EmptyEnv_x: R_EmptyEnv_static = newObjectRef(value); break;
-    case R_Bracket2Symbol_x: R_Bracket2Symbol_static = newObjectRef(value); break;
-    case R_BracketSymbol_x: R_BracketSymbol_static = newObjectRef(value); break;
-    case R_BraceSymbol_x: R_BraceSymbol_static = newObjectRef(value); break;
-    case R_ClassSymbol_x: R_ClassSymbol_static = newObjectRef(value); break;
-    case R_DeviceSymbol_x: R_DeviceSymbol_static = newObjectRef(value); break;
-    case R_DevicesSymbol_x: R_DevicesSymbol_static = newObjectRef(value); break;
-    case R_DimNamesSymbol_x: R_DimNamesSymbol_static = newObjectRef(value); break;
-    case R_DimSymbol_x: R_DimSymbol_static = newObjectRef(value); break;
-    case R_DollarSymbol_x: R_DollarSymbol_static = newObjectRef(value); break;
-    case R_DotsSymbol_x: R_DotsSymbol_static = newObjectRef(value); break;
-    case R_DropSymbol_x: R_DropSymbol_static = newObjectRef(value); break;
-    case R_LastvalueSymbol_x: R_LastvalueSymbol_static = newObjectRef(value); break;
-    case R_LevelsSymbol_x: R_LevelsSymbol_static = newObjectRef(value); break;
-    case R_ModeSymbol_x: R_ModeSymbol_static = newObjectRef(value); break;
-    case R_NameSymbol_x: R_NameSymbol_static = newObjectRef(value); break;
-    case R_NamesSymbol_x: R_NamesSymbol_static = newObjectRef(value); break;
-    case R_NaRmSymbol_x: R_NaRmSymbol_static = newObjectRef(value); break;
-    case R_PackageSymbol_x: R_PackageSymbol_static = newObjectRef(value); break;
-    case R_QuoteSymbol_x: R_QuoteSymbol_static = newObjectRef(value); break;
-    case R_RowNamesSymbol_x: R_RowNamesSymbol_static = newObjectRef(value); break;
-    case R_SeedsSymbol_x: R_SeedsSymbol_static = newObjectRef(value); break;
-    case R_SourceSymbol_x: R_SourceSymbol_static = newObjectRef(value); break;
-    case R_TspSymbol_x: R_TspSymbol_static = newObjectRef(value); break;
-    case R_dot_defined_x: R_dot_defined_static = newObjectRef(value); break;
-    case R_dot_Method_x: R_dot_Method_static = newObjectRef(value); break;
-    case R_dot_target_x: R_dot_target_static = newObjectRef(value); break;
-    case R_SrcrefSymbol_x: R_SrcrefSymbol_static = newObjectRef(value); break;
-    case R_SrcfileSymbol_x: R_SrcfileSymbol_static = newObjectRef(value); break;
-    case R_NaString_x: R_NaString_static = newObjectRef(value); break;
-    case R_BlankString_x: R_BlankString_static = newObjectRef(value); break;
-    case R_BlankScalarString_x: R_BlankString_static = newObjectRef(value); break;
-    case R_BaseSymbol_x: R_BaseSymbol_static = newObjectRef(value); break;
-    case R_NamespaceEnvSymbol_x: R_NamespaceEnvSymbol_static = newObjectRef(value); break;
-    // case R_RestartToken_x: R_RestartToken_static = newObjectRef(value); break;
+    case R_NilValue_x: R_NilValue_static = createGlobalRef(value, 1); break;
+    case R_UnboundValue_x: R_UnboundValue_static = createGlobalRef(value, 1); break;
+    case R_MissingArg_x: R_MissingArg_static = createGlobalRef(value, 1); break;
+    case R_Srcref_x: R_Srcref_static = createGlobalRef(value, 1); break;
+    case R_EmptyEnv_x: R_EmptyEnv_static = createGlobalRef(value, 1); break;
+    case R_Bracket2Symbol_x: R_Bracket2Symbol_static = createGlobalRef(value, 1); break;
+    case R_BracketSymbol_x: R_BracketSymbol_static = createGlobalRef(value, 1); break;
+    case R_BraceSymbol_x: R_BraceSymbol_static = createGlobalRef(value, 1); break;
+    case R_DoubleColonSymbol_x: R_DoubleColonSymbol_static = createGlobalRef(value, 1); break;
+    case R_ClassSymbol_x: R_ClassSymbol_static = createGlobalRef(value, 1); break;
+    case R_DeviceSymbol_x: R_DeviceSymbol_static = createGlobalRef(value, 1); break;
+    case R_DevicesSymbol_x: R_DevicesSymbol_static = createGlobalRef(value, 1); break;
+    case R_DimNamesSymbol_x: R_DimNamesSymbol_static = createGlobalRef(value, 1); break;
+    case R_DimSymbol_x: R_DimSymbol_static = createGlobalRef(value, 1); break;
+    case R_DollarSymbol_x: R_DollarSymbol_static = createGlobalRef(value, 1); break;
+    case R_DotsSymbol_x: R_DotsSymbol_static = createGlobalRef(value, 1); break;
+    case R_DropSymbol_x: R_DropSymbol_static = createGlobalRef(value, 1); break;
+    case R_LastvalueSymbol_x: R_LastvalueSymbol_static = createGlobalRef(value, 1); break;
+    case R_LevelsSymbol_x: R_LevelsSymbol_static = createGlobalRef(value, 1); break;
+    case R_ModeSymbol_x: R_ModeSymbol_static = createGlobalRef(value, 1); break;
+    case R_NameSymbol_x: R_NameSymbol_static = createGlobalRef(value, 1); break;
+    case R_NamesSymbol_x: R_NamesSymbol_static = createGlobalRef(value, 1); break;
+    case R_NaRmSymbol_x: R_NaRmSymbol_static = createGlobalRef(value, 1); break;
+    case R_PackageSymbol_x: R_PackageSymbol_static = createGlobalRef(value, 1); break;
+    case R_QuoteSymbol_x: R_QuoteSymbol_static = createGlobalRef(value, 1); break;
+    case R_RowNamesSymbol_x: R_RowNamesSymbol_static = createGlobalRef(value, 1); break;
+    case R_SeedsSymbol_x: R_SeedsSymbol_static = createGlobalRef(value, 1); break;
+    case R_SourceSymbol_x: R_SourceSymbol_static = createGlobalRef(value, 1); break;
+    case R_TspSymbol_x: R_TspSymbol_static = createGlobalRef(value, 1); break;
+    case R_dot_defined_x: R_dot_defined_static = createGlobalRef(value, 1); break;
+    case R_dot_Method_x: R_dot_Method_static = createGlobalRef(value, 1); break;
+    case R_dot_target_x: R_dot_target_static = createGlobalRef(value, 1); break;
+    case R_SrcrefSymbol_x: R_SrcrefSymbol_static = createGlobalRef(value, 1); break;
+    case R_SrcfileSymbol_x: R_SrcfileSymbol_static = createGlobalRef(value, 1); break;
+    case R_NaString_x: R_NaString_static = createGlobalRef(value, 1); break;
+    case R_BlankString_x: R_BlankString_static = createGlobalRef(value, 1); break;
+    case R_BlankScalarString_x: R_BlankString_static = createGlobalRef(value, 1); break;
+    case R_BaseSymbol_x: R_BaseSymbol_static = createGlobalRef(value, 1); break;
+    case R_NamespaceEnvSymbol_x: R_NamespaceEnvSymbol_static = createGlobalRef(value, 1); break;
+    // case R_RestartToken_x: R_RestartToken_static = createGlobalRef(value, 1); break;
     default:
     	printf("Call_initvar_obj: unimplemented index %d\n", index);
     	exit(1);
 	}
 }
-
diff --git a/com.oracle.truffle.r.native/gnur/Makefile.gnur b/com.oracle.truffle.r.native/gnur/Makefile.gnur
index a6819b2a23e2fdb1dd3fc034318542e1e41717cd..2f82aecaa339c5a8d16481627cf289770394215d 100644
--- a/com.oracle.truffle.r.native/gnur/Makefile.gnur
+++ b/com.oracle.truffle.r.native/gnur/Makefile.gnur
@@ -26,13 +26,6 @@
 # that it shares, but is simpler and safer to just build all of it. The relevant 
 # pieces are then copied to other FastR directories.
 #
-# The configuration of GnuR for FastR is platform specific and a special step
-# is needed for Linux where, ordinarily, the PCRE library is compiled non-PIC
-# as it is built as a library archive. FastR needs a shared library, which can be
-# enabled by setting --enable-R-shlib, but unfortunately this also sets the visibility
-# of the functions to hidden, so FastR cannot find them. There does not appear to be a 
-# way to fix this simply using configure args, so we patch up the Makeconf file.
-
 # Portions of the Makeconf file are then extracted to use in building the native
 # parts of FastR, especially packages with native code.
 
@@ -40,13 +33,9 @@
 
 OSNAME := $(shell uname)
 
-ifeq ($(FASTR_RFFI),llvm)
-FC_DIR := $(abspath $(TOPDIR)/../mx.fastr/compilers)
-FASTR_COMPILERS := CC=$(FC_DIR)/fastr-cc FC=$(FC_DIR)/fastr-fc F77=$(FC_DIR)/fastr-fc CXX=$(FC_DIR)/fastr-c++ CXXCPP=$(FC_DIR)/fastr-cpp OBJC=$(FC_DIR)/fastr-cc
-endif
-
 ifneq ($(FASTR_RFFI),llvm)
 # LLVM text parser and -g don't get on
+# TODO check still true
 OPT_FLAGS := -g -O2
 OPT_FLAGS := -O2
 
@@ -68,11 +57,7 @@ all: Makefile $(GNUR_HOME) iconv config build
 
 $(GNUR_HOME): 
 	tar xf $(TOPDIR)/../libdownloads/R-$(R_VERSION).tar.gz
-# Solaris doesn't need this and ed can't handle the size of the configure file!
-ifneq ($(OSNAME), SunOS)
-	ed $(GNUR_HOME)/configure < edconfigure # to fix the zlib version check (fixed in GNUR in the meantime)
-endif
-
+	(cd $(GNUR_HOME) && patch < $(TOPDIR)/gnur/configure.patch) # to fix the zlib version check (fixed in GNUR in the meantime)
 
 # After this platform check, GNUR_CONFIG_FLAGS must be set
 ifeq ($(OSNAME), SunOS)
@@ -87,10 +72,11 @@ ifeq ($(OSNAME), SunOS)
     FLIBS_COMMON := -lsunimath -lfai -lsunmath -lmtsk
     ifeq ($(OS_ARCH), i386)
         SUB_ARCH := amd64
-        FLIBS_SUB_ARCH := $(SSTUDIO_HOME)prod/lib/$(SUB_ARCH)/libfsu.so.1 $(SSTUDIO_HOME)prod/lib/$(SUB_ARCH)/libfui.so.2
+        FLIBS_SUB_ARCH := $(SSTUDIO_HOME)lib/$(SUB_ARCH)/libfsu.so.1 $(SSTUDIO_HOME)lib/$(SUB_ARCH)/libfui.so.2
+        GNUR_CONFIG_FLAGS := --build=x86_64-pc-solaris2.11
     else
         SUB_ARCH := sparc/64
-        FLIBS_SUB_ARCH := -lifai -lfai2 -lfsumai -lfprodai -lfminlai -lfmaxlai -lfminvai -lfmaxvai -lfui $(SSTUDIO_HOME)prod/lib/$(SUB_ARCH)/libfsu.so.1
+        FLIBS_SUB_ARCH := -lifai -lfai2 -lfsumai -lfprodai -lfminlai -lfmaxlai -lfminvai -lfmaxvai -lfui $(SSTUDIO_HOME)lib/$(SUB_ARCH)/libfsu.so.1
     endif
     ICONV := libiconv-1.14
     $(shell mkdir -p iconv_install)
@@ -100,8 +86,8 @@ ifeq ($(OSNAME), SunOS)
     ICONV_CONFIG_FLAGS := CC=cc CXX=CC CFLAGS=$(ICONV_CFLAGS) LDFLAGS=$(ICONV_LDFLAGS)
 # required for Solaris compiler >=12.2, see Appendix C of R installation guide: 
 # http://cran.r-project.org/doc/manuals/r-release/R-admin.html#Solaris 
-    GNUR_FLIBS := FLIBS="-R$(SSTUDIO_HOME)prod/lib/$(SUB_ARCH) $(FLIBS_COMMON) $(FLIBS_SUB_ARCH)"
-    GNUR_CONFIG_FLAGS := $(ICONV_CONFIG_FLAGS) CPPFLAGS=$(ICONV_CFLAGS) DYLIB_LDFLAGS=$(ICONV_LDFLAGS) $(GNUR_FLIBS) F77="sunf95 -m64 -xcode=pic32"
+    GNUR_FLIBS := FLIBS="-R$(SSTUDIO_HOME)lib/$(SUB_ARCH) $(FLIBS_COMMON) $(FLIBS_SUB_ARCH)"
+    GNUR_CONFIG_FLAGS += $(ICONV_CONFIG_FLAGS) CPPFLAGS=$(ICONV_CFLAGS) DYLIB_LDFLAGS=$(ICONV_LDFLAGS) $(GNUR_FLIBS) F77="sunf95 -m64 -xcode=pic32"
 
 iconv: $(ICONV) iconv_config iconv_build
 
diff --git a/com.oracle.truffle.r.native/gnur/Makefile.platform b/com.oracle.truffle.r.native/gnur/Makefile.platform
index 70ab4217cdff586579b5f2d7855ab74ab6bac943..8366712be3e5a2e965bd8833c05ca06272671a54 100644
--- a/com.oracle.truffle.r.native/gnur/Makefile.platform
+++ b/com.oracle.truffle.r.native/gnur/Makefile.platform
@@ -38,6 +38,9 @@ $(TOPDIR)/platform.mk: sedMakeconf $(GNUR_HOME)/Makeconf Makefile
 	sed -f sedEtcMakeconf $(GNUR_HOME)/etc/Makeconf > /dev/null 2>&1
 	cat platform.mk.temp1 platform.mk.temp2 > platform.mk.temp
 	ed platform.mk.temp < edAddFASTR
+ifeq ($(FASTR_RFFI),llvm)
+	ed platform.mk.temp <edLLVM
+endif
 	echo OS_NAME = $(OS_NAME) >> platform.mk.temp
 ifeq ($(OS_NAME),SunOS)
 	echo JDK_OS_DIR = solaris >> platform.mk.temp
diff --git a/com.oracle.truffle.r.native/gnur/configure.patch b/com.oracle.truffle.r.native/gnur/configure.patch
new file mode 100644
index 0000000000000000000000000000000000000000..b4f0be9936176b6dc7ce55cc96c9234ecb966b97
--- /dev/null
+++ b/com.oracle.truffle.r.native/gnur/configure.patch
@@ -0,0 +1,18 @@
+--- ./R-3.3.2/configure Mon Oct 24 04:34:26 2016
++++ ./configure.new     Wed Jul 26 04:43:08 2017
+@@ -35507,10 +35507,11 @@
+ #include <string.h>
+ #include <zlib.h>
+ int main() {
+-#ifdef ZLIB_VERSION
+-/* Work around Debian bug: it uses 1.2.3.4 even though there was no such
+-   version on the master site zlib.net */
+-  exit(strncmp(ZLIB_VERSION, "1.2.5", 5) < 0);
++#ifdef ZLIB_VERNUM
++  if (ZLIB_VERNUM < 0x1250) {
++    exit(1);
++  }
++  exit(0);
+ #else
+   exit(1);
+ #endif
diff --git a/com.oracle.truffle.r.native/gnur/edLLVM b/com.oracle.truffle.r.native/gnur/edLLVM
new file mode 100644
index 0000000000000000000000000000000000000000..4cefc6d92562aeb914d69b7c2aff95ad6800a5a6
--- /dev/null
+++ b/com.oracle.truffle.r.native/gnur/edLLVM
@@ -0,0 +1,12 @@
+/^CC =/
+d
+i
+CC = $(FASTR_NATIVE_DIR)/llvm_tools/llvm-cc
+.
+/^F77 =/
+d
+i
+F77 = $(FASTR_NATIVE_DIR)/llvm_tools/llvm-fc
+.
+w
+q
diff --git a/com.oracle.truffle.r.native/gnur/edconfigure b/com.oracle.truffle.r.native/gnur/edconfigure
deleted file mode 100644
index ba5c8bbaf62383c3576331b6e809a59fff4e195e..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.native/gnur/edconfigure
+++ /dev/null
@@ -1,9 +0,0 @@
-35510,35513c
-#ifdef ZLIB_VERNUM
-  if (ZLIB_VERNUM < 0x1250) {
-    exit(1);
-  }
-  exit(0);
-.
-w
-q
diff --git a/com.oracle.truffle.r.native/library/base/Makefile b/com.oracle.truffle.r.native/library/base/Makefile
index 9e56056560f802add59e270d8f8024f5ed39984f..1609a5e864747a619cde100355afc11fa8cfaa83 100644
--- a/com.oracle.truffle.r.native/library/base/Makefile
+++ b/com.oracle.truffle.r.native/library/base/Makefile
@@ -52,6 +52,7 @@ post.done:
 # rebuild GNU R in compressed mode
 	(cd $(GNUR_HOME); $(MAKE))
 	touch post.done
+	find $(FASTR_LIBRARY_DIR)/base -exec touch {} +
 
 clean.done:
 	rm -f post.done pre.done
diff --git a/com.oracle.truffle.r.native/library/lib.mk b/com.oracle.truffle.r.native/library/lib.mk
index 4f6a44fcb9c53fa71a7161839d02d0fdc4e9cf31..997d88708bc1351a2dbe20113fc02f948a5d6e61 100644
--- a/com.oracle.truffle.r.native/library/lib.mk
+++ b/com.oracle.truffle.r.native/library/lib.mk
@@ -109,8 +109,10 @@ $(LIB_PKG): $(C_OBJECTS) $(F_OBJECTS) $(GNUR_C_OBJECTS) $(GNUR_F_OBJECTS) $(PKGD
 	mkdir -p $(FASTR_LIBRARY_DIR)/$(PKG)/libs
 	cp $(LIB_PKG) $(FASTR_LIBRARY_DIR)/$(PKG)/libs
 ifeq ($(OS_NAME),Darwin)
+ifneq ($(FASTR_RFFI),llvm)	
 	install_name_tool -id @rpath/../library/$(PKG)/libs/$(PKG).so $(FASTR_LIBRARY_DIR)/$(PKG)/libs/$(PKG).so
 endif
+endif
 
 $(OBJ)/%.o: $(SRC)/%.c $(H_SOURCES)
 	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
diff --git a/com.oracle.truffle.r.native/library/tools/Makefile b/com.oracle.truffle.r.native/library/tools/Makefile
index f044af7d7ee2e27bf916d756996d9d80bf577cec..9c415e7f92e967f064f4844ba8170c6043556189 100644
--- a/com.oracle.truffle.r.native/library/tools/Makefile
+++ b/com.oracle.truffle.r.native/library/tools/Makefile
@@ -40,6 +40,9 @@ else
 ifeq ($(FASTR_RFFI),llvm)
 XTRA_C_SOURCES += $(SRC)/truffle_llvm/gramRd_llvm.c
 XTRA_C_OBJECTS += $(OBJ)/gramRd_llvm.o
+SULONG_DIR = $(abspath $(FASTR_R_HOME)/../sulong)
+
+SULONG_INCLUDES = -I$(SULONG_DIR)/include
 else
 ifeq ($(FASTR_RFFI),jni)
 XTRA_C_SOURCES += $(SRC)/jni/gramRd_jni.c
@@ -62,7 +65,10 @@ $(OBJ)/%.o: $(GNUR_SRC)/%.c
 	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
 
 $(OBJ)/gramRd_nfi.o: $(SRC)/truffle_nfi/gramRd_nfi.c
-	$(CC) $(CFLAGS) $(FFI_INCLUDES) -c $< -o $@
+	$(CC) $(CFLAGS) $(FFI_INCLUDES) $(NFI_INCLUDES) -c $< -o $@
+
+$(OBJ)/gramRd_llvm.o: $(SRC)/truffle_llvm/gramRd_llvm.c
+	$(CC) $(CFLAGS) $(FFI_INCLUDES) $(SULONG_INCLUDES) -c $< -o $@
 
 $(OBJ)/gramRd_jni.o: $(SRC)/jni/gramRd_jni.c
 	$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@
diff --git a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/caccess.c b/com.oracle.truffle.r.native/library/tools/src/truffle_llvm/gramRd_llvm.c
similarity index 75%
rename from com.oracle.truffle.r.native/fficall/src/truffle_llvm/caccess.c
rename to com.oracle.truffle.r.native/library/tools/src/truffle_llvm/gramRd_llvm.c
index 6743e91b48a8436d2f36d0ae9f41da0926747e0a..a6c7bdc2f870cbf0869e0e2e28795d642697a920 100644
--- a/com.oracle.truffle.r.native/fficall/src/truffle_llvm/caccess.c
+++ b/com.oracle.truffle.r.native/library/tools/src/truffle_llvm/gramRd_llvm.c
@@ -20,19 +20,18 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+#include "../gramRd_fastr.h"
+#include <truffle.h>
 
-int caccess_read_pointer_int(int *address) {
-	return *address;
-}
+typedef int (*call_getc)(void *conn);
 
-double caccess_read_pointer_double(double *address) {
-	return *address;
-}
+static void **gramRd_callbacks = NULL;
 
-int caccess_read_array_int(int *address, int index) {
-	return address[index];
+void gramRd_addCallback(void *callback) {
+	gramRd_callbacks = truffle_managed_malloc(1 * sizeof(void*));
+	gramRd_callbacks[0] = callback;
 }
 
-double caccess_read_array_double(double *address, int index) {
-	return address[index];
+int callGetCMethod(void *conn) {
+	return ((call_getc) gramRd_callbacks[0])(conn);
 }
diff --git a/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c b/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c
index c5716bb4c39a020499f69b2c1d97ecc4edb3d2a1..db70c16af36dc2bf5c8f571fa2d5e8c9a4c1bcbb 100644
--- a/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c
+++ b/com.oracle.truffle.r.native/library/tools/src/truffle_nfi/gramRd_nfi.c
@@ -21,10 +21,12 @@
  * questions.
  */
 #include "../gramRd_fastr.h"
+#include <trufflenfi.h>
 
 static int (*call_RConnGetC)(void *conn);
 
-void gramRd_nfi_init(void *closure) {
+void gramRd_nfi_init(TruffleEnv* env, void *closure) {
+	(*env)->newClosureRef(env, closure);
 	call_RConnGetC = closure;
 }
 
diff --git a/mx.fastr/compilers/fastr-cc b/com.oracle.truffle.r.native/llvm_tools/llvm-c++
similarity index 66%
rename from mx.fastr/compilers/fastr-cc
rename to com.oracle.truffle.r.native/llvm_tools/llvm-c++
index ff05a0f750e2aea46665b44880480462d2d443c0..6708749372cf282269fb11f1cd6c9bae4e67a492 100755
--- a/mx.fastr/compilers/fastr-cc
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-c++
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 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,26 +22,21 @@
 #
 #!/bin/bash
 
-SOURCE="${BASH_SOURCE[0]}"
-while [ -h "$SOURCE" ]; do
-  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
-  SOURCE="$(readlink "$SOURCE")"
-  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
-done
+SOURCE="$0"
 DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
 
-with_sulong=0
-while [ $DIR != "/" ] ; do
-  if [ -d $DIR/sulong ] && [ -d $DIR/sulong/mx.sulong ] ; then
-    with_sulong=1
-    break
-  fi
-  DIR=`dirname $DIR`
-done
+. $DIR/llvm-helper
+fortran=0
+analyze_args "$@"
 
-if [ $with_sulong = 1 ] && [ "$FASTR_SULONG_IGNORE" = "" ] ; then
-	mx --dynamicimport sulong fastr-cc $@
+if [ $is_link -eq 1 ]
+then
+  create_bc_lib "$@"
 else
-    gcc $@
+  llvm_tool=clang++
+  get_llvm_tool
+  runit $llvm_tool_bin $llvm_args
+  mem2reg_opt
+  fake_obj
 fi
 
diff --git a/mx.fastr/compilers/fastr-cpp b/com.oracle.truffle.r.native/llvm_tools/llvm-cc
similarity index 66%
rename from mx.fastr/compilers/fastr-cpp
rename to com.oracle.truffle.r.native/llvm_tools/llvm-cc
index 5e5a24e6cc91d91f5ca7c67efcfb65904417366e..69ddd766c92d216024bd3c330e07dc91c482ac28 100755
--- a/mx.fastr/compilers/fastr-cpp
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-cc
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2017, 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,25 +22,23 @@
 #
 #!/bin/bash
 
-SOURCE="${BASH_SOURCE[0]}"
-while [ -h "$SOURCE" ]; do
-  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
-  SOURCE="$(readlink "$SOURCE")"
-  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
-done
+SOURCE="$0"
 DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
 
-with_sulong=0
-while [ $DIR != "/" ] ; do
-  if [ -d $DIR/sulong ] && [ -d $DIR/sulong/mx.sulong ] ; then
-    with_sulong=1
-    break
-  fi
-  DIR=`dirname $DIR`
-done
+. $DIR/llvm-helper
+fortran=0
+analyze_args "$@"
 
-if [ $with_sulong = 1 ] && [ "$FASTR_SULONG_IGNORE" = "" ] ; then
-	mx --dynamicimport sulong fastr-cpp $@
+
+if [ $is_link -eq 1 ]
+then
+  create_bc_lib "$@"
 else
-    cpp $@
+  llvm_tool=clang
+  get_llvm_tool
+  runit $llvm_tool_bin $llvm_args
+  mem2reg_opt
+  fake_obj
 fi
+
+
diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-fc b/com.oracle.truffle.r.native/llvm_tools/llvm-fc
new file mode 100755
index 0000000000000000000000000000000000000000..1cbd62881872c119b531b496155f13db4f34aab1
--- /dev/null
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-fc
@@ -0,0 +1,64 @@
+#
+# Copyright (c) 2017, 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.
+#
+#!/bin/bash
+
+SOURCE="$0"
+DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
+
+. $DIR/llvm-helper
+fortran=1
+analyze_args "$@"
+
+if [ -z "$FASTR_LLVM_GFORTRAN" ]
+then
+  echo FASTR_LLVM_GFORTRAN must be set
+  exit 1
+fi
+
+if [ -z "$FASTR_LLVM_GFORTRAN_LLVM_AS" ]
+then
+  echo FASTR_LLVM_GFORTRAN_LLVM_AS must be set
+  exit 1
+fi
+
+if [ -z "$FASTR_LLVM_DRAGONEGG" ]
+then
+  echo FASTR_DRAGONEGG must be set
+  exit 1
+fi
+
+function ll_to_bc() {
+  f=`basename $llvm_ir_file`
+  d=`dirname $llvm_ir_file`
+  llvm_ir_bc_file=${d}/${f%%.*}.bc
+}
+
+
+runit $FASTR_LLVM_GFORTRAN -fplugin=$FASTR_LLVM_DRAGONEGG -fplugin-arg-dragonegg-emit-ir $llvm_args
+ll_to_bc
+runit $FASTR_LLVM_GFORTRAN_LLVM_AS $llvm_ir_file -o $llvm_ir_bc_file
+runit rm $llvm_ir_file
+llvm_ir_file=$llvm_ir_bc_file
+mem2reg_opt
+fake_obj
+
diff --git a/com.oracle.truffle.r.native/llvm_tools/llvm-helper b/com.oracle.truffle.r.native/llvm_tools/llvm-helper
new file mode 100644
index 0000000000000000000000000000000000000000..058eb34e7c9099dd368bd056028b4a52625292b4
--- /dev/null
+++ b/com.oracle.truffle.r.native/llvm_tools/llvm-helper
@@ -0,0 +1,160 @@
+#
+# Copyright (c) 2017, 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.
+#
+# Helper functions for llvm-cc et al
+# Global variables are set by these functions
+
+if [ -n "$FASTR_LLVM_TOOLMODE" ]
+then
+  run_mode=$FASTR_LLVM_TOOLMODE
+else
+  run_mode="run"
+fi
+
+function runit() {
+  if [ $run_mode == "echo" ]
+  then
+    echo $@
+  elif [ $run_mode == "echorun" ]
+  then
+    echo $@
+    $@
+  else
+    $@
+  fi
+}
+
+# Input: all the arguments to the original command line
+# Global variables set:
+# llvm_ir_file: name of file containing LLVM IR, e.g. foo.bc
+# llvm_file_ext: extension of above, e.g. .bc
+# llvm_args: processed arguments to pass to llvm tool, e.g. clang
+
+function analyze_args() {
+  llvm_args="-g "
+  if [ $fortran -eq 1 ]
+  then
+    llvm_args+='-S '
+    llvm_file_ext='.ll'
+  else
+    llvm_file_ext='.bc'
+    llvm_args+='-emit-llvm '
+  fi
+
+  is_link=0
+  llvm_ir_file=""
+  
+  while [[ $# -gt 0 ]]
+  do
+    llvm_args+="$1 "
+    case $1 in
+      -o)
+        shift
+	p=$1
+	f=`basename $p`
+	d=`dirname $p`
+	ext=${f##*.}
+	if [ $ext == 'so' ] || [ $ext == 'dylib' ]
+	then
+	  is_link=1
+	elif [ $ext == 'o' ]
+	then
+	  llvm_ir_file=${d}/${f%%.*}
+	  llvm_ir_file+=$llvm_file_ext
+	  llvm_args+="$llvm_ir_file "
+	fi
+      ;;
+     *)
+     ;;
+    esac
+    shift
+  done
+}
+
+# Input arguments:
+# llvm_tool: name of tool to find
+# Global variables set:
+# path to tool (defaults to plain ${llvm_tool}, assumed to be on the PATH)
+
+function get_llvm_tool() {
+  if [ -n "${FASTR_LLVM_HOME}" ]
+  then
+    llvm_tool_bin=${FASTR_LLVM_HOME}/${llvm_tool}
+  else
+    llvm_tool_uc=`echo ${llvm_tool} | tr /a-z/ /A-Z/ | tr /+/ /P/`
+    x=FASTR_LLVM_${llvm_tool_uc}
+    if [ -n  "${!x}" ]
+    then
+      llvm_tool_bin=${!x}
+    else
+      llvm_tool_bin=${llvm_tool}
+    fi
+  fi
+}
+
+
+function mem2reg_opt() {
+   llvm_tool="opt"
+   get_llvm_tool
+   runit ${llvm_tool_bin} -mem2reg $llvm_ir_file -o ${llvm_ir_file}.opt
+   rc=$?
+   if [ $rc -eq 0 ]
+   then
+     runit mv ${llvm_ir_file}.opt $llvm_ir_file
+   fi
+}
+
+function fake_obj() {
+  f=`basename $llvm_ir_file`
+  d=`dirname $llvm_ir_file`
+  runit touch ${d}/${f%%.*}.o 
+}
+
+# Input: all the arguments to the original command line
+function create_bc_lib() {
+  bcfiles=""
+  lib=""
+  while [[ $# -gt 0 ]]
+  do
+    case $1 in
+      -o)
+        shift
+	lib=$1
+      ;;
+     *)
+        f=$1
+     	ext=${f##*.}
+	if [ $ext == 'o' ]
+	then
+	  fn=${f%%.*}.bc
+	  bcfiles+="$fn "
+	fi
+     ;;
+    esac
+    shift
+  done
+
+# we do not have the luxury of controlling the name of the entry (unlike in python)
+# it will be the pathname, which we will reduce to a module name on input in FastR
+
+  runit zip -r $lib $bcfiles
+}
diff --git a/com.oracle.truffle.r.native/run/Makefile b/com.oracle.truffle.r.native/run/Makefile
index 8d0b3687120d49b52006a99541182b95c1970cdf..b793c3585c141f73090286849a5a7e95ff62e392 100644
--- a/com.oracle.truffle.r.native/run/Makefile
+++ b/com.oracle.truffle.r.native/run/Makefile
@@ -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
@@ -53,6 +53,8 @@ ETC_FILES := $(addprefix $(GNUR_HOME)/etc/,javaconf ldpaths Renviron repositorie
 
 SHARE_FILES := $(addprefix $(GNUR_HOME)/share/,R Rd make java encodings)
 
+LLVM_TOOLS := $(wildcard $(FASTR_NATIVE_DIR)/llvm_tools/*)
+
 all: rundirs rcmds includedir
 
 rundirs:
@@ -76,7 +78,7 @@ $(FASTR_BIN_DIR)/R: Makefile R.sh Rscript.sh Rscript_exec.sh Rclasspath.sh
 	cp Rclasspath.sh $(FASTR_BIN_DIR)/execRextras/Rclasspath
 	chmod +x $(FASTR_BIN_DIR)/exec/R $(FASTR_BIN_DIR)/execRextras/Rscript $(FASTR_BIN_DIR)/Rscript $(FASTR_BIN_DIR)/execRextras/Rclasspath
 	# update R_HOME_DIR to FastR
-	sed -e 's!^\(R_HOME_DIR=\)\(.*\)!\1"$(FASTR_R_HOME)"!' < $(R_SCRIPT) > $(FASTR_BIN_DIR)/R
+	(sed -e 's!^\(R_HOME_DIR=\)\(.*\)!\1"$(FASTR_R_HOME)"!' | sed -e 's/    -h.--help./    --r-help\)/') < $(R_SCRIPT) > $(FASTR_BIN_DIR)/R
 	chmod +x $(FASTR_BIN_DIR)/R 
 	touch $(FASTR_ETC_DIR)/ldpaths
 	sed -e "s|\(R_LIBS_USER=.*-'\)\(.*\)'}|\1$(FASTR_R_HOME)/library'}|" < $(GNUR_HOME)/etc/Renviron > $(FASTR_ETC_DIR)/Renviron
@@ -85,12 +87,18 @@ $(FASTR_BIN_DIR)/R: Makefile R.sh Rscript.sh Rscript_exec.sh Rclasspath.sh
 	cp $(GNUR_HOME)/etc/repositories $(FASTR_ETC_DIR)/repositories
 	cp $(GNUR_HOME)/etc/ldpaths $(FASTR_ETC_DIR)/ldpaths
 	ed Makeconf.etc < edMakeconf.etc
+ifeq ($(FASTR_RFFI),llvm)
+	ed Makeconf.etc < edMakeconf.etc.llvm
+	cp $(LLVM_TOOLS) $(FASTR_BIN_DIR)
+endif
 	cp Makeconf.etc $(FASTR_ETC_DIR)/Makeconf
 	cp -r $(SHARE_FILES) $(FASTR_SHARE_DIR)
 	# TODO may need filtering
 	cp -r $(DOC_FILES) $(FASTR_DOC_DIR)
 	# overrides
 	cp examples-header.R examples-footer.R $(FASTR_SHARE_DIR)/R
+	# record the FFI version
+	bash -c "echo -n $(FASTR_RFFI) >$(FASTR_ETC_DIR)/ffibuildtype"
 
 includedir: $(FASTR_R_HOME)/include/Rinternals.h
 
diff --git a/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm b/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm
new file mode 100644
index 0000000000000000000000000000000000000000..b079665f85e0bd0e746a91f0ef81c9438293d91d
--- /dev/null
+++ b/com.oracle.truffle.r.native/run/edMakeconf.etc.llvm
@@ -0,0 +1,27 @@
+/^CC =/
+d
+i
+CC = $(R_HOME)/bin/llvm-cc
+.
+/^CXX =/
+d
+i
+CXX = $(R_HOME)/bin/llvm-c++
+.
+/^FC =/
+d
+i
+FC = $(R_HOME)/bin/llvm-fc
+.
+/^F77 =/
+d
+i
+F77 = $(R_HOME)/bin/llvm-fc
+.
+/^OBJC =/
+d
+i
+OBJC = $(R_HOME)/bin/llvm-cc
+.
+w
+q
diff --git a/com.oracle.truffle.r.native/version.source b/com.oracle.truffle.r.native/version.source
index 409940768f2a684935a7d15a29f96e82c487f439..7facc89938bbc5635e3d36ffa56b4c85e9b07db8 100644
--- a/com.oracle.truffle.r.native/version.source
+++ b/com.oracle.truffle.r.native/version.source
@@ -1 +1 @@
-23
+36
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java
index 701bc12f35e8be31b0a6024361e7558becdebd2e..a9e8526f52283062b09dea5a4f1a1e95e6547f38 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/EagerResourceHandlerFactory.java
@@ -31,7 +31,6 @@ import java.net.URL;
 import java.nio.file.Files;
 import java.nio.file.Paths;
 import java.security.CodeSource;
-import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Map;
@@ -140,17 +139,14 @@ public class EagerResourceHandlerFactory extends ResourceHandlerFactory implemen
     }
 
     @Override
-    public String[] getRFiles(Class<?> accessor, String pkgName) {
-        ArrayList<String> list = new ArrayList<>();
+    public Map<String, String> getRFiles(Class<?> accessor, String pkgName) {
+        Map<String, String> result = new HashMap<>();
         for (Map.Entry<String, FileInfo> entry : files.entrySet()) {
             if (entry.getValue().url.toString().contains(pkgName + "/R")) {
                 String content = new String(entry.getValue().data);
-                list.add(content);
+                result.put(entry.getValue().url.toString(), content);
             }
         }
-        String[] result = new String[list.size()];
-        list.toArray(result);
         return result;
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
index 980ba240c7bf383fc3686e52e2830f07cbc5e08d..7718503513539ace7444d0777c02d1ca02f0d0f4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackage.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.function.Supplier;
@@ -101,7 +102,7 @@ public abstract class RBuiltinPackage {
         return name;
     }
 
-    private static final ConcurrentHashMap<String, String[]> rFilesCache = new ConcurrentHashMap<>();
+    private static final ConcurrentHashMap<String, Map<String, String>> rFilesCache = new ConcurrentHashMap<>();
 
     /**
      * Get a list of R override files for package {@code pkgName}, from the {@code pkgName/R}
@@ -109,12 +110,12 @@ public abstract class RBuiltinPackage {
      */
     public static ArrayList<Source> getRFiles(String pkgName) {
         ArrayList<Source> componentList = new ArrayList<>();
-        String[] rFileContents = rFilesCache.get(pkgName);
+        Map<String, String> rFileContents = rFilesCache.get(pkgName);
         if (rFileContents == null) {
             rFileContents = ResourceHandlerFactory.getHandler().getRFiles(RBuiltinPackage.class, pkgName);
             rFilesCache.put(pkgName, rFileContents);
         }
-        for (String rFileContent : rFileContents) {
+        for (String rFileContent : rFileContents.values()) {
             Source content = RSource.fromTextInternal(rFileContent, RSource.Internal.R_IMPL);
             componentList.add(content);
         }
@@ -145,18 +146,28 @@ public abstract class RBuiltinPackage {
         }
     }
 
+    protected void add(Class<?> builtinMetaClass, Class<?> builtinClass,
+                    Supplier<RBuiltinNode> constructor) {
+        add(builtinMetaClass, builtinClass, constructor, null);
+    }
+
     protected void add(Class<?> builtinClass,
                     Supplier<RBuiltinNode> constructor) {
         add(builtinClass, constructor, null);
     }
 
     protected void add(Class<?> builtinClass, Supplier<RBuiltinNode> constructor, RSpecialFactory specialCall) {
-        RBuiltin annotation = builtinClass.getAnnotation(RBuiltin.class);
+        add(builtinClass, builtinClass, constructor, specialCall);
+    }
+
+    protected void add(Class<?> builtinMetaClass, Class<?> builtinClass, Supplier<RBuiltinNode> constructor, RSpecialFactory specialCall) {
+        RBuiltin annotation = builtinMetaClass.getAnnotation(RBuiltin.class);
         String[] parameterNames = annotation.parameterNames();
         parameterNames = Arrays.stream(parameterNames).map(n -> n.isEmpty() ? null : n).toArray(String[]::new);
         ArgumentsSignature signature = ArgumentsSignature.get(parameterNames);
 
-        putBuiltin(new RBuiltinFactory(annotation.name(), builtinClass, annotation.visibility(), annotation.aliases(), annotation.kind(), signature, annotation.nonEvalArgs(), annotation.splitCaller(),
+        putBuiltin(new RBuiltinFactory(annotation.name(), builtinMetaClass, builtinClass, annotation.visibility(), annotation.aliases(), annotation.kind(), signature, annotation.nonEvalArgs(),
+                        annotation.splitCaller(),
                         annotation.alwaysSplit(), annotation.dispatch(), annotation.genericName(), constructor, annotation.behavior(), specialCall));
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
index aac98e96fe31cdff43ad564b9b6b09520fd8b701..2d774b7c73d36ab3feaafe8032a4ee7b639b35ee 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/RBuiltinPackages.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.nodes.builtin.base.BasePackage;
@@ -50,6 +51,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinLookup;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -69,7 +71,7 @@ public final class RBuiltinPackages implements RBuiltinLookup {
         return instance;
     }
 
-    public static void loadBase(MaterializedFrame baseFrame) {
+    public static void loadBase(TruffleRLanguage language, MaterializedFrame baseFrame) {
         RBuiltinPackage pkg = basePackage;
         REnvironment baseEnv = REnvironment.baseEnv();
         BaseVariables.initialize(baseEnv);
@@ -82,7 +84,7 @@ public final class RBuiltinPackages implements RBuiltinLookup {
             String methodName = entrySet.getKey();
             RBuiltinFactory builtinFactory = entrySet.getValue();
             if (builtinFactory.getKind() != RBuiltinKind.INTERNAL) {
-                RFunction function = createFunction(builtinFactory, methodName);
+                RFunction function = createFunction(language, builtinFactory, methodName);
                 try {
                     baseEnv.put(methodName, function);
                     baseEnv.lockBinding(methodName);
@@ -115,6 +117,11 @@ public final class RBuiltinPackages implements RBuiltinLookup {
             } catch (ParseException e) {
                 throw new RInternalError(e, "error while parsing base source from %s", baseSource.getName());
             }
+            // forcibly clear last.warnings during startup:
+            FrameSlot slot = baseFrame.getFrameDescriptor().findFrameSlot("last.warning");
+            if (slot != null) {
+                FrameSlotChangeMonitor.setObject(baseFrame, slot, null);
+            }
         } finally {
             RContext.getInstance().setLoadingBase(false);
         }
@@ -138,15 +145,10 @@ public final class RBuiltinPackages implements RBuiltinLookup {
         }
     }
 
-    /**
-     * Global builtin cache.
-     */
-    private static final HashMap<String, RFunction> cachedBuiltinFunctions = new HashMap<>();
-
     @Override
-    public RFunction lookupBuiltin(String methodName) {
+    public RFunction lookupBuiltin(TruffleRLanguage language, String methodName) {
         CompilerAsserts.neverPartOfCompilation();
-        RFunction function = cachedBuiltinFunctions.get(methodName);
+        RFunction function = language.getBuiltinFunctionCache().get(methodName);
         if (function != null) {
             return function;
         }
@@ -155,27 +157,28 @@ public final class RBuiltinPackages implements RBuiltinLookup {
         if (builtin == null) {
             return null;
         }
-        return createFunction(builtin, methodName);
+        return createFunction(language, builtin, methodName);
     }
 
-    private static RootCallTarget createArgumentsCallTarget(RBuiltinFactory builtin) {
+    private static RootCallTarget createArgumentsCallTarget(TruffleRLanguage language, RBuiltinFactory builtin) {
         CompilerAsserts.neverPartOfCompilation();
 
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        RBuiltinRootNode root = new RBuiltinRootNode(builtin, frameDescriptor, null);
+        RBuiltinRootNode root = new RBuiltinRootNode(language, builtin, frameDescriptor, null);
         FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(builtin.getName(), frameDescriptor);
         return Truffle.getRuntime().createCallTarget(root);
     }
 
-    private static RFunction createFunction(RBuiltinFactory builtinFactory, String methodName) {
+    private static RFunction createFunction(TruffleRLanguage language, RBuiltinFactory builtinFactory, String methodName) {
         try {
-            RFunction function = cachedBuiltinFunctions.get(methodName);
+            HashMap<String, RFunction> cache = language.getBuiltinFunctionCache();
+            RFunction function = cache.get(methodName);
             if (function != null) {
                 return function;
             }
-            RootCallTarget callTarget = createArgumentsCallTarget(builtinFactory);
+            RootCallTarget callTarget = createArgumentsCallTarget(language, builtinFactory);
             function = RDataFactory.createFunction(builtinFactory.getName(), "base", callTarget, builtinFactory, null);
-            cachedBuiltinFunctions.put(methodName, function);
+            cache.put(methodName, function);
             return function;
         } catch (Throwable t) {
             throw new RuntimeException("error while creating builtin " + methodName + " / " + builtinFactory, t);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
index 5930d40906f9b27ab93507d436d496c1d7a2b457..0b7bea50bf7e33cc7c76a4dfb782b1d26091f899 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
@@ -23,9 +23,11 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -34,6 +36,7 @@ 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.RNull;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
@@ -45,6 +48,10 @@ public abstract class APerm extends RBuiltinNode.Arg3 {
 
     private final BranchProfile emptyPermVector = BranchProfile.create();
     private final ConditionProfile mustResize = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile setDimNamesProfile = ConditionProfile.createBinaryProfile();
+
+    @Child private SetDimNamesAttributeNode setDimNames;
+    @Child private ExtractListElement extractListElement;
 
     static {
         Casts casts = new Casts(APerm.class);
@@ -104,7 +111,8 @@ public abstract class APerm extends RBuiltinNode.Arg3 {
     @Specialization
     protected RAbstractVector aPerm(RAbstractVector vector, RAbstractIntVector permVector, byte resize,
                     @Cached("create()") GetDimAttributeNode getDimsNode,
-                    @Cached("create()") SetDimAttributeNode setDimsNode) {
+                    @Cached("create()") SetDimAttributeNode setDimsNode,
+                    @Cached("create()") GetDimNamesAttributeNode getDimNamesNode) {
 
         int[] dim = getDimsNode.getDimensions(vector);
         checkErrorConditions(dim);
@@ -124,6 +132,25 @@ public abstract class APerm extends RBuiltinNode.Arg3 {
             posV = incArray(posV, pDim);
         }
 
+        RList dimNames = getDimNamesNode.getDimNames(vector);
+        if (setDimNamesProfile.profile(dimNames != null)) {
+            if (setDimNames == null) {
+                setDimNames = insert(SetDimNamesAttributeNode.create());
+                extractListElement = insert(ExtractListElement.create());
+            }
+            Object[] permData = new Object[dimNames.getLength()];
+            RStringVector names = dimNames.getNames(); // May be null for "list(NULL,NULL)"
+            String[] permNames = (names != null) ? new String[permData.length] : null;
+            for (int i = 0; i < permData.length; i++) {
+                permData[i] = extractListElement.execute(dimNames, perm[i]);
+                if (permNames != null) {
+                    permNames[i] = names.getDataAt(perm[i]);
+                }
+            }
+            RList permDimNames = RDataFactory.createList(permData, (names != null) ? RDataFactory.createStringVector(permNames, names.isComplete()) : null);
+            setDimNames.setDimNames(result, permDimNames);
+        }
+
         return result;
     }
 
@@ -150,7 +177,7 @@ public abstract class APerm extends RBuiltinNode.Arg3 {
         }
 
         // Note: if this turns out to be slow, we can cache the permutation
-        return aPerm(vector, RDataFactory.createIntVector(perm, true), resize, getDimsNode, setDimsNode);
+        return aPerm(vector, RDataFactory.createIntVector(perm, true), resize, getDimsNode, setDimsNode, getDimNamesNode);
     }
 
     private static int[] getReverse(int[] dim) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java
index b3604b3037b1952cbf6d1786c60895f4578107cd..1a4545d3fc9a09660d61c795a18687b72efdbfc9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/All.java
@@ -23,14 +23,14 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RDispatch.SUMMARY_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUMMARY;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
-@RBuiltin(name = "all", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
+@RBuiltin(name = "all", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE_SUMMARY)
 public abstract class All extends Quantifier {
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java
index 30375f72c6613f1bc93bfe6845189ba73c7aec68..4f15454bb7c7389e996deae2e8b0926d43eb2317 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Any.java
@@ -23,14 +23,14 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RDispatch.SUMMARY_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUMMARY;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 
-@RBuiltin(name = "any", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
+@RBuiltin(name = "any", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE_SUMMARY)
 public abstract class Any extends Quantifier {
 
     static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
index 217ee20c8ec7163c7f1103833eef89499cdbad60..515d57eec9c176430c07e87124e1c292f75e5d93 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
@@ -24,12 +24,11 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUMMARY;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
@@ -49,12 +48,12 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-@RBuiltin(name = "anyNA", kind = PRIMITIVE, parameterNames = {"x", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
+@RBuiltin(name = "anyNA", kind = PRIMITIVE, parameterNames = {"x", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE_SUMMARY)
 public abstract class AnyNA extends RBuiltinNode.Arg2 {
 
     private final NACheck naCheck = NACheck.create();
 
-    public abstract byte execute(VirtualFrame frame, Object value, boolean recursive);
+    public abstract byte execute(Object value, boolean recursive);
 
     static {
         Casts casts = new Casts(AnyNA.class);
@@ -157,15 +156,15 @@ public abstract class AnyNA extends RBuiltinNode.Arg2 {
     }
 
     @Specialization(guards = "recursive")
-    protected byte isNA(VirtualFrame frame, RList list, boolean recursive,
+    protected byte isNA(RList list, boolean recursive,
                     @Cached("createRecursive()") AnyNA recursiveNode,
                     @Cached("createClassProfile()") ValueProfile elementProfile,
                     @Cached("create()") RLengthNode length) {
 
         for (int i = 0; i < list.getLength(); i++) {
             Object value = elementProfile.profile(list.getDataAt(i));
-            if (length.executeInteger(frame, value) > 0) {
-                byte result = recursiveNode.execute(frame, value, recursive);
+            if (length.executeInteger(value) > 0) {
+                byte result = recursiveNode.execute(value, recursive);
                 if (result == RRuntime.LOGICAL_TRUE) {
                     return RRuntime.LOGICAL_TRUE;
                 }
@@ -176,7 +175,7 @@ public abstract class AnyNA extends RBuiltinNode.Arg2 {
 
     @Specialization(guards = "!recursive")
     @SuppressWarnings("unused")
-    protected byte isNA(VirtualFrame frame, RList list, boolean recursive) {
+    protected byte isNA(RList list, boolean recursive) {
         return RRuntime.LOGICAL_FALSE;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java
deleted file mode 100644
index 130ec5a77e8d0e2344b0ff675af560e2908df99f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Arg.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.builtin.base;
-
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.runtime.RDispatch.COMPLEX_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
-import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
-
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-
-@RBuiltin(name = "Arg", kind = PRIMITIVE, parameterNames = {"z"}, dispatch = COMPLEX_GROUP_GENERIC, behavior = PURE)
-public abstract class Arg extends UnaryArithmeticBuiltinNode {
-
-    public Arg() {
-        super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
-    }
-
-    static {
-        Casts casts = new Casts(Arg.class);
-        casts.arg("z").mustBe(numericValue().or(complexValue()), RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION);
-    }
-
-    @Override
-    public RType calculateResultType(RType argumentType) {
-        switch (argumentType) {
-            case Complex:
-                return RType.Double;
-            default:
-                return super.calculateResultType(argumentType);
-        }
-    }
-
-    @Override
-    public int op(byte op) {
-        return 0;
-    }
-
-    @Override
-    public int op(int op) {
-        return op;
-    }
-
-    @Override
-    public double op(double op) {
-        if (op >= 0) {
-            return 0;
-        } else {
-            return Math.PI;
-        }
-    }
-
-    @Override
-    public double opd(double re, double im) {
-        return Math.atan2(im, re);
-    }
-
-    @Specialization
-    @Override
-    public Object calculateUnboxed(Object op) {
-        return super.calculateUnboxed(op);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
index b2eddad3015480640b7f423eec79d4bf52e7b15e..12232ab137e342c1b43594c39d61fa10042aa5ce 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Args.java
@@ -89,7 +89,7 @@ public abstract class Args extends RBuiltinNode.Arg1 {
         RRootNode rootNode = (RRootNode) fun.getTarget().getRootNode();
         FormalArguments formals = rootNode.getFormalArguments();
         String newDesc = "args(" + rootNode.getDescription() + ")";
-        FunctionDefinitionNode newNode = FunctionDefinitionNode.create(RSyntaxNode.LAZY_DEPARSE, rootNode.getFrameDescriptor(), null, SaveArgumentsNode.NO_ARGS,
+        FunctionDefinitionNode newNode = FunctionDefinitionNode.create(getRLanguage(), RSyntaxNode.LAZY_DEPARSE, rootNode.getFrameDescriptor(), null, SaveArgumentsNode.NO_ARGS,
                         ConstantNode.create(RSyntaxNode.LAZY_DEPARSE, RNull.instance), formals, newDesc, null);
         return RDataFactory.createFunction(newDesc, RFunction.NO_NAME, Truffle.getRuntime().createCallTarget(newNode), null, REnvironment.globalEnv().getFrame());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
index 436d647e5b0272fb1e93448706808a897b05d80b..5ad02cca608837419ec6fc089a807a26b7d0fc2e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCall.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.Call.CallUtil;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -56,22 +57,26 @@ public abstract class AsCall extends RBuiltinNode.Arg1 {
         Casts.noCasts(AsCall.class);
     }
 
+    @Child private CallUtil util = new CallUtil();
+
     @Specialization
     protected RLanguage asCallFunction(RList x) {
         // TODO error checks
         RArgsValuesAndNames avn = makeNamesAndValues(x);
         if (x.getDataAt(0) instanceof RSymbol) {
-            return Call.makeCallSourceUnavailable(((RSymbol) x.getDataAt(0)).getName(), avn);
+            return util.makeCallSourceUnavailable(((RSymbol) x.getDataAt(0)).getName(), avn);
         } else if (x.getDataAt(0) instanceof String) {
-            return Call.makeCallSourceUnavailable((String) x.getDataAt(0), avn);
+            return util.makeCallSourceUnavailable((String) x.getDataAt(0), avn);
         } else if (x.getDataAt(0) instanceof RAbstractStringVector) {
-            return Call.makeCallSourceUnavailable(((RAbstractStringVector) x.getDataAt(0)).getDataAt(0), avn);
+            return util.makeCallSourceUnavailable(((RAbstractStringVector) x.getDataAt(0)).getDataAt(0), avn);
         } else if (x.getDataAt(0) instanceof RFunction) {
-            return Call.makeCallSourceUnavailable((RFunction) x.getDataAt(0), avn);
+            return CallUtil.makeCallSourceUnavailable((RFunction) x.getDataAt(0), avn);
         } else if (x.getDataAt(0) instanceof Integer) {
-            return Call.makeCallSourceUnavailable((Integer) x.getDataAt(0), avn);
+            return CallUtil.makeCallSourceUnavailable((Integer) x.getDataAt(0), avn);
         } else if (x.getDataAt(0) instanceof Double) {
-            return Call.makeCallSourceUnavailable((Double) x.getDataAt(0), avn);
+            return CallUtil.makeCallSourceUnavailable((Double) x.getDataAt(0), avn);
+        } else if (x.getDataAt(0) instanceof RLanguage) {
+            return (RLanguage) x.getDataAt(0);
         } else {
             throw RInternalError.unimplemented();
         }
@@ -87,7 +92,7 @@ public abstract class AsCall extends RBuiltinNode.Arg1 {
             RLanguage l = (RLanguage) x.getDataAt(0);
             f = ((ReadVariableNode) RASTUtils.unwrap(l.getRep())).getIdentifier();
         }
-        return Call.makeCallSourceUnavailable(f, makeNamesAndValues(x));
+        return util.makeCallSourceUnavailable(f, makeNamesAndValues(x));
     }
 
     private RArgsValuesAndNames makeNamesAndValues(RAbstractContainer x) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
index fc78a3380061c29124b906e348e6805793462ca7..8c864fd5ecc6df02e3c0ed012b78dc572e1e8b99 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java
@@ -31,11 +31,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RDispatch;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 
-@RBuiltin(name = "as.double", aliases = {"as.numeric"}, kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
+@RBuiltin(name = "as.double", aliases = {"as.numeric"}, kind = PRIMITIVE, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "..."}, behavior = PURE)
 public abstract class AsDouble extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
index d465f8dea58e6a08ff9b0403d2e1274fc47eb3b7..6f9d7397c1b608445af908913e2243fe6c0ff088 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsFunction.java
@@ -32,9 +32,7 @@ import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.r.nodes.access.AccessArgumentNode;
-import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
@@ -45,6 +43,7 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExpression;
@@ -96,7 +95,7 @@ public abstract class AsFunction extends RBuiltinNode.Arg2 {
                 if (arg == RMissing.instance) {
                     defaultValue = null;
                 } else if (arg == RNull.instance) {
-                    defaultValue = ConstantNode.create(RNull.instance);
+                    defaultValue = RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, RNull.instance).asRNode();
                 } else if (arg instanceof RLanguage) {
                     defaultValue = (RNode) ((RLanguage) arg).getRep();
                 } else if (arg instanceof RSymbol) {
@@ -104,10 +103,10 @@ public abstract class AsFunction extends RBuiltinNode.Arg2 {
                     if (symbol.isMissing()) {
                         defaultValue = null;
                     } else {
-                        defaultValue = ReadVariableNode.create(symbol.getName());
+                        defaultValue = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, symbol.getName(), false).asRNode();
                     }
-                } else if (RRuntime.asAbstractVector(arg) instanceof RAttributable) {
-                    defaultValue = ConstantNode.create(arg);
+                } else if (RRuntime.convertScalarVectors(arg) instanceof RAttributable) {
+                    defaultValue = RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, arg).asRNode();
                 } else {
                     throw RInternalError.unimplemented();
                 }
@@ -132,10 +131,10 @@ public abstract class AsFunction extends RBuiltinNode.Arg2 {
         if (bodyObject instanceof RLanguage) {
             body = ((RLanguage) x.getDataAtAsObject(x.getLength() - 1)).getRep();
         } else if (bodyObject instanceof RSymbol) {
-            body = ReadVariableNode.create(((RSymbol) bodyObject).getName());
+            body = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) bodyObject).getName(), false).asRNode();
         } else {
             assert bodyObject instanceof Integer || bodyObject instanceof Double || bodyObject instanceof Byte || bodyObject instanceof String;
-            body = ConstantNode.create(bodyObject);
+            body = RContext.getASTBuilder().constant(RSyntaxNode.LAZY_DEPARSE, bodyObject).asRNode();
         }
         if (!RBaseNode.isRSyntaxNode(body)) {
             throw RInternalError.unimplemented();
@@ -143,7 +142,8 @@ public abstract class AsFunction extends RBuiltinNode.Arg2 {
         FrameDescriptor descriptor = new FrameDescriptor();
         FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("<as.function.default>", descriptor);
         FrameSlotChangeMonitor.initializeEnclosingFrame(descriptor, envir.getFrame());
-        FunctionDefinitionNode rootNode = FunctionDefinitionNode.create(RSyntaxNode.LAZY_DEPARSE, descriptor, null, saveArguments, (RSyntaxNode) body, formals, "from AsFunction", null);
+        FunctionDefinitionNode rootNode = FunctionDefinitionNode.create(getRLanguage(), RSyntaxNode.LAZY_DEPARSE, descriptor, null, saveArguments, (RSyntaxNode) body, formals, "from AsFunction",
+                        null);
         RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
         return RDataFactory.createFunction(RFunction.NO_NAME, RFunction.NO_NAME, callTarget, null, envir.getFrame());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
index 35f09fb010d3f10bd55af458dd42335abf4ed799..bed3577395dd0cd89c1a94c3e9133dea90605722 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -35,7 +36,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
-@RBuiltin(name = "as.integer", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
+@RBuiltin(name = "as.integer", kind = PRIMITIVE, dispatch = INTERNAL_GENERIC, parameterNames = {"x", "..."}, behavior = PURE)
 public abstract class AsInteger extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
index 3bdca002dea69b0a8b6be9d467be2958010d683f..0932f151059671380b639e3188ab92cd0f14e035 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsLogical.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyLogicalVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -35,7 +36,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 
-@RBuiltin(name = "as.logical", kind = PRIMITIVE, parameterNames = {"x", "..."}, behavior = PURE)
+@RBuiltin(name = "as.logical", kind = PRIMITIVE, dispatch = INTERNAL_GENERIC, parameterNames = {"x", "..."}, behavior = PURE)
 public abstract class AsLogical extends RBuiltinNode.Arg2 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
index de58fbb3b766943aa47841bef6f4f71dea325ea8..e430bfc593783fa5a497c25816291203800efaf2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsRaw.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
+import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -35,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 
-@RBuiltin(name = "as.raw", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
+@RBuiltin(name = "as.raw", kind = PRIMITIVE, dispatch = INTERNAL_GENERIC, parameterNames = {"x"}, behavior = PURE)
 public abstract class AsRaw extends RBuiltinNode.Arg1 {
 
     private final ConditionProfile noAttributes = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
index ece6175263701856a21d98d2ceeb984d7dd58dc5..776a5b37de2972097b39584ad76ab46adc0f897d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
@@ -59,6 +60,7 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -68,8 +70,9 @@ import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @RBuiltin(name = "as.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, dispatch = INTERNAL_GENERIC, behavior = COMPLEX)
@@ -118,6 +121,7 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
         return internal.execute(x, mode);
     }
 
+    @ImportStatic(RRuntime.class)
     public abstract static class AsVectorInternal extends Node {
 
         public abstract Object execute(Object x, String mode);
@@ -160,6 +164,10 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
             return mode == cachedMode || indirectMatchProfile.profile(cachedMode.equals(mode));
         }
 
+        protected ForeignArray2R createForeignArray2R() {
+            return ForeignArray2RNodeGen.create();
+        }
+
         // there should never be more than ~12 specializations
         @SuppressWarnings("unused")
         @Specialization(limit = "99", guards = "matchesMode(mode, cachedMode)")
@@ -167,7 +175,19 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
                         @Cached("mode") String cachedMode,
                         @Cached("fromMode(cachedMode)") RType type,
                         @Cached("createCast(type)") CastNode cast,
-                        @Cached("create()") DropAttributesNode drop) {
+                        @Cached("create()") DropAttributesNode drop,
+                        @Cached("createForeignArray2R()") ForeignArray2R foreignArray2R) {
+            if (RRuntime.isForeignObject(x)) {
+                Object o = foreignArray2R.execute(x, true);
+                if (!RRuntime.isForeignObject(o)) {
+                    return cast == null ? o : cast.doCast(o);
+                }
+                if (type == RType.List) {
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "list");
+                } else {
+                    throw RError.error(RError.SHOW_CALLER, RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "vector");
+                }
+            }
             return drop.execute(cast == null ? x : cast.doCast(x));
         }
 
@@ -223,7 +243,7 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
 
             @Specialization
             @TruffleBoundary
-            protected Object castPairlist(RAbstractListVector x) {
+            protected Object castPairlist(RAbstractVector x) {
                 // TODO implement non-empty element list conversion; this is a placeholder for type
                 // test
                 if (x.getLength() == 0) {
@@ -233,16 +253,21 @@ public abstract class AsVector extends RBuiltinNode.Arg2 {
                     RStringVector names = x.getNames();
                     for (int i = x.getLength() - 1; i >= 0; i--) {
                         Object name = names == null ? RNull.instance : RDataFactory.createSymbolInterned(names.getDataAt(i));
-                        Object data = x.getDataAt(i);
+                        Object data = x.getDataAtAsObject(i);
                         list = RDataFactory.createPairList(data, list, name);
                     }
                     return list;
                 }
             }
 
+            @Specialization
+            protected Object doRNull(@SuppressWarnings("unused") RNull value) {
+                return RNull.instance;
+            }
+
             @Fallback
-            protected Object castPairlist(@SuppressWarnings("unused") Object x) {
-                throw RInternalError.unimplemented("non-list casts to pairlist");
+            protected Object castPairlist(Object x) {
+                throw RInternalError.unimplemented("non-list casts to pairlist for " + x.getClass().getSimpleName());
             }
         }
     }
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 42325e9757f5c0822e37f34d38c0c357e9efbdaa..3e2489c23cab0c3661c4ab8e883a8dc5628b0f47 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
@@ -35,6 +35,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.GetAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.IterableAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetRowNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -47,11 +48,9 @@ import com.oracle.truffle.r.runtime.RRuntime;
 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.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 
 @RBuiltin(name = "attr", kind = PRIMITIVE, parameterNames = {"x", "which", "exact"}, behavior = PURE)
 public abstract class Attr extends RBuiltinNode.Arg3 {
@@ -124,7 +123,7 @@ public abstract class Attr extends RBuiltinNode.Arg3 {
         if (attributes == null) {
             return RNull.instance;
         } else {
-            return getFullRowNames(getRowNamesNode.getRowNames(container));
+            return GetAttributesNode.getFullRowNames(getRowNamesNode.getRowNames(container));
         }
     }
 
@@ -143,20 +142,6 @@ public abstract class Attr extends RBuiltinNode.Arg3 {
         }
     }
 
-    public static Object getFullRowNames(Object a) {
-        if (a == RNull.instance) {
-            return RNull.instance;
-        } else {
-            if (a instanceof RAbstractIntVector) {
-                RAbstractIntVector rowNames = (RAbstractIntVector) a;
-                if (rowNames.getLength() == 2 && RRuntime.isNA(rowNames.getDataAt(0))) {
-                    return RDataFactory.createIntSequence(1, 1, Math.abs(rowNames.getDataAt(1)));
-                }
-            }
-            return a;
-        }
-    }
-
     protected static boolean isRowNamesAttr(String name) {
         return name.equals(RRuntime.ROWNAMES_ATTR_KEY);
     }
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 5f3aee4e78d586e8754665ea9e0e3f6a480975a3..668410e59d03995caaafbb39e9b82a80fccc571f 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
@@ -25,109 +25,44 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import java.util.Arrays;
-
 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.object.DynamicObject;
-import com.oracle.truffle.api.profiles.BranchProfile;
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.GetAttributesNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 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.RLanguage;
-import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @RBuiltin(name = "attributes", kind = PRIMITIVE, parameterNames = {"obj"}, behavior = PURE)
 public abstract class Attributes extends RBuiltinNode.Arg1 {
 
-    private final BranchProfile rownamesBranch = BranchProfile.create();
-    @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
-    @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
+    @Child private GetAttributesNode getAttributesNode = GetAttributesNode.create();
 
     static {
         Casts.noCasts(Attributes.class);
     }
 
     @Specialization
-    protected Object attributesNull(RAbstractContainer container,
-                    @Cached("createBinaryProfile()") ConditionProfile hasAttributesProfile) {
-        if (hasAttributesProfile.profile(hasAttributes(container))) {
-            return createResult(container, container instanceof RLanguage);
-        } else {
-            return RNull.instance;
-        }
+    protected Object attributesNull(RAbstractContainer container) {
+        return getAttributesNode.execute(container);
     }
 
     /**
-     * Unusual cases that it is not worth specializing on as they are not performance-centric,
-     * basically any type that is not an {@link RAbstractContainer} but is {@link RAttributable},
-     * e.g. {@link REnvironment}.
+     * Unusual cases that it is not worth specializing on as they are not performance-centric.
      */
     @Fallback
     @TruffleBoundary
     protected Object attributes(Object object) {
         if (object instanceof RAttributable) {
-            if (!hasAttributes((RAttributable) object)) {
-                return RNull.instance;
-            } else {
-                return createResult((RAttributable) object, false);
-            }
+            return getAttributesNode.execute((RAttributable) object);
         } else if (object == RNull.instance || RRuntime.isForeignObject(object)) {
             return RNull.instance;
         } else {
             throw RError.nyi(this, "object cannot be attributed");
         }
     }
-
-    /**
-     * {@code language} objects behave differently regarding "names"; they don't get included.
-     */
-    private Object createResult(RAttributable attributable, boolean ignoreNames) {
-        DynamicObject attributes = attributable.getAttributes();
-        int size = attributes.size();
-        String[] names = new String[size];
-        Object[] values = new Object[size];
-        int z = 0;
-        for (RAttributesLayout.RAttribute attr : arrayAttrAccess.execute(attributes)) {
-            String name = attr.getName();
-            if (ignoreNames && name.equals(RRuntime.NAMES_ATTR_KEY)) {
-                continue;
-            }
-            names[z] = name;
-            if (name.equals(RRuntime.ROWNAMES_ATTR_KEY)) {
-                rownamesBranch.enter();
-                values[z] = Attr.getFullRowNames(attr.getValue());
-            } else {
-                values[z] = attr.getValue();
-            }
-            z++;
-        }
-        if (ignoreNames && z != names.length) {
-            if (z == 0) {
-                return RNull.instance;
-            } else {
-                names = Arrays.copyOfRange(names, 0, names.length - 1);
-                values = Arrays.copyOfRange(values, 0, values.length - 1);
-            }
-        }
-        RList result = RDataFactory.createList(values);
-        setNamesNode.setNames(result, RDataFactory.createStringVector(names, true));
-        return result;
-    }
-
-    private static boolean hasAttributes(RAttributable attributable) {
-        return attributable.getAttributes() != null && !attributable.getAttributes().isEmpty();
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
index 7befd61a6d92b13739f47315f30ab3f29e202af5..34ef1ba2767595d042291e46004c6ca53f08f993 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java
@@ -27,8 +27,10 @@ import static com.oracle.truffle.r.runtime.nmath.RMath.fmax2;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.BaseGammaFunctionsFactory.DpsiFnCalcNodeGen;
 import com.oracle.truffle.r.runtime.RError;
@@ -53,7 +55,8 @@ public class BaseGammaFunctions {
         }
 
         @Specialization
-        protected RDoubleVector digamma(RAbstractDoubleVector x) {
+        protected RDoubleVector digamma(RAbstractDoubleVector x,
+                        @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
             naValCheck.enable(x);
             double[] result = new double[x.getLength()];
             boolean warnNaN = false;
@@ -73,7 +76,9 @@ public class BaseGammaFunctions {
             if (warnNaN) {
                 warning(RError.Message.NAN_PRODUCED);
             }
-            return RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA());
+            RDoubleVector resultVector = RDataFactory.createDoubleVector(result, naValCheck.neverSeenNA());
+            copyAttributesNode.execute(resultVector, x);
+            return resultVector;
         }
 
         protected double scalarFunction(@SuppressWarnings("unused") double xv) {
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 e3a1265309de34b27e0774a7c315d00ef201ba9d..50d0689a9aa446411dd26e17617ca41b4df9d3af 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
@@ -34,6 +34,8 @@ import com.oracle.truffle.r.nodes.binary.BinaryBooleanNodeGen;
 import com.oracle.truffle.r.nodes.binary.BinaryBooleanScalarNodeGen;
 import com.oracle.truffle.r.nodes.binary.BinaryBooleanSpecial;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinPackage;
+import com.oracle.truffle.r.nodes.builtin.base.DebugFunctions.FastRSetBreakpoint;
+import com.oracle.truffle.r.nodes.builtin.base.DebugFunctionsFactory.FastRSetBreakpointNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.fastpaths.AssignFastPathNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.fastpaths.ExistsFastPathNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.fastpaths.GetFastPathNodeGen;
@@ -41,6 +43,8 @@ import com.oracle.truffle.r.nodes.builtin.base.fastpaths.IntersectFastPathNodeGe
 import com.oracle.truffle.r.nodes.builtin.base.fastpaths.IsElementFastPathNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.fastpaths.MatrixFastPathNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.fastpaths.SetDiffFastPathNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.fastpaths.SubscriptDataFrameFastPathNodeGen;
+import com.oracle.truffle.r.nodes.builtin.base.fastpaths.SubsetDataFrameFastPathNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.fastpaths.VectorFastPathsFactory.DoubleFastPathNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.fastpaths.VectorFastPathsFactory.IntegerFastPathNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.foreign.CallAndExternalFunctions;
@@ -90,12 +94,16 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRContext;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRContextFactory;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRDebug;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRDebugNodeGen;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRHelp;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRHelpNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRIdentity;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRIdentityNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspect;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInspectNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRInteropFactory;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRLibPaths;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRLibPathsNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRPkgSource;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRPkgSourceNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastRRefCountInfo;
@@ -128,6 +136,16 @@ import com.oracle.truffle.r.nodes.builtin.fastr.FastRTryNodeGen;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastrDqrls;
 import com.oracle.truffle.r.nodes.builtin.fastr.FastrDqrlsNodeGen;
 import com.oracle.truffle.r.nodes.builtin.query.RTableBuiltinNodeGen;
+import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmem;
+import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemNodeGen;
+import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemShow;
+import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemShowNodeGen;
+import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemSnapshot;
+import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemSnapshotNodeGen;
+import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemSource;
+import com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmemSourceNodeGen;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticSpecial;
 import com.oracle.truffle.r.nodes.unary.UnaryNotNode;
 import com.oracle.truffle.r.nodes.unary.UnaryNotNodeGen;
 import com.oracle.truffle.r.runtime.RVisibility;
@@ -156,6 +174,38 @@ public class BasePackage extends RBuiltinPackage {
          */
         add(UnaryNotNode.class, UnaryNotNodeGen::create);
 
+        addUnaryArithmetic(Ceiling.class, Ceiling::new);
+        addUnaryArithmetic(Floor.class, Floor::new);
+        addUnaryArithmetic(Trunc.class, Trunc::new);
+        addUnaryArithmetic(LogFunctions.Log10.class, LogFunctions.Log10::new);
+        addUnaryArithmetic(LogFunctions.Log1p.class, LogFunctions.Log1p::new);
+        addUnaryArithmetic(LogFunctions.Log2.class, LogFunctions.Log2::new);
+        addUnaryArithmetic(NumericalFunctions.Abs.class, NumericalFunctions.Abs::new);
+        addUnaryArithmetic(NumericalFunctions.Arg.class, NumericalFunctions.Arg::new);
+        addUnaryArithmetic(NumericalFunctions.Conj.class, NumericalFunctions.Conj::new);
+        addUnaryArithmetic(NumericalFunctions.Im.class, NumericalFunctions.Im::new);
+        addUnaryArithmetic(NumericalFunctions.Mod.class, NumericalFunctions.Mod::new);
+        addUnaryArithmetic(NumericalFunctions.Re.class, NumericalFunctions.Re::new);
+        addUnaryArithmetic(NumericalFunctions.Sign.class, NumericalFunctions.Sign::new);
+        addUnaryArithmetic(NumericalFunctions.Sqrt.class, NumericalFunctions.Sqrt::new);
+        addUnaryArithmetic(TrigExpFunctions.Acos.class, TrigExpFunctions.Acos::new);
+        addUnaryArithmetic(TrigExpFunctions.Acosh.class, TrigExpFunctions.Acosh::new);
+        addUnaryArithmetic(TrigExpFunctions.Asin.class, TrigExpFunctions.Asin::new);
+        addUnaryArithmetic(TrigExpFunctions.Asinh.class, TrigExpFunctions.Asinh::new);
+        addUnaryArithmetic(TrigExpFunctions.Atan.class, TrigExpFunctions.Atan::new);
+        addUnaryArithmetic(TrigExpFunctions.Atanh.class, TrigExpFunctions.Atanh::new);
+        addUnaryArithmetic(TrigExpFunctions.Cos.class, TrigExpFunctions.Cos::new);
+        addUnaryArithmetic(TrigExpFunctions.Cosh.class, TrigExpFunctions.Cosh::new);
+        addUnaryArithmetic(TrigExpFunctions.Cospi.class, TrigExpFunctions.Cospi::new);
+        addUnaryArithmetic(TrigExpFunctions.Exp.class, TrigExpFunctions.Exp::new);
+        addUnaryArithmetic(TrigExpFunctions.ExpM1.class, TrigExpFunctions.ExpM1::new);
+        addUnaryArithmetic(TrigExpFunctions.Sin.class, TrigExpFunctions.Sin::new);
+        addUnaryArithmetic(TrigExpFunctions.Sinh.class, TrigExpFunctions.Sinh::new);
+        addUnaryArithmetic(TrigExpFunctions.Sinpi.class, TrigExpFunctions.Sinpi::new);
+        addUnaryArithmetic(TrigExpFunctions.Tan.class, TrigExpFunctions.Tan::new);
+        addUnaryArithmetic(TrigExpFunctions.Tanh.class, TrigExpFunctions.Tanh::new);
+        addUnaryArithmetic(TrigExpFunctions.Tanpi.class, TrigExpFunctions.Tanpi::new);
+
         addBinaryArithmetic(BinaryArithmetic.AddBuiltin.class, BinaryArithmetic.ADD, UnaryArithmetic.PLUS);
         addBinaryArithmetic(BinaryArithmetic.SubtractBuiltin.class, BinaryArithmetic.SUBTRACT, UnaryArithmetic.NEGATE);
         addBinaryArithmetic(BinaryArithmetic.DivBuiltin.class, BinaryArithmetic.DIV, null);
@@ -180,12 +230,10 @@ public class BasePackage extends RBuiltinPackage {
         // Now load the rest of the builtins in "base"
         add(Abbrev.class, AbbrevNodeGen::create);
         add(APerm.class, APermNodeGen::create);
-        add(NumericalFunctions.Abs.class, NumericalFunctionsFactory.AbsNodeGen::create);
         add(All.class, AllNodeGen::create);
         add(AllNames.class, AllNamesNodeGen::create);
         add(Any.class, AnyNodeGen::create);
         add(AnyNA.class, AnyNANodeGen::create);
-        add(Arg.class, ArgNodeGen::create);
         add(Args.class, ArgsNodeGen::create);
         add(Array.class, ArrayNodeGen::create);
         add(AsCall.class, AsCallNodeGen::create);
@@ -232,7 +280,6 @@ public class BasePackage extends RBuiltinPackage {
         add(CallAndExternalFunctions.DotExternalGraphics.class, CallAndExternalFunctionsFactory.DotExternalGraphicsNodeGen::create);
         add(Capabilities.class, CapabilitiesNodeGen::create);
         add(Cat.class, CatNodeGen::create);
-        add(Ceiling.class, CeilingNodeGen::create);
         add(CharMatch.class, CharMatchNodeGen::create);
         add(Col.class, ColNodeGen::create);
         add(Colon.class, ColonNodeGen::create, Colon::special);
@@ -243,7 +290,6 @@ public class BasePackage extends RBuiltinPackage {
         add(Complex.class, ComplexNodeGen::create);
         add(CompileFunctions.CompilePKGS.class, CompileFunctionsFactory.CompilePKGSNodeGen::create);
         add(CompileFunctions.EnableJIT.class, CompileFunctionsFactory.EnableJITNodeGen::create);
-        add(NumericalFunctions.Conj.class, NumericalFunctionsFactory.ConjNodeGen::create);
         add(ConditionFunctions.AddCondHands.class, ConditionFunctionsFactory.AddCondHandsNodeGen::create);
         add(ConditionFunctions.AddRestart.class, ConditionFunctionsFactory.AddRestartNodeGen::create);
         add(ConditionFunctions.DfltStop.class, ConditionFunctionsFactory.DfltStopNodeGen::create);
@@ -293,7 +339,8 @@ public class BasePackage extends RBuiltinPackage {
         add(ConnectionFunctions.IsIncomplete.class, ConnectionFunctionsFactory.IsIncompleteNodeGen::create);
         add(Contributors.class, ContributorsNodeGen::create);
         add(CopyDFAttr.class, CopyDFAttrNodeGen::create);
-        add(Crossprod.class, CrossprodNodeGen::create);
+        add(CrossprodCommon.TCrossprod.class, CrossprodCommon.class, CrossprodCommon::createTCrossprod);
+        add(CrossprodCommon.Crossprod.class, CrossprodCommon.class, CrossprodCommon::createCrossprod);
         add(CRC64.class, CRC64NodeGen::create);
         add(CumMax.class, CumMaxNodeGen::create);
         add(CumMin.class, CumMinNodeGen::create);
@@ -369,23 +416,25 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRContext.Join.class, FastRContextFactory.JoinNodeGen::create);
         add(FastrDqrls.class, FastrDqrlsNodeGen::create);
         add(FastRDebug.class, FastRDebugNodeGen::create);
+        add(FastRSetBreakpoint.class, FastRSetBreakpointNodeGen::create);
+        add(FastRHelp.class, FastRHelpNodeGen::create);
         add(FastRIdentity.class, FastRIdentityNodeGen::create);
         add(FastRTry.class, FastRTryNodeGen::create);
         add(FastRInspect.class, FastRInspectNodeGen::create);
         add(FastRInterop.Eval.class, FastRInteropFactory.EvalNodeGen::create);
-        add(FastRInterop.EvalFile.class, FastRInteropFactory.EvalFileNodeGen::create);
         add(FastRInterop.Export.class, FastRInteropFactory.ExportNodeGen::create);
-        add(FastRInterop.HasSize.class, FastRInteropFactory.HasSizeNodeGen::create);
         add(FastRInterop.Import.class, FastRInteropFactory.ImportNodeGen::create);
         add(FastRInterop.InteropNew.class, FastRInteropFactory.InteropNewNodeGen::create);
         add(FastRInterop.IsNull.class, FastRInteropFactory.IsNullNodeGen::create);
         add(FastRInterop.IsExecutable.class, FastRInteropFactory.IsExecutableNodeGen::create);
         add(FastRInterop.IsExternal.class, FastRInteropFactory.IsExternalNodeGen::create);
         add(FastRInterop.JavaClass.class, FastRInteropFactory.JavaClassNodeGen::create);
-        add(FastRInterop.IsJavaArray.class, FastRInteropFactory.IsJavaArrayNodeGen::create);
+        add(FastRInterop.JavaClassName.class, FastRInteropFactory.JavaClassNameNodeGen::create);
+        add(FastRInterop.JavaAddToClasspath.class, FastRInteropFactory.JavaAddToClasspathNodeGen::create);
+        add(FastRInterop.IsForeignArray.class, FastRInteropFactory.IsForeignArrayNodeGen::create);
         add(FastRInterop.NewJavaArray.class, FastRInteropFactory.NewJavaArrayNodeGen::create);
         add(FastRInterop.ToJavaArray.class, FastRInteropFactory.ToJavaArrayNodeGen::create);
-        add(FastRInterop.FromJavaArray.class, FastRInteropFactory.FromJavaArrayNodeGen::create);
+        add(FastRInterop.FromForeignArray.class, FastRInteropFactory.FromForeignArrayNodeGen::create);
         add(FastRInterop.ToBoolean.class, FastRInteropFactory.ToBooleanNodeGen::create);
         add(FastRInterop.ToByte.class, FastRInteropFactory.ToByteNodeGen::create);
         add(FastRInterop.ToChar.class, FastRInteropFactory.ToCharNodeGen::create);
@@ -406,6 +455,11 @@ public class BasePackage extends RBuiltinPackage {
         add(FastRTrace.Untrace.class, FastRTraceFactory.UntraceNodeGen::create);
         add(FastRTree.class, FastRTreeNodeGen::create);
         add(FastRTreeStats.class, FastRTreeStatsNodeGen::create);
+        add(FastRprofmem.class, FastRprofmemNodeGen::create);
+        add(FastRprofmemShow.class, FastRprofmemShowNodeGen::create);
+        add(FastRprofmemSource.class, FastRprofmemSourceNodeGen::create);
+        add(FastRprofmemSnapshot.class, FastRprofmemSnapshotNodeGen::create);
+        add(FastRLibPaths.class, FastRLibPathsNodeGen::create);
         add(FileFunctions.BaseName.class, FileFunctionsFactory.BaseNameNodeGen::create);
         add(FileFunctions.DirCreate.class, FileFunctionsFactory.DirCreateNodeGen::create);
         add(FileFunctions.DirExists.class, FileFunctionsFactory.DirExistsNodeGen::create);
@@ -425,7 +479,6 @@ public class BasePackage extends RBuiltinPackage {
         add(FileFunctions.ListFiles.class, FileFunctionsFactory.ListFilesNodeGen::create);
         add(FileFunctions.ListDirs.class, FileFunctionsFactory.ListDirsNodeGen::create);
         add(FileFunctions.Unlink.class, FileFunctionsFactory.UnlinkNodeGen::create);
-        add(Floor.class, FloorNodeGen::create);
         add(ForceAndCall.class, ForceAndCallNodeGen::create);
         add(Formals.class, FormalsNodeGen::create);
         add(Format.class, FormatNodeGen::create);
@@ -447,7 +500,6 @@ public class BasePackage extends RBuiltinPackage {
         add(GetFunctions.Get.class, GetFunctionsFactory.GetNodeGen::create);
         add(GetFunctions.Get0.class, GetFunctionsFactory.Get0NodeGen::create);
         add(GetFunctions.MGet.class, GetFunctionsFactory.MGetNodeGen::create);
-        add(GetOldClass.class, GetOldClassNodeGen::create);
         add(OptionsFunctions.GetOption.class, OptionsFunctionsFactory.GetOptionNodeGen::create);
         add(GetText.class, GetTextNodeGen::create);
         add(Getwd.class, GetwdNodeGen::create);
@@ -470,7 +522,6 @@ public class BasePackage extends RBuiltinPackage {
         add(HiddenInternalFunctions.LazyLoadDBinsertValue.class, HiddenInternalFunctionsFactory.LazyLoadDBinsertValueNodeGen::create);
         add(IConv.class, IConvNodeGen::create);
         add(Identical.class, Identical::create);
-        add(NumericalFunctions.Im.class, NumericalFunctionsFactory.ImNodeGen::create);
         add(InheritsBuiltin.class, InheritsBuiltinNodeGen::create);
         add(Interactive.class, InteractiveNodeGen::create);
         add(Internal.class, InternalNodeGen::create);
@@ -533,9 +584,6 @@ public class BasePackage extends RBuiltinPackage {
         add(LocaleFunctions.LocaleConv.class, LocaleFunctionsFactory.LocaleConvNodeGen::create);
         add(LocaleFunctions.SetLocale.class, LocaleFunctionsFactory.SetLocaleNodeGen::create);
         add(LogFunctions.Log.class, LogFunctionsFactory.LogNodeGen::create);
-        add(LogFunctions.Log10.class, LogFunctionsFactory.Log10NodeGen::create);
-        add(LogFunctions.Log1p.class, LogFunctionsFactory.Log1pNodeGen::create);
-        add(LogFunctions.Log2.class, LogFunctionsFactory.Log2NodeGen::create);
         add(Ls.class, LsNodeGen::create);
         add(MakeNames.class, MakeNamesNodeGen::create);
         add(MakeUnique.class, MakeUniqueNodeGen::create);
@@ -550,7 +598,6 @@ public class BasePackage extends RBuiltinPackage {
         add(Merge.class, MergeNodeGen::create);
         add(Min.class, MinNodeGen::create);
         add(Missing.class, MissingNodeGen::create);
-        add(NumericalFunctions.Mod.class, NumericalFunctionsFactory.ModNodeGen::create);
         add(NArgs.class, NArgsNodeGen::create);
         add(NChar.class, NCharNodeGen::create);
         add(NGetText.class, NGetTextNodeGen::create);
@@ -563,6 +610,7 @@ public class BasePackage extends RBuiltinPackage {
         add(NamespaceFunctions.RegisterNamespace.class, NamespaceFunctionsFactory.RegisterNamespaceNodeGen::create);
         add(NamespaceFunctions.UnregisterNamespace.class, NamespaceFunctionsFactory.UnregisterNamespaceNodeGen::create);
         add(NormalizePath.class, NormalizePathNodeGen::create);
+        add(OldClass.class, OldClassNodeGen::create);
         add(OnExit.class, OnExitNodeGen::create);
         add(OptionsFunctions.Options.class, OptionsFunctionsFactory.OptionsNodeGen::create);
         add(Order.class, OrderNodeGen::create);
@@ -590,7 +638,6 @@ public class BasePackage extends RBuiltinPackage {
         add(RawFunctions.RawToChar.class, RawFunctionsFactory.RawToCharNodeGen::create);
         add(RawFunctions.RawShift.class, RawFunctionsFactory.RawShiftNodeGen::create);
         add(RawToBits.class, RawToBitsNodeGen::create);
-        add(NumericalFunctions.Re.class, NumericalFunctionsFactory.ReNodeGen::create);
         add(ReadDCF.class, ReadDCFNodeGen::create);
         add(ReadREnviron.class, ReadREnvironNodeGen::create);
         add(Readline.class, ReadlineNodeGen::create);
@@ -622,7 +669,6 @@ public class BasePackage extends RBuiltinPackage {
         add(SerializeFunctions.UnserializeFromConn.class, SerializeFunctionsFactory.UnserializeFromConnNodeGen::create);
         add(Setwd.class, SetwdNodeGen::create);
         add(ShortRowNames.class, ShortRowNamesNodeGen::create);
-        add(NumericalFunctions.Sign.class, NumericalFunctionsFactory.SignNodeGen::create);
         add(Signif.class, SignifNodeGen::create);
         add(SinkFunctions.Sink.class, SinkFunctionsFactory.SinkNodeGen::create);
         add(SinkFunctions.SinkNumber.class, SinkFunctionsFactory.SinkNumberNodeGen::create);
@@ -633,7 +679,6 @@ public class BasePackage extends RBuiltinPackage {
         add(SortFunctions.Sort.class, SortFunctionsFactory.SortNodeGen::create);
         add(Split.class, SplitNodeGen::create);
         add(Sprintf.class, SprintfNodeGen::create);
-        add(NumericalFunctions.Sqrt.class, NumericalFunctionsFactory.SqrtNodeGen::create);
         add(StandardGeneric.class, StandardGenericNodeGen::create);
         add(StartsEndsWithFunctions.StartsWith.class, StartsEndsWithFunctionsFactory.StartsWithNodeGen::create);
         add(StartsEndsWithFunctions.EndsWith.class, StartsEndsWithFunctionsFactory.EndsWithNodeGen::create);
@@ -671,25 +716,7 @@ public class BasePackage extends RBuiltinPackage {
         add(TraceFunctions.Retracemem.class, TraceFunctionsFactory.RetracememNodeGen::create);
         add(TraceFunctions.Untracemem.class, TraceFunctionsFactory.UntracememNodeGen::create);
         add(Transpose.class, TransposeNodeGen::create);
-        add(TrigExpFunctions.Acos.class, TrigExpFunctionsFactory.AcosNodeGen::create);
-        add(TrigExpFunctions.Acosh.class, TrigExpFunctionsFactory.AcoshNodeGen::create);
-        add(TrigExpFunctions.Asin.class, TrigExpFunctionsFactory.AsinNodeGen::create);
-        add(TrigExpFunctions.Asinh.class, TrigExpFunctionsFactory.AsinhNodeGen::create);
-        add(TrigExpFunctions.Atan.class, TrigExpFunctionsFactory.AtanNodeGen::create);
         add(TrigExpFunctions.Atan2.class, TrigExpFunctionsFactory.Atan2NodeGen::create);
-        add(TrigExpFunctions.Atanh.class, TrigExpFunctionsFactory.AtanhNodeGen::create);
-        add(TrigExpFunctions.Cos.class, TrigExpFunctionsFactory.CosNodeGen::create);
-        add(TrigExpFunctions.Cosh.class, TrigExpFunctionsFactory.CoshNodeGen::create);
-        add(TrigExpFunctions.Cospi.class, TrigExpFunctionsFactory.CospiNodeGen::create);
-        add(TrigExpFunctions.Exp.class, TrigExpFunctionsFactory.ExpNodeGen::create);
-        add(TrigExpFunctions.ExpM1.class, TrigExpFunctionsFactory.ExpM1NodeGen::create);
-        add(TrigExpFunctions.Sin.class, TrigExpFunctionsFactory.SinNodeGen::create);
-        add(TrigExpFunctions.Sinh.class, TrigExpFunctionsFactory.SinhNodeGen::create);
-        add(TrigExpFunctions.Sinpi.class, TrigExpFunctionsFactory.SinpiNodeGen::create);
-        add(TrigExpFunctions.Tan.class, TrigExpFunctionsFactory.TanNodeGen::create);
-        add(TrigExpFunctions.Tanh.class, TrigExpFunctionsFactory.TanhNodeGen::create);
-        add(TrigExpFunctions.Tanpi.class, TrigExpFunctionsFactory.TanpiNodeGen::create);
-        add(Trunc.class, TruncNodeGen::create);
         add(Typeof.class, TypeofNodeGen::create);
         add(UnClass.class, UnClassNodeGen::create);
         add(Unique.class, UniqueNodeGen::create);
@@ -753,7 +780,11 @@ public class BasePackage extends RBuiltinPackage {
     }
 
     private void addBinaryArithmetic(Class<?> builtinClass, BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) {
-        add(builtinClass, () -> BinaryArithmeticNodeGen.create(binaryFactory, unaryFactory), BinaryArithmeticSpecial.createSpecialFactory(binaryFactory));
+        add(builtinClass, () -> BinaryArithmeticNodeGen.create(binaryFactory, unaryFactory), BinaryArithmeticSpecial.createSpecialFactory(binaryFactory, unaryFactory));
+    }
+
+    private void addUnaryArithmetic(Class<?> builtinClass, UnaryArithmeticFactory unaryFactory) {
+        add(builtinClass, () -> new UnaryArithmeticBuiltinNode(unaryFactory), UnaryArithmeticSpecial.createSpecialFactory(unaryFactory));
     }
 
     private void addBinaryCompare(Class<?> builtinClass, BooleanOperationFactory factory) {
@@ -777,6 +808,8 @@ public class BasePackage extends RBuiltinPackage {
     @Override
     public void loadOverrides(MaterializedFrame baseFrame) {
         super.loadOverrides(baseFrame);
+        addFastPath(baseFrame, "[[.data.frame", SubscriptDataFrameFastPathNodeGen::create, RVisibility.ON);
+        addFastPath(baseFrame, "[.data.frame", SubsetDataFrameFastPathNodeGen::create, RVisibility.ON);
         addFastPath(baseFrame, "matrix", MatrixFastPathNodeGen::create, Matrix.class);
         addFastPath(baseFrame, "setdiff", SetDiffFastPathNodeGen::create, RVisibility.ON);
         addFastPath(baseFrame, "get", GetFastPathNodeGen::create, RVisibility.ON);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
index 1247be422fe02181dc6da7960e969f6674ed44f2..794229c9aae8f269919166366dfcb42e346ef626 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java
@@ -631,7 +631,6 @@ public abstract class Bind extends RBaseNode {
             }
             return result != null ? result.function : null;
         }
-
     }
 
     public RVector<?> genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, RVector<?> result, int[] resultDimensions, int[] firstDims, boolean rowsAndColumnsNotEqual,
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
index dc67759ab247512bf3874f8bb7d12c843877287b..6f8b4034f27b6222cb8a6a4359c65c82bcf71d22 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BitwiseFunctions.java
@@ -91,14 +91,14 @@ public class BitwiseFunctions {
                             v = aVal ^ bVal;
                             break;
                         case SHIFTR:
-                            if (bVal > 31) {
+                            if (bVal > 31 || bVal < 0) {
                                 v = RRuntime.INT_NA;
                             } else {
                                 v = aVal >>> bVal;
                             }
                             break;
                         case SHIFTL:
-                            if (bVal > 31) {
+                            if (bVal > 31 || bVal < 0) {
                                 v = RRuntime.INT_NA;
                             } else {
                                 v = aVal << bVal;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
index 8f0f513b5c7f3caaed7217d6668f7b97b57f04ac..2b58ec4749cd083200e13849baf26ea8b2a1bb9b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BrowserFunctions.java
@@ -30,6 +30,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.MaterializedFrame;
@@ -38,13 +39,16 @@ import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNode;
 import com.oracle.truffle.r.nodes.builtin.helpers.BrowserInteractNodeGen;
+import com.oracle.truffle.r.nodes.function.GetCallerFrameNode;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
 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.SubstituteVirtualFrame;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState.HelperState;
@@ -55,6 +59,7 @@ public class BrowserFunctions {
     public abstract static class BrowserNode extends RBuiltinNode.Arg4 {
 
         @Child private BrowserInteractNode browserInteractNode = BrowserInteractNodeGen.create();
+        @Child private GetCallerFrameNode getCallerFrame;
 
         @Override
         public Object[] getDefaultParameterValues() {
@@ -78,8 +83,18 @@ public class BrowserFunctions {
                     browserState.push(new HelperState(text, condition));
                     MaterializedFrame mFrame = frame.materialize();
                     RCaller caller = RArguments.getCall(mFrame);
+                    RFunction fun = RArguments.getFunction(mFrame);
+                    VirtualFrame actualFrame = frame;
+                    if (fun != null && fun.isBuiltin() && fun.getRBuiltin().getBuiltinNodeClass() == BrowserNode.class) {
+                        if (getCallerFrame == null) {
+                            CompilerDirectives.transferToInterpreterAndInvalidate();
+                            getCallerFrame = insert(new GetCallerFrameNode());
+                        }
+                        actualFrame = SubstituteVirtualFrame.create(getCallerFrame.execute(mFrame));
+                        caller = caller.getParent();
+                    }
                     doPrint(caller);
-                    browserInteractNode.execute(frame);
+                    browserInteractNode.execute(actualFrame, caller);
                 } finally {
                     browserState.pop();
                 }
@@ -95,7 +110,7 @@ public class BrowserFunctions {
             } else {
                 callerString = RContext.getRRuntimeASTAccess().getCallerSource(caller);
             }
-            RContext.getInstance().getConsoleHandler().printf("Called from: %s%n", callerString);
+            RContext.getInstance().getConsole().printf("Called from: %s%n", callerString);
 
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
index 20b0d7b466b80e2279f2d0fbc23cb9e5b3cf1ff4..c6f72e666cc5aa71de98f9c01a976e4a79c810e1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Call.java
@@ -48,6 +48,7 @@ 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.RSymbol;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
@@ -69,76 +70,81 @@ public abstract class Call extends RBuiltinNode.Arg2 {
         casts.arg("").mustBe(stringValue(), RError.Message.FIRST_ARG_MUST_BE_STRING).asStringVector().findFirst();
     }
 
+    @Child private CallUtil util = new CallUtil();
+
     @Specialization
     protected RLanguage call(String name, RArgsValuesAndNames args) {
-        return makeCall(name, args);
+        return util.makeCall(name, args);
     }
 
-    @TruffleBoundary
-    private static RLanguage makeCall(String name, RArgsValuesAndNames args) {
-        return "function".equals(name) ? makeFunction(args) : makeCall0(ReadVariableNode.createFunctionLookup(RSyntaxNode.LAZY_DEPARSE, name), false, args);
-    }
+    public static final class CallUtil extends RBaseNode {
 
-    private static RLanguage makeFunction(RArgsValuesAndNames args) {
-        CompilerAsserts.neverPartOfCompilation();
-        Object body = RNull.instance;
-        if (args.getLength() >= 2) {
-            body = args.getArgument(1);
+        @TruffleBoundary
+        private RLanguage makeCall(String name, RArgsValuesAndNames args) {
+            return "function".equals(name) ? makeFunction(args) : makeCall0(ReadVariableNode.wrap(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.createFunctionLookup(name)), false, args);
         }
-        Object argList = args.getLength() == 0 ? RNull.instance : args.getArgument(0);
-        ArrayList<RCodeBuilder.Argument<RSyntaxNode>> finalArgs = new ArrayList<>();
-        while (argList != RNull.instance) {
-            if (!(argList instanceof RPairList)) {
-                throw RError.error(RError.SHOW_CALLER, Message.BAD_FUNCTION_EXPR);
+
+        private RLanguage makeFunction(RArgsValuesAndNames args) {
+            CompilerAsserts.neverPartOfCompilation();
+            Object body = RNull.instance;
+            if (args.getLength() >= 2) {
+                body = args.getArgument(1);
+            }
+            Object argList = args.getLength() == 0 ? RNull.instance : args.getArgument(0);
+            ArrayList<RCodeBuilder.Argument<RSyntaxNode>> finalArgs = new ArrayList<>();
+            while (argList != RNull.instance) {
+                if (!(argList instanceof RPairList)) {
+                    throw RError.error(RError.SHOW_CALLER, Message.BAD_FUNCTION_EXPR);
+                }
+                RPairList pl = (RPairList) argList;
+                String name = ((RSymbol) pl.getTag()).getName();
+                RSyntaxNode value = RASTUtils.createNodeForValue(pl.car()).asRSyntaxNode();
+                finalArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, name, value));
+                argList = pl.cdr();
             }
-            RPairList pl = (RPairList) argList;
-            String name = ((RSymbol) pl.getTag()).getName();
-            RSyntaxNode value = RASTUtils.createNodeForValue(pl.car()).asRSyntaxNode();
-            finalArgs.add(RCodeBuilder.argument(RSyntaxNode.LAZY_DEPARSE, name, value));
-            argList = pl.cdr();
+            RSyntaxNode function = RContext.getASTBuilder().function(getRLanguage(), RSyntaxNode.LAZY_DEPARSE, finalArgs, RASTUtils.createNodeForValue(body).asRSyntaxNode(), null);
+            return RDataFactory.createLanguage(function.asRNode());
         }
-        RSyntaxNode function = RContext.getASTBuilder().function(RSyntaxNode.LAZY_DEPARSE, finalArgs, RASTUtils.createNodeForValue(body).asRSyntaxNode(), null);
-        return RDataFactory.createLanguage(function.asRNode());
-    }
-
-    @TruffleBoundary
-    protected static RLanguage makeCallSourceUnavailable(String name, RArgsValuesAndNames args) {
-        return "function".equals(name) ? makeFunction(args) : makeCall0(ReadVariableNode.createFunctionLookup(RSyntaxNode.LAZY_DEPARSE, name), true, args);
-    }
 
-    @TruffleBoundary
-    protected static RLanguage makeCallSourceUnavailable(int i, RArgsValuesAndNames args) {
-        return makeCall0(ConstantNode.create(i), true, args);
-    }
+        @TruffleBoundary
+        protected RLanguage makeCallSourceUnavailable(String name, RArgsValuesAndNames args) {
+            return "function".equals(name) ? makeFunction(args) : makeCall0(ReadVariableNode.wrap(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.createFunctionLookup(name)), true, args);
+        }
 
-    @TruffleBoundary
-    protected static RLanguage makeCallSourceUnavailable(double d, RArgsValuesAndNames args) {
-        return makeCall0(ConstantNode.create(d), true, args);
-    }
+        @TruffleBoundary
+        protected static RLanguage makeCallSourceUnavailable(int i, RArgsValuesAndNames args) {
+            return makeCall0(ConstantNode.create(i), true, args);
+        }
 
-    @TruffleBoundary
-    protected static RLanguage makeCallSourceUnavailable(RFunction function, RArgsValuesAndNames args) {
-        return makeCall0(function, true, args);
-    }
+        @TruffleBoundary
+        protected static RLanguage makeCallSourceUnavailable(double d, RArgsValuesAndNames args) {
+            return makeCall0(ConstantNode.create(d), true, args);
+        }
 
-    /**
-     *
-     * @param fn an {@link RFunction} or {@link String}
-     * @param argsAndNames if not {@code null} the argument values and (optional) names
-     * @return the {@link RLanguage} instance denoting the call
-     */
-    @TruffleBoundary
-    private static RLanguage makeCall0(Object fn, boolean sourceUnavailable, RArgsValuesAndNames argsAndNames) {
-        assert !(fn instanceof String);
-        int argLength = argsAndNames == null ? 0 : argsAndNames.getLength();
-        RSyntaxNode[] args = new RSyntaxNode[argLength];
-        Object[] values = argsAndNames == null ? null : argsAndNames.getArguments();
-        ArgumentsSignature signature = argsAndNames == null ? ArgumentsSignature.empty(0) : argsAndNames.getSignature();
-
-        for (int i = 0; i < argLength; i++) {
-            args[i] = (RSyntaxNode) RASTUtils.createNodeForValue(values[i]);
+        @TruffleBoundary
+        protected static RLanguage makeCallSourceUnavailable(RFunction function, RArgsValuesAndNames args) {
+            return makeCall0(function, true, args);
         }
 
-        return RDataFactory.createLanguage(RASTUtils.createCall(fn, sourceUnavailable, signature, args).asRNode());
+        /**
+         *
+         * @param fn an {@link RFunction} or {@link String}
+         * @param argsAndNames if not {@code null} the argument values and (optional) names
+         * @return the {@link RLanguage} instance denoting the call
+         */
+        @TruffleBoundary
+        private static RLanguage makeCall0(Object fn, boolean sourceUnavailable, RArgsValuesAndNames argsAndNames) {
+            assert !(fn instanceof String);
+            int argLength = argsAndNames == null ? 0 : argsAndNames.getLength();
+            RSyntaxNode[] args = new RSyntaxNode[argLength];
+            Object[] values = argsAndNames == null ? null : argsAndNames.getArguments();
+            ArgumentsSignature signature = argsAndNames == null ? ArgumentsSignature.empty(0) : argsAndNames.getSignature();
+
+            for (int i = 0; i < argLength; i++) {
+                args[i] = (RSyntaxNode) RASTUtils.createNodeForValue(values[i]);
+            }
+
+            return RDataFactory.createLanguage(RASTUtils.createCall(fn, sourceUnavailable, signature, args).asRNode());
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
index 8a80bf7e438c3cc9ee71ec83529aebd16dbee763..015ffea85340b0fbdc899feed463a5a35a43a9dd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Capabilities.java
@@ -83,7 +83,7 @@ public abstract class Capabilities extends RBuiltinNode.Arg0 {
             boolean value = c.defValue;
             switch (c) {
                 case cledit:
-                    value = RContext.getInstance().isInteractive() && !RContext.getInstance().getStartParams().getNoReadline();
+                    value = RContext.getInstance().isInteractive() && !RContext.getInstance().getStartParams().noReadline();
                     break;
             }
             data[c.ordinal()] = RRuntime.asLogical(value);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
index 97a39652446ab3a30f9a514bf3c94bbe1ee7fb0e..4590c44a69bafa50113821feb55ec36a55510f2f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Ceiling.java
@@ -22,64 +22,21 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
-@RBuiltin(name = "ceiling", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class Ceiling extends UnaryArithmeticBuiltinNode {
+@RBuiltin(name = "ceiling", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+public final class Ceiling extends UnaryArithmetic {
 
-    public static final UnaryArithmeticFactory CEILING = FloorNodeGen.create();
-
-    public Ceiling() {
-        super(RType.Double, RError.Message.NON_NUMERIC_MATH, null);
-    }
-
-    static {
-        Casts casts = new Casts(Ceiling.class);
-        casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustNotBeNull().mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(true,
-                        true, true);
-    }
-
-    @Override
-    public int op(byte op) {
-        return op;
-    }
-
-    @Override
-    public int op(int op) {
-        return op;
-    }
+    public static final UnaryArithmeticFactory CEILING = Ceiling::new;
 
     @Override
     public double op(double op) {
         return Math.ceil(op);
     }
-
-    @Override
-    protected double opd(double re, double im) {
-        return op(re);
-    }
-
-    @Override
-    public RComplex op(double re, double im) {
-        return RDataFactory.createComplex(op(re), op(im));
-    }
-
-    @Specialization
-    @Override
-    public Object calculateUnboxed(Object op) {
-        return super.calculateUnboxed(op);
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
index 90e3aa33b9021ae0ec2cd1bc318904288d560934..3e6b6ea49cde5bb42d72cbf8b726136758172c66 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Colon.java
@@ -25,12 +25,10 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -51,6 +49,7 @@ import com.oracle.truffle.r.runtime.data.RSequence;
 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.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
@@ -93,7 +92,7 @@ public abstract class Colon extends RBuiltinNode.Arg2 {
     }
 
     @NodeInfo(cost = NodeCost.NONE)
-    abstract static class ColonInternal extends Node {
+    abstract static class ColonInternal extends RBaseNode {
 
         private final NACheck leftNA = NACheck.create();
         private final NACheck rightNA = NACheck.create();
@@ -102,8 +101,7 @@ public abstract class Colon extends RBuiltinNode.Arg2 {
 
         private void naCheck(boolean na) {
             if (na) {
-                CompilerDirectives.transferToInterpreter();
-                throw RError.error(this, RError.Message.NA_OR_NAN);
+                error(RError.Message.NA_OR_NAN);
             }
         }
 
@@ -116,6 +114,7 @@ public abstract class Colon extends RBuiltinNode.Arg2 {
             leftNA.enable(left);
             rightNA.enable(right);
             naCheck(leftNA.check(left) || rightNA.check(right));
+            checkVecLength(left, right);
             return RDataFactory.createAscendingRange(left, right);
         }
 
@@ -124,14 +123,38 @@ public abstract class Colon extends RBuiltinNode.Arg2 {
             leftNA.enable(left);
             rightNA.enable(right);
             naCheck(leftNA.check(left) || rightNA.check(right));
+            checkVecLength(left, right);
             return RDataFactory.createDescendingRange(left, right);
         }
 
-        @Specialization(guards = "asDouble(left) <= right")
+        protected static boolean isNaN(double x) {
+            return Double.isNaN(x);
+        }
+
+        @SuppressWarnings("unused")
+        @Specialization(guards = "isNaN(right)")
+        protected RSequence colonRightNaN(int left, double right) {
+            throw error(Message.NA_OR_NAN);
+        }
+
+        @SuppressWarnings("unused")
+        @Specialization(guards = "isNaN(left)")
+        protected RSequence colonLeftNaN(double left, int right) {
+            throw error(Message.NA_OR_NAN);
+        }
+
+        @SuppressWarnings("unused")
+        @Specialization(guards = "isNaN(left) || isNaN(right)")
+        protected RSequence colonLeftOrRightNaN(double left, double right) {
+            throw error(Message.NA_OR_NAN);
+        }
+
+        @Specialization(guards = {"!isNaN(left)", "asDouble(left) <= right"})
         protected RSequence colonAscending(int left, double right,
                         @Cached("createBinaryProfile()") ConditionProfile isDouble) {
             leftNA.enable(left);
             naCheck(leftNA.check(left) || RRuntime.isNAorNaN(right));
+            checkVecLength(left, right);
             if (isDouble.profile(right > Integer.MAX_VALUE)) {
                 return RDataFactory.createAscendingRange(left, right);
             } else {
@@ -139,11 +162,12 @@ public abstract class Colon extends RBuiltinNode.Arg2 {
             }
         }
 
-        @Specialization(guards = "asDouble(left) > right")
+        @Specialization(guards = {"!isNaN(left)", "asDouble(left) > right"})
         protected RSequence colonDescending(int left, double right,
                         @Cached("createBinaryProfile()") ConditionProfile isDouble) {
             leftNA.enable(left);
             naCheck(leftNA.check(left) || RRuntime.isNAorNaN(right));
+            checkVecLength(left, right);
             if (isDouble.profile(right <= Integer.MIN_VALUE)) {
                 return RDataFactory.createDescendingRange(left, right);
             } else {
@@ -151,31 +175,42 @@ public abstract class Colon extends RBuiltinNode.Arg2 {
             }
         }
 
-        @Specialization(guards = "left <= asDouble(right)")
+        @Specialization(guards = {"!isNaN(left)", "left <= asDouble(right)"})
         protected RDoubleSequence colonAscending(double left, int right) {
             rightNA.enable(right);
             naCheck(RRuntime.isNAorNaN(left) || rightNA.check(right));
+            checkVecLength(left, right);
             return RDataFactory.createAscendingRange(left, right);
         }
 
-        @Specialization(guards = "left > asDouble(right)")
+        @Specialization(guards = {"!isNaN(left)", "left > asDouble(right)"})
         protected RDoubleSequence colonDescending(double left, int right) {
             rightNA.enable(right);
             naCheck(RRuntime.isNAorNaN(left) || rightNA.check(right));
+            checkVecLength(left, right);
             return RDataFactory.createDescendingRange(left, right);
         }
 
-        @Specialization(guards = "left <= right")
+        @Specialization(guards = {"!isNaN(left)", "!isNaN(right)", "left <= right"})
         protected RDoubleSequence colonAscending(double left, double right) {
             naCheck(RRuntime.isNAorNaN(left) || RRuntime.isNAorNaN(right));
+            checkVecLength(left, right);
             return RDataFactory.createAscendingRange(left, right);
         }
 
-        @Specialization(guards = "left > right")
+        @Specialization(guards = {"!isNaN(left)", "!isNaN(right)", "left > right"})
         protected RDoubleSequence colonDescending(double left, double right) {
             naCheck(RRuntime.isNAorNaN(left) || RRuntime.isNAorNaN(right));
+            checkVecLength(left, right);
             return RDataFactory.createDescendingRange(left, right);
         }
+
+        private void checkVecLength(double from, double to) {
+            double r = Math.abs(to - from);
+            if (r >= Integer.MAX_VALUE) {
+                throw error(RError.Message.TOO_LONG_VECTOR);
+            }
+        }
     }
 
     @NodeInfo(cost = NodeCost.NONE)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index 4900debc6e7727015a5a17970fcee10d1d3caab1..58653d31ac1260cf5795ed598a7cc9d339a60374 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -41,6 +41,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
@@ -78,6 +79,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
+@ImportStatic(RRuntime.class)
 @RBuiltin(name = "c", kind = PRIMITIVE, parameterNames = {"...", "recursive"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
 public abstract class Combine extends RBuiltinNode.Arg2 {
 
@@ -110,7 +112,7 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
     public abstract Object executeCombine(Object value, Object recursive);
 
     protected boolean isSimpleArguments(RArgsValuesAndNames args) {
-        return !signatureHasNames(args.getSignature()) && args.getLength() == 1 && !(args.getArgument(0) instanceof RAbstractVector);
+        return !signatureHasNames(args.getSignature()) && args.getLength() == 1 && !(args.getArgument(0) instanceof RAbstractVector) && !RRuntime.isForeignObject(args.getArgument(0));
     }
 
     @Specialization(guards = {"isSimpleArguments(args)", "!recursive"})
@@ -212,10 +214,11 @@ public abstract class Combine extends RBuiltinNode.Arg2 {
     @ExplodeLoop
     private int prepareElements(Object[] args, CastNode cast, int precedence, Object[] elements) {
         int size = 0;
+        boolean exprListPrecedence = precedence == EXPRESSION_PRECEDENCE || precedence == LIST_PRECEDENCE;
         for (int i = 0; i < elements.length; i++) {
             CombineInputCast inputCast = getCast(i);
             Object value = args[i];
-            Object element = (precedence == EXPRESSION_PRECEDENCE && value instanceof RLanguage) ? value : cast.doCast(inputCast.cast(value));
+            Object element = (exprListPrecedence && value instanceof RLanguage) ? value : cast.doCast(inputCast.cast(value));
             element = inputCast.valueProfile.profile(element);
             elements[i] = element;
             size += getElementSize(element);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
index 9c6f24083b497de96d5c22cfa60eee2b21e33741..947fcb54b00fe9c8018076959f57931e53022df3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CommandArgs.java
@@ -39,7 +39,7 @@ public abstract class CommandArgs extends RBuiltinNode.Arg0 {
     @Specialization
     @TruffleBoundary
     protected RStringVector commandArgs() {
-        String[] s = RContext.getInstance().getStartParams().getArguments();
+        String[] s = RContext.getInstance().getEnv().getApplicationArguments();
         return RDataFactory.createStringVector(s, RDataFactory.COMPLETE_VECTOR);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
index 12fffb616a49f19672854e6aa2d57c0c22326559..2f8f4b2f6e33e465ceb65a8110915fdc0ef1392f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConditionFunctions.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
 /**
  * Condition handling. Derived from GnUR src/main/errors.c
@@ -71,8 +72,8 @@ public class ConditionFunctions {
                 throw error(RError.Message.BAD_HANDLER_DATA);
             }
             try {
-                if (!frame.isObject(handlerFrameSlot) || frame.getObject(handlerFrameSlot) == null) {
-                    frame.setObject(handlerFrameSlot, RErrorHandling.getHandlerStack());
+                if (!frame.isObject(handlerFrameSlot) || FrameSlotChangeMonitor.getObject(handlerFrameSlot, frame) == null) {
+                    FrameSlotChangeMonitor.setObject(frame, handlerFrameSlot, RErrorHandling.getHandlerStack());
                 }
             } catch (FrameSlotTypeException e) {
                 throw RInternalError.shouldNotReachHere();
@@ -121,7 +122,7 @@ public class ConditionFunctions {
             }
             try {
                 if (!frame.isObject(restartFrameSlot) || frame.getObject(restartFrameSlot) == null) {
-                    frame.setObject(restartFrameSlot, RErrorHandling.getRestartStack());
+                    FrameSlotChangeMonitor.setObject(frame, restartFrameSlot, RErrorHandling.getRestartStack());
                 }
             } catch (FrameSlotTypeException e) {
                 throw RInternalError.shouldNotReachHere();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
index 272c1ea4e83234bd361da44fc135b4fff3bb44de..792abffb0e426b6d7920b2eb98ee7f5bc0f7064c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ConnectionFunctions.java
@@ -827,8 +827,7 @@ public abstract class ConnectionFunctions {
 
         static {
             Casts casts = new Casts(ReadBin.class);
-            // TODO con can be a RAWSXP (not implemented)
-            CastsHelper.connection(casts);
+            casts.arg("con").defaultError(Message.INVALID_CONNECTION).mustNotBeNull().returnIf(rawValue()).asIntegerVector().findFirst();
             casts.arg("what").asStringVector().findFirst();
             CastsHelper.n(casts);
             CastsHelper.size(casts);
@@ -836,6 +835,22 @@ public abstract class ConnectionFunctions {
             CastsHelper.swap(casts);
         }
 
+        @SuppressWarnings("unused")
+        @Specialization
+        @TruffleBoundary
+        protected Object readBin(RAbstractRawVector con, String what, int n, int sizeInput, boolean signed, boolean swap) {
+            Object result;
+            switch (what) {
+                case "character":
+                    result = readString(con, con.getLength());
+                    break;
+
+                default:
+                    throw RInternalError.unimplemented();
+            }
+            return result;
+        }
+
         @Specialization
         @TruffleBoundary
         protected Object readBin(int con, String what, int n, int sizeInput, boolean signed, boolean swap) {
@@ -983,6 +998,23 @@ public abstract class ConnectionFunctions {
             return RDataFactory.createStringVector(stringData, RDataFactory.COMPLETE_VECTOR);
         }
 
+        private static RStringVector readString(RAbstractRawVector vec, int n) {
+            ArrayList<String> strings = new ArrayList<>(n);
+            byte[] chars;
+            if (vec instanceof RRaw) {
+                chars = new byte[1];
+                chars[0] = ((RRaw) vec).getRawDataAt(0);
+            } else {
+                chars = ((RRawVector) vec).getDataWithoutCopying();
+            }
+            strings.add(new String(chars, 0, n));
+
+            // There is no special encoding for NA_character_
+            String[] stringData = new String[1];
+            strings.toArray(stringData);
+            return RDataFactory.createStringVector(stringData, RDataFactory.COMPLETE_VECTOR);
+        }
+
         private static RRawVector readRaw(RConnection con, int n) throws IOException {
             ByteBuffer buffer = ByteBuffer.allocate(n);
             int bytesRead = con.readBin(buffer);
@@ -995,6 +1027,13 @@ public abstract class ConnectionFunctions {
             return RDataFactory.createRawVector(data);
         }
 
+        /*
+         * private static RRawVector readRaw(RAbstractRawVector raw, int n) { ByteBuffer buffer =
+         * ByteBuffer.allocate(n); int bytesRead = con.readBin(buffer); if (bytesRead == 0) { return
+         * RDataFactory.createEmptyRawVector(); } buffer.flip(); byte[] data = new byte[bytesRead];
+         * buffer.get(data); return RDataFactory.createRawVector(data); }
+         */
+
         private static RLogicalVector readLogical(RConnection con, int n, boolean swap) throws IOException {
             ByteBuffer buffer = ByteBuffer.allocate(n * 4);
             int bytesRead = con.readBin(buffer);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
deleted file mode 100644
index 56ddfda61520b9138b849c9a25584ee683956452..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Crossprod.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.nodes.builtin.base;
-
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
-import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
-import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RDoubleVector;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-
-@RBuiltin(name = "crossprod", kind = INTERNAL, parameterNames = {"x", "y"}, behavior = PURE)
-public abstract class Crossprod extends RBuiltinNode.Arg2 {
-
-    @Child private MatMult matMult = MatMultNodeGen.create(/* promoteDimNames: */ false);
-    @Child private Transpose transpose;
-
-    static {
-        Casts casts = new Casts(Crossprod.class);
-        casts.arg("x").mustBe(numericValue().or(complexValue()), RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR);
-        casts.arg("y").defaultError(RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR).allowNull().mustBe(numericValue().or(complexValue()));
-    }
-
-    private Object matMult(Object op1, Object op2) {
-        return matMult.executeObject(op1, op2);
-    }
-
-    private Object transpose(RAbstractVector value) {
-        if (transpose == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            transpose = insert(TransposeNodeGen.create());
-        }
-        return transpose.execute(value);
-    }
-
-    @Specialization(guards = {"x.isMatrix()", "y.isMatrix()"})
-    protected RDoubleVector crossprod(RAbstractDoubleVector x, RAbstractDoubleVector y,
-                    @Cached("create()") GetDimAttributeNode getXDimsNode,
-                    @Cached("create()") GetDimAttributeNode getYDimsNode) {
-        int[] xDims = getXDimsNode.getDimensions(x);
-        int[] yDims = getYDimsNode.getDimensions(y);
-        int xRows = xDims[0];
-        int xCols = xDims[1];
-        int yRows = yDims[0];
-        int yCols = yDims[1];
-        return matMult.doubleMatrixMultiply(x, y, xCols, xRows, yRows, yCols, xRows, 1, 1, yRows, false);
-    }
-
-    private static RDoubleVector mirror(RDoubleVector result, GetDimAttributeNode getResultDimsNode) {
-        /*
-         * Mirroring the result is not only good for performance, but it is also required to produce
-         * the same result as GNUR.
-         */
-        int[] resultDims = getResultDimsNode.getDimensions(result);
-        assert result.isMatrix() && resultDims[0] == resultDims[1];
-        int size = resultDims[0];
-        double[] data = result.getDataWithoutCopying();
-        for (int row = 0; row < size; row++) {
-            int destIndex = row * size + row + 1;
-            int sourceIndex = (row + 1) * size + row;
-            for (int col = row + 1; col < size; col++) {
-                data[destIndex] = data[sourceIndex];
-                destIndex++;
-                sourceIndex += size;
-            }
-        }
-        return result;
-    }
-
-    @Specialization
-    protected Object crossprod(RAbstractVector x, RAbstractVector y) {
-        return matMult(transpose(x), y);
-    }
-
-    @Specialization(guards = "x.isMatrix()")
-    protected RDoubleVector crossprodDoubleMatrix(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y,
-                    @Cached("create()") GetDimAttributeNode getDimsNode,
-                    @Cached("create()") GetDimAttributeNode getResultDimsNode) {
-        int[] xDims = getDimsNode.getDimensions(x);
-        int xRows = xDims[0];
-        int xCols = xDims[1];
-        return mirror(matMult.doubleMatrixMultiply(x, x, xCols, xRows, xRows, xCols, xRows, 1, 1, xRows, true), getResultDimsNode);
-    }
-
-    @Specialization
-    protected Object crossprod(RAbstractVector x, @SuppressWarnings("unused") RNull y) {
-        return matMult(transpose(x), x);
-    }
-}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CrossprodCommon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CrossprodCommon.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b4ca6fb6ce7420ac66d24bb5791682dd2dfa6c9
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CrossprodCommon.java
@@ -0,0 +1,200 @@
+/*
+ * 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
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.nodes.builtin.base;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+
+/**
+ * Implements the basic logic for {@code crossprod} and {@code tcrossprod}. Either the first matrix
+ * is transposed or the second one depending on the constructor's argument value.
+ */
+public abstract class CrossprodCommon extends RBuiltinNode.Arg2 {
+
+    @Child private Transpose transpose;
+    @Child protected MatMult matMult = MatMultNodeGen.create(/* promoteDimNames: */ false);
+    @Child private GetDimNamesAttributeNode getXDimNames = GetDimNamesAttributeNode.create();
+    @Child private GetDimNamesAttributeNode getYDimNames = GetDimNamesAttributeNode.create();
+    @Child private SetDimNamesAttributeNode setDimNames = SetDimNamesAttributeNode.create();
+    @Child private ExtractListElement getRowNames = ExtractListElement.create();
+    @Child private ExtractListElement colRowNames = ExtractListElement.create();
+    private final ConditionProfile anyDimNames = ConditionProfile.createBinaryProfile();
+    private final boolean transposeX;
+
+    static {
+        Casts casts = new Casts(CrossprodCommon.class);
+        casts.arg(0).mustBe(numericValue().or(complexValue()), RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR);
+        casts.arg(1).defaultError(RError.Message.NUMERIC_COMPLEX_MATRIX_VECTOR).allowNull().mustBe(numericValue().or(complexValue()));
+    }
+
+    protected CrossprodCommon(boolean transposeX) {
+        this.transposeX = transposeX;
+    }
+
+    public static CrossprodCommon createCrossprod() {
+        return CrossprodCommonNodeGen.create(true);
+    }
+
+    public static CrossprodCommon createTCrossprod() {
+        return CrossprodCommonNodeGen.create(false);
+    }
+
+    @Specialization(guards = {"x.isMatrix()", "y.isMatrix()"})
+    protected RDoubleVector crossprod(RAbstractDoubleVector x, RAbstractDoubleVector y,
+                    @Cached("create()") GetDimAttributeNode getXDimsNode,
+                    @Cached("create()") GetDimAttributeNode getYDimsNode) {
+        int[] xDims = getXDimsNode.getDimensions(x);
+        int[] yDims = getYDimsNode.getDimensions(y);
+        int xRows = transposeX ? xDims[1] : xDims[0];
+        int xCols = transposeX ? xDims[0] : xDims[1];
+        int yRows = transposeX ? yDims[0] : yDims[1];
+        int yCols = transposeX ? yDims[1] : yDims[0];
+        RDoubleVector result = matMult.doubleMatrixMultiply(x, y, xRows, xCols, yRows, yCols, getXRowStride(xDims[0]), getXColStride(xDims[0]), getYRowStride(yDims[0]), getYColStride(yDims[0]),
+                        false);
+        return copyDimNames(x, y, result);
+    }
+
+    @Specialization
+    protected Object crossprod(RAbstractVector x, RAbstractVector y) {
+        return copyDimNames(x, y, (RAbstractVector) matMult.executeObject(transposeX(x), transposeY(y)));
+    }
+
+    @Specialization(guards = "x.isMatrix()")
+    protected RDoubleVector crossprodDoubleMatrix(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y,
+                    @Cached("create()") GetDimAttributeNode getDimsNode,
+                    @Cached("create()") GetDimAttributeNode getResultDimsNode) {
+        int[] xDims = getDimsNode.getDimensions(x);
+        int xRows = transposeX ? xDims[1] : xDims[0];
+        int xCols = transposeX ? xDims[0] : xDims[1];
+        int yRows = transposeX ? xDims[0] : xDims[1];
+        int yCols = transposeX ? xDims[1] : xDims[0];
+        RDoubleVector result = mirror(
+                        matMult.doubleMatrixMultiply(x, x, xRows, xCols, yRows, yCols, getXRowStride(xDims[0]), getXColStride(xDims[0]), getYRowStride(xDims[0]), getYColStride(xDims[0]), true),
+                        getResultDimsNode);
+        return copyDimNames(x, x, result);
+    }
+
+    @Specialization
+    protected Object crossprod(RAbstractVector x, @SuppressWarnings("unused") RNull y) {
+        return copyDimNames(x, x, (RAbstractVector) matMult.executeObject(transposeX(x), transposeY(x)));
+    }
+
+    private Object transposeX(RAbstractVector x) {
+        return transposeX ? transpose(x) : x;
+    }
+
+    private Object transposeY(RAbstractVector y) {
+        return transposeX ? y : transpose(y);
+    }
+
+    private int getXRowStride(int rows) {
+        return transposeX ? rows : 1;
+    }
+
+    private int getXColStride(int rows) {
+        return transposeX ? 1 : rows;
+    }
+
+    private int getYRowStride(int rows) {
+        return transposeX ? 1 : rows;
+    }
+
+    private int getYColStride(int rows) {
+        return transposeX ? rows : 1;
+    }
+
+    private Object transpose(RAbstractVector value) {
+        if (transpose == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            transpose = insert(TransposeNodeGen.create());
+        }
+        return transpose.execute(value);
+    }
+
+    // Copies row names from x and col names from y, note: what is cols and rows changes if the
+    // matrix is transposed.
+    private <T extends RAbstractVector> T copyDimNames(RAbstractVector x, RAbstractVector y, T result) {
+        RList xDimNames = getXDimNames.getDimNames(x);
+        RList yDimNames = getYDimNames.getDimNames(y);
+        if (anyDimNames.profile(xDimNames != null || yDimNames != null)) {
+            Object[] newDimnames = new Object[]{RNull.instance, RNull.instance};
+            if (xDimNames != null) {
+                newDimnames[0] = getRowNames.execute(xDimNames, transposeX ? 1 : 0);
+            }
+            if (yDimNames != null) {
+                newDimnames[1] = getRowNames.execute(yDimNames, transposeX ? 1 : 0);
+            }
+            setDimNames.setDimNames(result, RDataFactory.createList(newDimnames));
+        }
+        return result;
+    }
+
+    private static RDoubleVector mirror(RDoubleVector result, GetDimAttributeNode getResultDimsNode) {
+        // Mirroring the result is not only good for performance, but it is also required to produce
+        // the same result as GNUR.
+        int[] resultDims = getResultDimsNode.getDimensions(result);
+        assert result.isMatrix() && resultDims[0] == resultDims[1];
+        int size = resultDims[0];
+        double[] data = result.getDataWithoutCopying();
+        for (int row = 0; row < size; row++) {
+            int destIndex = row * size + row + 1;
+            int sourceIndex = (row + 1) * size + row;
+            for (int col = row + 1; col < size; col++) {
+                data[destIndex] = data[sourceIndex];
+                destIndex++;
+                sourceIndex += size;
+            }
+        }
+        return result;
+    }
+
+    // Note: these are just a placeholders for the builtin metadata, the actual code is in
+    // CrossprodCommon
+    @RBuiltin(name = "crossprod", kind = INTERNAL, parameterNames = {"x", "y"}, behavior = PURE)
+    public abstract static class Crossprod extends Arg2 {
+    }
+
+    @RBuiltin(name = "tcrossprod", kind = INTERNAL, parameterNames = {"x", "y"}, behavior = PURE)
+    public abstract static class TCrossprod extends Arg2 {
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
index 963a91850bce768380aa729a5abe1be9d79a090d..56bb231456813d173e3755fea8891b5c7a0fdef0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java
@@ -57,6 +57,7 @@ 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.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import java.time.LocalTime;
 
 // from GnuR datatime.c
 
@@ -226,12 +227,12 @@ public class DatePOSIXFunctions {
         @Specialization
         @TruffleBoundary
         protected RDoubleVector asPOSIXct(RAbstractListVector x, String tz) {
-            RAbstractVector secVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(0));
-            RAbstractVector minVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(1));
-            RAbstractVector hourVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(2));
-            RAbstractVector mdayVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(3));
-            RAbstractVector monVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(4));
-            RAbstractVector yearVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(5));
+            RAbstractVector secVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(0));
+            RAbstractVector minVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(1));
+            RAbstractVector hourVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(2));
+            RAbstractVector mdayVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(3));
+            RAbstractVector monVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(4));
+            RAbstractVector yearVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(5));
             TimeZone zone;
             if (tz.isEmpty()) {
                 zone = RContext.getInstance().getSystemTimeZone();
@@ -285,12 +286,12 @@ public class DatePOSIXFunctions {
         @TruffleBoundary
         protected RDoubleVector posix2date(RAbstractListVector x,
                         @Cached("create()") SetClassAttributeNode setClassAttrNode) {
-            RAbstractVector secVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(0));
-            RAbstractVector minVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(1));
-            RAbstractVector hourVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(2));
-            RAbstractVector mdayVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(3));
-            RAbstractVector monVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(4));
-            RAbstractVector yearVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(5));
+            RAbstractVector secVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(0));
+            RAbstractVector minVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(1));
+            RAbstractVector hourVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(2));
+            RAbstractVector mdayVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(3));
+            RAbstractVector monVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(4));
+            RAbstractVector yearVector = (RAbstractVector) RRuntime.convertScalarVectors(x.getDataAt(5));
 
             int length = max(secVector.getLength(), minVector.getLength(), hourVector.getLength(), mdayVector.getLength(), monVector.getLength(), yearVector.getLength());
             double[] data = new double[length];
@@ -344,12 +345,12 @@ public class DatePOSIXFunctions {
         @Specialization
         @TruffleBoundary
         protected RStringVector format(RAbstractListVector x, RAbstractStringVector format, boolean usetz) {
-            RAbstractDoubleVector secVector = (RAbstractDoubleVector) RRuntime.asAbstractVector(x.getDataAt(0));
-            RAbstractIntVector minVector = (RAbstractIntVector) RRuntime.asAbstractVector(x.getDataAt(1));
-            RAbstractIntVector hourVector = (RAbstractIntVector) RRuntime.asAbstractVector(x.getDataAt(2));
-            RAbstractIntVector mdayVector = (RAbstractIntVector) RRuntime.asAbstractVector(x.getDataAt(3));
-            RAbstractIntVector monVector = (RAbstractIntVector) RRuntime.asAbstractVector(x.getDataAt(4));
-            RAbstractIntVector yearVector = (RAbstractIntVector) RRuntime.asAbstractVector(x.getDataAt(5));
+            RAbstractDoubleVector secVector = (RAbstractDoubleVector) RRuntime.convertScalarVectors(x.getDataAt(0));
+            RAbstractIntVector minVector = (RAbstractIntVector) RRuntime.convertScalarVectors(x.getDataAt(1));
+            RAbstractIntVector hourVector = (RAbstractIntVector) RRuntime.convertScalarVectors(x.getDataAt(2));
+            RAbstractIntVector mdayVector = (RAbstractIntVector) RRuntime.convertScalarVectors(x.getDataAt(3));
+            RAbstractIntVector monVector = (RAbstractIntVector) RRuntime.convertScalarVectors(x.getDataAt(4));
+            RAbstractIntVector yearVector = (RAbstractIntVector) RRuntime.convertScalarVectors(x.getDataAt(5));
             ZoneId zone;
             DateTimeFormatterBuilder[] builders = createFormatters(format, false);
             String tzone = getTimeZomeFromAttribute(x);
@@ -427,7 +428,14 @@ public class DatePOSIXFunctions {
                     continue;
                 }
                 try {
-                    LocalDateTime time = LocalDateTime.from(parse);
+                    LocalDateTime time;
+                    try {
+                        time = LocalDateTime.from(parse);
+                    } catch (DateTimeException e) {
+                        // Try just time and use current date
+                        LocalTime tm = LocalTime.from(parse);
+                        time = LocalDateTime.of(LocalDate.now(), tm);
+                    }
                     builder.setEntry(i, time.getSecond(), time.getMinute(), time.getHour(), time.getDayOfMonth(), time.getMonthValue() - 1, time.getYear() - 1900, time.getDayOfWeek().ordinal(),
                                     time.getDayOfYear(), 0);
                     continue;
@@ -455,6 +463,10 @@ public class DatePOSIXFunctions {
 
     private static DateTimeFormatterBuilder createFormatter(String format, boolean forInput) {
         DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
+        if (forInput) {
+            // Opposite of STRICT mode; allows to parse single-digit hour and minute like '0:3:22'.
+            builder.parseLenient();
+        }
         boolean escaped = false;
         int i = 0;
         while (i < format.length()) {
@@ -540,9 +552,10 @@ public class DatePOSIXFunctions {
                     case 'H':
                         /*
                          * Hours as decimal number (00–23). As a special exception strings such as
-                         * 24:00:00 are accepted for input, since ISO 8601 allows these.
+                         * 24:00:00 are accepted for input, since ISO 8601 allows these. For output
+                         * 00-23 is required thus using HOUR_OF_DAY.
                          */
-                        builder.appendValue(ChronoField.CLOCK_HOUR_OF_DAY, 2);
+                        builder.appendValue(forInput ? ChronoField.CLOCK_HOUR_OF_DAY : ChronoField.HOUR_OF_DAY, 2);
                         break;
                     case 'I':
                         // Hours as decimal number (01–12).
@@ -733,7 +746,7 @@ public class DatePOSIXFunctions {
 
     private static String getTimeZomeFromAttribute(RAbstractListVector x) {
         Object attr = x.getAttributes().get("tzone");
-        RAbstractVector vector = (RAbstractVector) RRuntime.asAbstractVector(attr);
+        RAbstractVector vector = (RAbstractVector) RRuntime.convertScalarVectors(attr);
         if (vector.getLength() == 0) {
             return "";
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
index e0793ec5a6f9c87c4c6219f5a5909bd74dcb78c1..87a026db36e484b204ffcbe49af9865fdba99920 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DebugFunctions.java
@@ -22,21 +22,32 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
+
+import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode.Arg3;
 import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling;
 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.RSource;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
@@ -82,7 +93,6 @@ public class DebugFunctions {
         @Specialization
         @TruffleBoundary
         protected RNull debugonce(RFunction fun, Object text, Object condition) {
-            // TODO implement
             doDebug(this, fun, text, condition, true);
             return RNull.instance;
         }
@@ -118,4 +128,48 @@ public class DebugFunctions {
             return RRuntime.asLogical(DebugHandling.isDebugged(func));
         }
     }
+
+    @RBuiltin(name = ".fastr.setBreakpoint", visibility = OFF, kind = PRIMITIVE, parameterNames = {"srcfile", "line", "clear"}, behavior = COMPLEX)
+    public abstract static class FastRSetBreakpoint extends Arg3 {
+
+        static {
+            Casts casts = new Casts(FastRSetBreakpoint.class);
+            casts.arg("srcfile").mustNotBeMissing().mustBe(nullValue().not()).mustBe(stringValue()).asStringVector().findFirst();
+            casts.arg("line").allowMissing().asIntegerVector().findFirst();
+            casts.arg("clear").asLogicalVector().findFirst().map(toBoolean());
+        }
+
+        @Specialization
+        protected Object setBreakpoint(String fileLine, @SuppressWarnings("unused") RMissing lineNr, boolean clear) {
+
+            int hashIdx = fileLine.lastIndexOf('#');
+            if (hashIdx != -1) {
+
+                String fileName = fileLine.substring(0, hashIdx);
+                int lnr = RRuntime.string2intNoCheck(fileLine.substring(hashIdx));
+                if (lnr != RRuntime.INT_NA) {
+                    return setBreakpoint(fileName, lnr, clear);
+                }
+            }
+
+            throw error(RError.Message.GENERIC, "Line number missing");
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object setBreakpoint(String fileName, int lineNr, boolean clear) {
+
+            try {
+                Source fromSrcfile = RSource.fromFileName(fileName, false);
+                if (!clear) {
+                    DebugHandling.enableLineDebug(fromSrcfile, lineNr);
+                } else {
+                    DebugHandling.disableLineDebug(fromSrcfile, lineNr);
+                }
+                return RDataFactory.createStringVectorFromScalar(fileName + "#" + lineNr);
+            } catch (IOException e) {
+                return RNull.instance;
+            }
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index ce6d340ec5cb2eb59e18ed0f4ad03e5748e25fc2..271e4ac0bd5980f0966e60189d3f043000dab43e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 
 import java.util.Arrays;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -45,7 +44,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.DoCallNodeGen.DoCallInternalNodeGen;
@@ -169,7 +167,7 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
                 shareObjectNode.execute(argValues[i]);
             }
             ArgumentsSignature signature = getArgsNames(argsAsList);
-            RCaller caller = RCaller.create(virtualFrame, RCallerHelper.createFromArguments(func, new RArgsValuesAndNames(argValues, signature)));
+            RCaller caller = RCaller.createWithInternalParent(virtualFrame, RCallerHelper.createFromArguments(func, new RArgsValuesAndNames(argValues, signature)));
             try {
                 Object resultValue = RContext.getEngine().evalFunction(func, envFrame, caller, false, signature, argValues);
                 setVisibilityNode.execute(virtualFrame, getVisibility(envFrame));
@@ -184,12 +182,10 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
         protected static boolean isSimple(RFunction function, RList args) {
             RBuiltinDescriptor builtin = function.getRBuiltin();
             if (builtin != null && builtin.getDispatch() != RDispatch.DEFAULT) {
-                CompilerDirectives.transferToInterpreter();
                 return false;
             }
             for (int i = 0; i < args.getLength(); i++) {
                 if (args.getDataAt(i) instanceof RLanguage) {
-                    CompilerDirectives.transferToInterpreter();
                     // Note: language is tricky because of formulae, which are language that is
                     // really not meant to be evaluated again in a different frame than the one were
                     // the were evaluated for the first time. The solution should be to clone the
@@ -208,7 +204,7 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
         }
 
         @TruffleBoundary
-        private boolean getVisibility(MaterializedFrame envFrame) {
+        private static boolean getVisibility(MaterializedFrame envFrame) {
             FrameSlot envVisibilitySlot = FrameSlotChangeMonitor.findOrAddFrameSlot(envFrame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean);
             if (envVisibilitySlot != null) {
                 try {
@@ -228,7 +224,7 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
         }
 
         @TruffleBoundary
-        private CallResult doCallGeneric(RFunction function, Object[] argValues, ArgumentsSignature argsSignature, boolean quote, RCaller call, REnvironment env) {
+        private static CallResult doCallGeneric(RFunction function, Object[] argValues, ArgumentsSignature argsSignature, boolean quote, RCaller call, REnvironment env) {
             RSyntaxNode[] argsConstants = new RSyntaxNode[argValues.length];
             for (int i = 0; i < argValues.length; i++) {
                 if (!quote && argValues[i] instanceof RLanguage) {
@@ -238,7 +234,7 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
                     if (symbol.isMissing()) {
                         argsConstants[i] = ConstantNode.create(REmpty.instance);
                     } else {
-                        argsConstants[i] = ReadVariableNode.create(((RSymbol) argValues[i]).getName());
+                        argsConstants[i] = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) argValues[i]).getName(), false);
                     }
                 } else {
                     argsConstants[i] = ConstantNode.create(argValues[i]);
@@ -249,7 +245,7 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
             }
             RLanguage lang = RDataFactory.createLanguage(RASTUtils.createCall(ConstantNode.create(function), true, argsSignature, argsConstants).asRNode());
             try {
-                Object resultValue = RContext.getEngine().eval(lang, env, call);
+                Object resultValue = RContext.getEngine().eval(lang, env, call.withInternalParent());
                 MaterializedFrame envFrame = env.getFrame();
                 FrameSlot envVisibilitySlot = FrameSlotChangeMonitor.findOrAddFrameSlot(envFrame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean);
                 boolean resultVisibility = false;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
index 1156a95d30ae2872f2e2c89d9a130509b324f968..c871aa49bd28cc1d851c34f8d76cc0cf85a6103f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java
@@ -76,6 +76,7 @@ public class DynLoadFunctions {
                 DLLInfo dllInfo = loadPackageDLLNode.execute(lib, local, now);
                 return dllInfo.toRList();
             } catch (DLLException ex) {
+                ex.printStackTrace();
                 throw error(ex);
             }
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
index 656ad0b6b12e10c6db46ba3b914c698142e316a9..5fc572acadb1e05df9c53596b9fba59c653ca5d4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java
@@ -22,8 +22,10 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -94,7 +96,8 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"leftJustify(justify)", "encodeNA"})
-    protected RStringVector encodeStringLeftJustifyEncodeNA(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA) {
+    protected RStringVector encodeStringLeftJustifyEncodeNA(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         final int maxElWidth = computeWidth(x, width, quoteEl);
         final String[] result = new String[x.getLength()];
         na.enable(x);
@@ -110,12 +113,15 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
                 result[i] = Utils.stringFormat(concat("%-", maxElWidth, "s"), concat(quoteEl, currentEl, quoteEl));
             }
         }
-        return RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+        RStringVector resultVector = RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+        copyAttributesNode.execute(resultVector, x);
+        return resultVector;
     }
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"leftJustify(justify)", "!encodeNA"})
-    protected RStringVector encodeStringLeftJustify(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA) {
+    protected RStringVector encodeStringLeftJustify(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         final int maxElWidth = computeWidth(x, width, quoteEl);
         final String[] result = new String[x.getLength()];
         na.enable(x);
@@ -130,12 +136,15 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
                 result[i] = Utils.stringFormat(concat("%-", maxElWidth, "s"), concat(quoteEl, currentEl, quoteEl));
             }
         }
-        return RDataFactory.createStringVector(result, !seenNA);
+        RStringVector resultVector = RDataFactory.createStringVector(result, !seenNA);
+        copyAttributesNode.execute(resultVector, x);
+        return resultVector;
     }
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"rightJustify(justify)", "encodeNA"})
-    protected RStringVector encodeStringRightJustifyEncodeNA(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA) {
+    protected RStringVector encodeStringRightJustifyEncodeNA(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         final int maxElWidth = computeWidth(x, width, quoteEl);
         final String[] result = new String[x.getLength()];
         na.enable(x);
@@ -151,12 +160,15 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
                 result[i] = Utils.stringFormat(concat("%", maxElWidth, "s"), concat(quoteEl, currentEl, quoteEl));
             }
         }
-        return RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+        RStringVector resultVector = RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+        copyAttributesNode.execute(resultVector, x);
+        return resultVector;
     }
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"rightJustify(justify)", "!encodeNA"})
-    protected RStringVector encodeStringRightJustify(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA) {
+    protected RStringVector encodeStringRightJustify(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         final int maxElWidth = computeWidth(x, width, quoteEl);
         final String[] result = new String[x.getLength()];
         na.enable(x);
@@ -171,12 +183,15 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
                 result[i] = Utils.stringFormat(concat("%", maxElWidth, "s"), concat(quoteEl, currentEl, quoteEl));
             }
         }
-        return RDataFactory.createStringVector(result, !seenNA);
+        RStringVector resultVector = RDataFactory.createStringVector(result, !seenNA);
+        copyAttributesNode.execute(resultVector, x);
+        return resultVector;
     }
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"centerJustify(justify)", "encodeNA"})
-    protected RStringVector encodeStringCenterJustifyEncodeNA(RAbstractStringVector x, int width, String quoteEl, RAbstractIntVector justify, boolean encodeNA) {
+    protected RStringVector encodeStringCenterJustifyEncodeNA(RAbstractStringVector x, int width, String quoteEl, RAbstractIntVector justify, boolean encodeNA,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         final int maxElWidth = computeWidth(x, width, quoteEl);
         final String[] result = new String[x.getLength()];
         final int quoteLength = quoteEl.length() > 0 ? 2 : 0;
@@ -199,12 +214,15 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
             final int rightPadding = totalPadding - leftPadding;
             result[i] = addPadding(currentEl, leftPadding, rightPadding, quoteEl);
         }
-        return RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+        RStringVector resultVector = RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+        copyAttributesNode.execute(resultVector, x);
+        return resultVector;
     }
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"centerJustify(justify)", "!encodeNA"})
-    protected RStringVector encodeStringCenterJustify(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA) {
+    protected RStringVector encodeStringCenterJustify(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         final int maxElWidth = computeWidth(x, width, quoteEl);
         final String[] result = new String[x.getLength()];
         final int quoteLength = quoteEl.length() > 0 ? 2 : 0;
@@ -224,7 +242,9 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
                 result[i] = addPaddingIgnoreNA(currentEl, leftPadding, rightPadding, quoteEl);
             }
         }
-        return RDataFactory.createStringVector(result, !seenNA);
+        RStringVector resultVector = RDataFactory.createStringVector(result, !seenNA);
+        copyAttributesNode.execute(resultVector, x);
+        return resultVector;
     }
 
     @TruffleBoundary
@@ -270,7 +290,8 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"noJustify(width, justify)", "encodeNA"})
-    protected RStringVector encodeStringNoJustifyEncodeNA(RAbstractStringVector x, int width, String quoteEl, RAbstractIntVector justify, boolean encodeNA) {
+    protected RStringVector encodeStringNoJustifyEncodeNA(RAbstractStringVector x, int width, String quoteEl, RAbstractIntVector justify, boolean encodeNA,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         final String[] result = new String[x.getLength()];
         na.enable(x);
         for (int i = 0; i < x.getLength(); i++) {
@@ -282,12 +303,15 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
                 result[i] = concat(quoteEl, currentEl, quoteEl);
             }
         }
-        return RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+        RStringVector resultVector = RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+        copyAttributesNode.execute(resultVector, x);
+        return resultVector;
     }
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"noJustify(width, justify)", "!encodeNA"})
-    protected RStringVector encodeStringNoJustify(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA) {
+    protected RStringVector encodeStringNoJustify(RAbstractStringVector x, int width, final String quoteEl, RAbstractIntVector justify, boolean encodeNA,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         final String[] result = new String[x.getLength()];
         na.enable(x);
         boolean seenNA = false;
@@ -301,7 +325,9 @@ public abstract class EncodeString extends RBuiltinNode.Arg5 {
                 result[i] = concat(quoteEl, currentEl, quoteEl);
             }
         }
-        return RDataFactory.createStringVector(result, !seenNA);
+        RStringVector resultVector = RDataFactory.createStringVector(result, !seenNA);
+        copyAttributesNode.execute(resultVector, x);
+        return resultVector;
     }
 
     protected boolean leftJustify(RAbstractIntVector justify) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
index 1f9ed8bb2281941355312a476d4316dcd3249e62..14cc631717cbcc5bcf1db61d9a08a405b3432d25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java
@@ -70,6 +70,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.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -281,7 +282,6 @@ public class EnvFunctions {
             }
             return REnvironment.globalEnv();
         }
-
     }
 
     @RBuiltin(name = "parent.env", kind = INTERNAL, parameterNames = {"env"}, behavior = READS_FRAME)
@@ -754,6 +754,11 @@ public class EnvFunctions {
             return s;
         }
 
+        @Specialization
+        RExternalPtr copy(RExternalPtr ptr) {
+            return ptr.copy();
+        }
+
         @Specialization
         RSymbol copy(@SuppressWarnings("unused") RMissing m) {
             return RDataFactory.createSymbol(" ");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
index f4d636e57a42f4340d51a196310c18a5b377efdf..0be5eb231324116a9ac7c2f4639f52f6a8a19496 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java
@@ -17,10 +17,10 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
@@ -39,6 +39,7 @@ import java.nio.file.FileSystems;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
 import java.nio.file.Path;
+import java.nio.file.PathMatcher;
 import java.nio.file.Paths;
 import java.nio.file.SimpleFileVisitor;
 import java.nio.file.StandardCopyOption;
@@ -68,8 +69,8 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -1033,7 +1034,7 @@ public class FileFunctions {
         @Specialization
         @TruffleBoundary
         protected RNull show(RAbstractStringVector files, RAbstractStringVector header, RAbstractStringVector title, boolean deleteFile, @SuppressWarnings("unused") String pager) {
-            ConsoleHandler console = RContext.getInstance().getConsoleHandler();
+            ConsoleIO console = RContext.getInstance().getConsole();
             for (int i = 0; i < title.getLength(); i++) {
                 console.println("==== " + title.getDataAt(i) + " ====");
             }
@@ -1128,28 +1129,57 @@ public class FileFunctions {
         @TruffleBoundary
         protected int doUnlink(RAbstractStringVector vec, boolean recursive, @SuppressWarnings("unused") boolean force) {
             int result = 1;
-            FileSystem fileSystem = FileSystems.getDefault();
             for (int i = -0; i < vec.getLength(); i++) {
                 String pathPattern = Utils.tildeExpand(vec.getDataAt(i));
                 if (pathPattern.length() == 0 || RRuntime.isNA(pathPattern)) {
                     continue;
                 }
-                if (containsGlobChar(pathPattern) >= 0) {
-                    throw RError.nyi(this, "wildcards");
+                int firstGlobCharIdx = containsGlobChar(pathPattern);
+                if (firstGlobCharIdx >= 0) {
+                    result = removeGlob(pathPattern, recursive, firstGlobCharIdx, result);
+                } else {
+                    result = removeFile(FileSystems.getDefault().getPath(pathPattern), recursive, result);
                 }
-                Path path = fileSystem.getPath(pathPattern);
-                if (Files.isDirectory(path)) {
-                    if (!recursive) {
-                        continue;
-                    } else {
-                        result = recursiveDelete(path);
+            }
+            return result;
+        }
+
+        private int removeGlob(String pathPattern, boolean recursive, int firstGlobCharIdx, int result) {
+            // we take as much as we can from the pathPatter as the search root
+            int lastSeparator = pathPattern.substring(0, firstGlobCharIdx).lastIndexOf(File.separatorChar);
+            String searchRoot = pathPattern.substring(0, lastSeparator);
+            try {
+                int[] tmpResult = new int[]{result};
+                PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pathPattern);
+                Files.walkFileTree(Paths.get(searchRoot), new SimpleFileVisitor<Path>() {
+                    @Override
+                    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                        if (matcher.matches(file)) {
+                            tmpResult[0] = removeFile(file, recursive, tmpResult[0]);
+                            return recursive ? FileVisitResult.SKIP_SUBTREE : FileVisitResult.CONTINUE;
+                        }
+                        return FileVisitResult.CONTINUE;
                     }
+                });
+                return tmpResult[0];
+            } catch (IOException e) {
+                return 0;
+            }
+        }
+
+        private int removeFile(Path path, boolean recursive, int resultIn) {
+            int result = resultIn;
+            if (Files.isDirectory(path)) {
+                if (!recursive) {
+                    return result;
+                } else {
+                    result = recursiveDelete(path);
                 }
-                try {
-                    Files.deleteIfExists(path);
-                } catch (IOException ex) {
-                    result = 0;
-                }
+            }
+            try {
+                Files.deleteIfExists(path);
+            } catch (IOException ex) {
+                result = 0;
             }
             return result;
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
index 605e55f3fb557cbafdb69fdae364aea1b56d8296..9f531ce897be5d47cfc479fbf748f1b2cbde200e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Floor.java
@@ -22,64 +22,21 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
-@RBuiltin(name = "floor", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class Floor extends UnaryArithmeticBuiltinNode {
+@RBuiltin(name = "floor", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+public final class Floor extends UnaryArithmetic {
 
-    public static final UnaryArithmeticFactory FLOOR = FloorNodeGen.create();
-
-    public Floor() {
-        super(RType.Double, RError.Message.NON_NUMERIC_MATH, null);
-    }
-
-    static {
-        Casts casts = new Casts(Floor.class);
-        casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustNotBeNull().mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(true,
-                        true, true);
-    }
-
-    @Override
-    public int op(byte op) {
-        return op;
-    }
-
-    @Override
-    public int op(int op) {
-        return op;
-    }
+    public static final UnaryArithmeticFactory FLOOR = Floor::new;
 
     @Override
     public double op(double op) {
         return Math.floor(op);
     }
-
-    @Override
-    protected double opd(double re, double im) {
-        return op(re);
-    }
-
-    @Override
-    public RComplex op(double re, double im) {
-        return RDataFactory.createComplex(op(re), op(im));
-    }
-
-    @Specialization
-    @Override
-    public Object calculateUnboxed(Object op) {
-        return super.calculateUnboxed(op);
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
index 6075cc51c5493d49521c59a05d26eba0b06d02c8..16c660c1a74169513f5eeca3b40ffac3335466c2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java
@@ -12,15 +12,34 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gte;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.gt;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.lte;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asIntegerVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asLogicalVector;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.findFirst;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mustBe;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.returnIf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.map;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asInteger;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mapIf;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalNA;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.object.Shape.Pred;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.printer.ComplexVectorPrinter;
 import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter;
@@ -74,7 +93,23 @@ public abstract class Format extends RBuiltinNode.Arg9 {
         casts.arg("width").asIntegerVector().findFirst(0).mustNotBeNA();
         casts.arg("justify").asIntegerVector().findFirst(RRuntime.INT_NA).mustBe(intNA().or(gte(JUSTIFY_LEFT).and(lte(JUSTIFY_NONE))));
         casts.arg("na.encode").asLogicalVector().findFirst(RRuntime.LOGICAL_FALSE).mustNotBeNA().map(toBoolean());
-        casts.arg("scientific").asIntegerVector().findFirst();
+        //@formatter:off
+        casts.arg("scientific").mapIf(logicalValue(),
+                        chain(asLogicalVector()).
+                            with(mustBe(singleElement())).
+                            with(findFirst().logicalElement()).
+                            with(returnIf(logicalNA(), map(constant(RRuntime.INT_NA)))).
+                            with(asInteger()).
+                            with(mapIf(gt(0),
+                                            map(constant(-100)),
+                                            map(constant(100)))).
+                            end(),
+                        chain(mustBe(numericValue())).
+                            with(asIntegerVector()).
+                            with(mustBe(singleElement())).
+                            with(findFirst().integerElement()).
+                            end());
+        //@formatter:on
         casts.arg("decimal.mark").asStringVector().findFirst();
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
index bab1c075934a48b4b486a6b16ec598ad46f3743f..59d2ff208bffeeb5c493687e37792b771ea3e4f9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java
@@ -160,9 +160,11 @@ public abstract class FormatC extends RBuiltinNode.Arg7 {
                     } /* if(do_fg) for(i..) */
                 } else {
                     String form = "%" + flag + width + "." + dig + format;
+                    String form2 = "%" + width + "s";
                     for (int i = 0; i < x.getLength(); i++) {
                         String str = String.format(form, x.getDataAtAsObject(i));
-                        result[i] = ("g".equals(format) || "f".equals(format)) ? trimZero(str) : str;
+                        str = ("g".equals(format) || "f".equals(format)) ? trimZero(str) : str;
+                        result[i] = String.format(form2, str);
                     }
                 }
             } else {
@@ -173,13 +175,21 @@ public abstract class FormatC extends RBuiltinNode.Arg7 {
     }
 
     private static String trimZero(String str) {
-        int i = str.length();
+        int e = str.indexOf('e');
+        int i = e < 0 ? str.length() : e;
         while (i > 0 && str.charAt(i - 1) == '0') {
             i--;
         }
         if (i > 0 && str.charAt(i - 1) == '.') {
             i--;
-            return str.substring(0, i);
+            String s = str.substring(0, i);
+            if (e < 0) {
+                return s;
+            } else {
+                StringBuilder sb = new StringBuilder(s);
+                sb.append(str.substring(e));
+                return sb.toString();
+            }
         }
         if (i == str.length()) {
             return str;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
index e7015136cf9bc346213560e8dfd47a03e42c52c3..a6e10e9ec1e2dca9b7b13a612b0706f55c51be26 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java
@@ -44,7 +44,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.FrameFunctionsFactory.SysFrameNodeGen;
 import com.oracle.truffle.r.nodes.function.ArgumentMatcher;
@@ -351,7 +350,7 @@ public class FrameFunctions {
                 Object argument = varArgParameter.getArgument(((VarArgNode) arg).getIndex());
                 if (argument instanceof RPromise) {
                     RNode unwrapped = (RNode) RASTUtils.unwrap(((RPromise) argument).getRep());
-                    return unwrapped instanceof ConstantNode ? unwrapped : ReadVariableNode.create(createVarArgName((VarArgNode) arg));
+                    return unwrapped instanceof ConstantNode ? unwrapped : RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, createVarArgName((VarArgNode) arg), false).asRNode();
                 } else {
                     return ConstantNode.create(argument);
                 }
@@ -650,6 +649,8 @@ public class FrameFunctions {
         @Specialization(guards = "n == 1")
         protected REnvironment parentFrameDirect(VirtualFrame frame, @SuppressWarnings("unused") int n,
                         @Cached("new()") GetCallerFrameNode getCaller) {
+            // Note: this works even without checking the call#hasInternalParent()
+            // The environment in the arguments array is the right one even after 'do.call'.
             return REnvironment.frameToEnvironment(getCaller.execute(frame));
         }
 
@@ -663,7 +664,11 @@ public class FrameFunctions {
                 promiseProfile.enter();
                 call = call.getParent();
             }
-            for (int i = 0; i < n; i++) {
+            int i = 0;
+            while (i < n) {
+                if (call.hasInternalParent()) {
+                    i--;    // in this loop iteration, we deal with the parent, but do not count it
+                }
                 call = call.getParent();
                 if (call == null) {
                     nullCallerProfile.enter();
@@ -673,6 +678,7 @@ public class FrameFunctions {
                     promiseProfile.enter();
                     call = call.getParent();
                 }
+                i++;
             }
             nonNullCallerProfile.enter();
             // if (RArguments.getDispatchArgs(f) != null && RArguments.getDispatchArgs(f) instanceof
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 ef414d42b61e114ba26cc3a4c5960b2a0bf0aa56..3e5b3d2fb9bbfc7022715e181b1ca6b59e44ca68 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
@@ -201,7 +201,6 @@ public class GetFunctions {
         protected Object get(VirtualFrame frame, String x, int envir, String mode, boolean inherits) {
             throw RInternalError.unimplemented();
         }
-
     }
 
     @RBuiltin(name = "get0", kind = INTERNAL, parameterNames = {"x", "envir", "mode", "inherits", "ifnotfound"}, behavior = COMPLEX)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java
index c8244e9b43e119641fcfe61092aaede81f6c5d26..868d59ad7321fbca04a61103f268912a5079f6cb 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Getwd.java
@@ -31,11 +31,12 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
 @RBuiltin(name = "getwd", kind = INTERNAL, parameterNames = {}, behavior = IO)
 public abstract class Getwd extends RBuiltinNode.Arg0 {
 
-    @Child private BaseRFFI.GetwdNode getwdNode = BaseRFFI.GetwdNode.create();
+    @Child private BaseRFFI.GetwdNode getwdNode = RFFIFactory.getBaseRFFI().createGetwdNode();
 
     @Specialization
     @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
index d1432ee475bb9ad690ebd2e7ee58f7c4464ef6d5..177902b34d228318732f5c7a32d605c22e6d8115 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java
@@ -14,9 +14,9 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -27,7 +27,6 @@ import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
-import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
@@ -39,6 +38,7 @@ import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RegExp;
@@ -122,8 +122,8 @@ public class GrepFunctions {
 
     @NodeInfo(cost = NodeCost.NONE)
     public static class CommonCodeNode extends RBaseNode {
-        @Child protected PCRERFFI.MaketablesNode maketablesNode = RFFIFactory.getRFFI().getPCRERFFI().createMaketablesNode();
-        @Child protected PCRERFFI.CompileNode compileNode = RFFIFactory.getRFFI().getPCRERFFI().createCompileNode();
+        @Child protected PCRERFFI.MaketablesNode maketablesNode = RFFIFactory.getPCRERFFI().createMaketablesNode();
+        @Child protected PCRERFFI.CompileNode compileNode = RFFIFactory.getPCRERFFI().createCompileNode();
 
         /**
          * Temporary method that handles the check for the arguments that are common to the majority
@@ -217,85 +217,89 @@ public class GrepFunctions {
     }
 
     protected static final class GrepCommonCodeNode extends CommonCodeNode {
-        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getPCRERFFI().createExecNode();
 
         protected Object doGrep(String patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean value, boolean perlPar, boolean fixed,
                         @SuppressWarnings("unused") boolean useBytes, boolean invert, boolean grepl) {
-            boolean perl = perlPar;
-            perl = checkPerlFixed(perlPar, fixed);
-            checkCaseFixed(ignoreCase, fixed);
-
-            String pattern = patternArg;
-            int len = vector.getLength();
-            if (RRuntime.isNA(pattern)) {
-                return value ? allStringNAResult(len) : allIntNAResult(len);
-            }
-            boolean[] matches = new boolean[len];
-            if (!perl) {
-                // TODO case
-                if (!fixed) {
-                    pattern = RegExp.checkPreDefinedClasses(pattern);
+            try {
+                boolean perl = perlPar;
+                perl = checkPerlFixed(perlPar, fixed);
+                checkCaseFixed(ignoreCase, fixed);
+
+                String pattern = patternArg;
+                int len = vector.getLength();
+                if (RRuntime.isNA(pattern)) {
+                    return value ? allStringNAResult(len) : allIntNAResult(len);
                 }
-                findAllMatches(matches, pattern, vector, fixed, ignoreCase);
-            } else {
-                PCRERFFI.Result pcre = compilePerlPattern(pattern, ignoreCase);
-                // TODO pcre_study for vectors > 10 ? (cf GnuR)
-                int[] ovector = new int[30];
-                for (int i = 0; i < len; i++) {
-                    String text = vector.getDataAt(i);
-                    if (!RRuntime.isNA(text)) {
-                        if (execNode.execute(pcre.result, 0, text, 0, 0, ovector) >= 0) {
-                            matches[i] = true;
+                boolean[] matches = new boolean[len];
+                if (!perl) {
+                    // TODO case
+                    if (!fixed) {
+                        pattern = RegExp.checkPreDefinedClasses(pattern);
+                    }
+                    findAllMatches(matches, pattern, vector, fixed, ignoreCase);
+                } else {
+                    PCRERFFI.Result pcre = compilePerlPattern(pattern, ignoreCase);
+                    // TODO pcre_study for vectors > 10 ? (cf GnuR)
+                    int[] ovector = new int[30];
+                    for (int i = 0; i < len; i++) {
+                        String text = vector.getDataAt(i);
+                        if (!RRuntime.isNA(text)) {
+                            if (execNode.execute(pcre.result, 0, text, 0, 0, ovector) >= 0) {
+                                matches[i] = true;
+                            }
                         }
                     }
                 }
-            }
 
-            if (grepl) {
-                byte[] data = new byte[len];
-                for (int i = 0; i < len; i++) {
-                    data[i] = RRuntime.asLogical(matches[i]);
+                if (grepl) {
+                    byte[] data = new byte[len];
+                    for (int i = 0; i < len; i++) {
+                        data[i] = RRuntime.asLogical(matches[i]);
+                    }
+                    return RDataFactory.createLogicalVector(data, RDataFactory.COMPLETE_VECTOR);
                 }
-                return RDataFactory.createLogicalVector(data, RDataFactory.COMPLETE_VECTOR);
-            }
 
-            int nmatches = 0;
-            for (int i = 0; i < len; i++) {
-                if (invert ^ matches[i]) {
-                    nmatches++;
+                int nmatches = 0;
+                for (int i = 0; i < len; i++) {
+                    if (invert ^ matches[i]) {
+                        nmatches++;
+                    }
                 }
-            }
 
-            if (nmatches == 0) {
-                return value ? RDataFactory.createEmptyStringVector() : RDataFactory.createEmptyIntVector();
-            } else {
-                if (value) {
-                    RStringVector oldNames = vector.getNames();
-                    String[] newNames = null;
-                    if (oldNames != null) {
-                        newNames = new String[nmatches];
-                    }
-                    String[] data = new String[nmatches];
-                    int j = 0;
-                    for (int i = 0; i < len; i++) {
-                        if (invert ^ matches[i]) {
-                            if (newNames != null) {
-                                newNames[j] = oldNames.getDataAt(i);
+                if (nmatches == 0) {
+                    return value ? RDataFactory.createEmptyStringVector() : RDataFactory.createEmptyIntVector();
+                } else {
+                    if (value) {
+                        RStringVector oldNames = vector.getNames();
+                        String[] newNames = null;
+                        if (oldNames != null) {
+                            newNames = new String[nmatches];
+                        }
+                        String[] data = new String[nmatches];
+                        int j = 0;
+                        for (int i = 0; i < len; i++) {
+                            if (invert ^ matches[i]) {
+                                if (newNames != null) {
+                                    newNames[j] = oldNames.getDataAt(i);
+                                }
+                                data[j++] = vector.getDataAt(i);
                             }
-                            data[j++] = vector.getDataAt(i);
                         }
-                    }
-                    return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR, newNames == null ? null : RDataFactory.createStringVector(newNames, RDataFactory.COMPLETE_VECTOR));
-                } else {
-                    int[] data = new int[nmatches];
-                    int j = 0;
-                    for (int i = 0; i < len; i++) {
-                        if (invert ^ matches[i]) {
-                            data[j++] = i + 1;
+                        return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR, newNames == null ? null : RDataFactory.createStringVector(newNames, RDataFactory.COMPLETE_VECTOR));
+                    } else {
+                        int[] data = new int[nmatches];
+                        int j = 0;
+                        for (int i = 0; i < len; i++) {
+                            if (invert ^ matches[i]) {
+                                data[j++] = i + 1;
+                            }
                         }
+                        return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR);
                     }
-                    return RDataFactory.createIntVector(data, RDataFactory.COMPLETE_VECTOR);
                 }
+            } catch (PatternSyntaxException e) {
+                throw error(Message.INVALID_REGEXP_REASON, patternArg, e.getMessage());
             }
         }
 
@@ -417,7 +421,7 @@ public class GrepFunctions {
     }
 
     protected static final class SubCommonCodeNode extends CommonCodeNode {
-        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getPCRERFFI().createExecNode();
 
         protected RStringVector doSub(String patternArg, String replacementArg, RAbstractStringVector vector, boolean ignoreCase, boolean perlPar,
                         boolean fixedPar, @SuppressWarnings("unused") boolean useBytes, boolean gsub) {
@@ -543,8 +547,7 @@ public class GrepFunctions {
                 ret.copyAttributesFrom(vector);
                 return ret;
             } catch (PatternSyntaxException e) {
-                CompilerDirectives.transferToInterpreter();
-                throw new RInternalError(e, "internal error: %s", e.getMessage());
+                throw error(Message.INVALID_REGEXP_REASON, patternArg, e.getMessage());
             }
         }
 
@@ -741,9 +744,9 @@ public class GrepFunctions {
         @Child SetFixedAttributeNode setCaptureLengthAttrNode = SetFixedAttributeNode.create("capture.length");
         @Child SetFixedAttributeNode setCaptureNamesAttrNode = SetFixedAttributeNode.create("capture.names");
         @Child SetFixedAttributeNode setDimNamesAttrNode = SetFixedAttributeNode.createDimNames();
-        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
-        @Child PCRERFFI.GetCaptureNamesNode getCaptureNamesNode = RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureNamesNode();
-        @Child PCRERFFI.GetCaptureCountNode getCaptureCountNode = RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureCountNode();
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getPCRERFFI().createExecNode();
+        @Child PCRERFFI.GetCaptureNamesNode getCaptureNamesNode = RFFIFactory.getPCRERFFI().createGetCaptureNamesNode();
+        @Child PCRERFFI.GetCaptureCountNode getCaptureCountNode = RFFIFactory.getPCRERFFI().createGetCaptureCountNode();
 
         static {
             Casts casts = new Casts(Regexpr.class);
@@ -784,71 +787,76 @@ public class GrepFunctions {
         @TruffleBoundary
         protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean perl, boolean fixed, boolean useBytesL,
                         @Cached("createCommon()") CommonCodeNode common) {
-            common.checkExtraArgs(false, false, false, useBytesL, false);
-            if (patternArg.getLength() > 1) {
-                throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet");
-            }
-            String pattern = patternArg.getDataAt(0);
-            if (!perl) {
-                pattern = RegExp.checkPreDefinedClasses(pattern);
-            }
-            // TODO: useBytes normally depends on the value of the parameter and (if false) on
-            // whether the string is ASCII
-            boolean useBytes = true;
-            boolean hasAnyCapture = false;
-            int[] result = new int[vector.getLength()];
-            int[] matchLength = new int[vector.getLength()];
-            String[] captureNames = null;
-            int[] captureStart = null;
-            int[] captureLength = null;
-            if (pattern.length() == 0) {
-                // emtpy pattern
-                Arrays.fill(result, 1);
-            } else {
-                for (int i = 0; i < vector.getLength(); i++) {
-                    Info res = getInfo(common, pattern, vector.getDataAt(i), ignoreCase, perl, fixed).get(0);
-                    result[i] = res.index;
-                    matchLength[i] = res.size;
-                    if (res.hasCapture) {
-                        hasAnyCapture = true;
-                        if (captureNames == null) {
-                            // first time we see captures
-                            captureNames = res.captureNames;
-                            captureStart = new int[captureNames.length * vector.getLength()];
-                            captureLength = new int[captureNames.length * vector.getLength()];
-                            // previous matches had no capture - fill in result with -1-s
-                            for (int k = 0; k < i; k++) {
-                                setNoCaptureValues(captureStart, captureLength, captureNames.length, vector.getLength(), k);
+            try {
+                common.checkExtraArgs(false, false, false, useBytesL, false);
+                if (patternArg.getLength() > 1) {
+                    throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet");
+                }
+                String pattern = patternArg.getDataAt(0);
+                if (!perl) {
+                    pattern = RegExp.checkPreDefinedClasses(pattern);
+                }
+                // TODO: useBytes normally depends on the value of the parameter and (if false) on
+                // whether the string is ASCII
+                boolean useBytes = true;
+                boolean hasAnyCapture = false;
+                int[] result = new int[vector.getLength()];
+                int[] matchLength = new int[vector.getLength()];
+                String[] captureNames = null;
+                int[] captureStart = null;
+                int[] captureLength = null;
+                if (pattern.length() == 0) {
+                    // emtpy pattern
+                    Arrays.fill(result, 1);
+                } else {
+                    for (int i = 0; i < vector.getLength(); i++) {
+                        Info res = getInfo(common, pattern, vector.getDataAt(i), ignoreCase, perl, fixed).get(0);
+                        result[i] = res.index;
+                        matchLength[i] = res.size;
+                        if (res.hasCapture) {
+                            hasAnyCapture = true;
+                            if (captureNames == null) {
+                                // first time we see captures
+                                captureNames = res.captureNames;
+                                captureStart = new int[captureNames.length * vector.getLength()];
+                                captureLength = new int[captureNames.length * vector.getLength()];
+                                // previous matches had no capture - fill in result with -1-s
+                                for (int k = 0; k < i; k++) {
+                                    setNoCaptureValues(captureStart, captureLength, captureNames.length, vector.getLength(), k);
+                                }
                             }
+                            assert captureNames.length == res.captureStart.length;
+                            assert captureNames.length == res.captureLength.length;
+                            for (int j = 0; j < captureNames.length; j++) {
+                                captureStart[j * vector.getLength() + i] = res.captureStart[j];
+                                captureLength[j * vector.getLength() + i] = res.captureLength[j];
+                            }
+                        } else if (hasAnyCapture) {
+                            // no capture for this part of the vector, but there are previous
+                            // captures
+                            setNoCaptureValues(captureStart, captureLength, captureNames.length, vector.getLength(), i);
                         }
-                        assert captureNames.length == res.captureStart.length;
-                        assert captureNames.length == res.captureLength.length;
-                        for (int j = 0; j < captureNames.length; j++) {
-                            captureStart[j * vector.getLength() + i] = res.captureStart[j];
-                            captureLength[j * vector.getLength() + i] = res.captureLength[j];
-                        }
-                    } else if (hasAnyCapture) {
-                        // no capture for this part of the vector, but there are previous captures
-                        setNoCaptureValues(captureStart, captureLength, captureNames.length, vector.getLength(), i);
                     }
                 }
+                RIntVector ret = RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR);
+                setMatchLengthAttrNode.execute(ret, RDataFactory.createIntVector(matchLength, RDataFactory.COMPLETE_VECTOR));
+                if (useBytes) {
+                    setUseBytesAttrNode.execute(ret, RRuntime.LOGICAL_TRUE);
+                }
+                if (hasAnyCapture) {
+                    RStringVector captureNamesVec = RDataFactory.createStringVector(captureNames, RDataFactory.COMPLETE_VECTOR);
+                    RIntVector captureStartVec = RDataFactory.createIntVector(captureStart, RDataFactory.COMPLETE_VECTOR, new int[]{vector.getLength(), captureNames.length});
+                    setDimNamesAttrNode.execute(captureStartVec, RDataFactory.createList(new Object[]{RNull.instance, captureNamesVec.copy()}));
+                    setCaptureStartAttrNode.execute(ret, captureStartVec);
+                    RIntVector captureLengthVec = RDataFactory.createIntVector(captureLength, RDataFactory.COMPLETE_VECTOR, new int[]{vector.getLength(), captureNames.length});
+                    setDimNamesAttrNode.execute(captureLengthVec, RDataFactory.createList(new Object[]{RNull.instance, captureNamesVec.copy()}));
+                    setCaptureLengthAttrNode.execute(ret, captureLengthVec);
+                    setCaptureNamesAttrNode.execute(ret, captureNamesVec);
+                }
+                return ret;
+            } catch (PatternSyntaxException e) {
+                throw error(Message.INVALID_REGEXP_REASON, patternArg, e.getMessage());
             }
-            RIntVector ret = RDataFactory.createIntVector(result, RDataFactory.COMPLETE_VECTOR);
-            setMatchLengthAttrNode.execute(ret, RDataFactory.createIntVector(matchLength, RDataFactory.COMPLETE_VECTOR));
-            if (useBytes) {
-                setUseBytesAttrNode.execute(ret, RRuntime.LOGICAL_TRUE);
-            }
-            if (hasAnyCapture) {
-                RStringVector captureNamesVec = RDataFactory.createStringVector(captureNames, RDataFactory.COMPLETE_VECTOR);
-                RIntVector captureStartVec = RDataFactory.createIntVector(captureStart, RDataFactory.COMPLETE_VECTOR, new int[]{vector.getLength(), captureNames.length});
-                setDimNamesAttrNode.execute(captureStartVec, RDataFactory.createList(new Object[]{RNull.instance, captureNamesVec.copy()}));
-                setCaptureStartAttrNode.execute(ret, captureStartVec);
-                RIntVector captureLengthVec = RDataFactory.createIntVector(captureLength, RDataFactory.COMPLETE_VECTOR, new int[]{vector.getLength(), captureNames.length});
-                setDimNamesAttrNode.execute(captureLengthVec, RDataFactory.createList(new Object[]{RNull.instance, captureNamesVec.copy()}));
-                setCaptureLengthAttrNode.execute(ret, captureLengthVec);
-                setCaptureNamesAttrNode.execute(ret, captureNamesVec);
-            }
-            return ret;
         }
 
         protected List<Info> getInfo(CommonCodeNode common, String pattern, String text, boolean ignoreCase, boolean perl, boolean fixed) {
@@ -960,39 +968,43 @@ public class GrepFunctions {
         @TruffleBoundary
         protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCase, boolean fixed, boolean useBytes,
                         @Cached("createCommon()") CommonCodeNode common) {
-            common.checkExtraArgs(false, false, false, useBytes, false);
-            if (patternArg.getLength() > 1) {
-                throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet");
-            }
-            RList ret = RDataFactory.createList(vector.getLength());
-            String pattern = patternArg.getDataAt(0);
-            pattern = RegExp.checkPreDefinedClasses(pattern);
-            // TODO: useBytes normally depends on the value of the parameter and (if false) on
-            // whether the string is ASCII
-            for (int i = 0; i < vector.getLength(); i++) {
-                int[] matchPos;
-                int[] matchLength;
-                if (pattern.length() == 0) {
-                    // emtpy pattern
-                    matchPos = new int[]{1};
-                    matchLength = new int[]{0};
-                } else {
-                    List<Info> res = getInfo(pattern, vector.getDataAt(i), ignoreCase, fixed);
-                    matchPos = new int[res.size()];
-                    matchLength = new int[res.size()];
-                    for (int j = 0; j < res.size(); j++) {
-                        matchPos[j] = res.get(j).index;
-                        matchLength[j] = res.get(j).size;
+            try {
+                common.checkExtraArgs(false, false, false, useBytes, false);
+                if (patternArg.getLength() > 1) {
+                    throw RInternalError.unimplemented("multi-element patterns in regexpr not implemented yet");
+                }
+                RList ret = RDataFactory.createList(vector.getLength());
+                String pattern = patternArg.getDataAt(0);
+                pattern = RegExp.checkPreDefinedClasses(pattern);
+                // TODO: useBytes normally depends on the value of the parameter and (if false) on
+                // whether the string is ASCII
+                for (int i = 0; i < vector.getLength(); i++) {
+                    int[] matchPos;
+                    int[] matchLength;
+                    if (pattern.length() == 0) {
+                        // emtpy pattern
+                        matchPos = new int[]{1};
+                        matchLength = new int[]{0};
+                    } else {
+                        List<Info> res = getInfo(pattern, vector.getDataAt(i), ignoreCase, fixed);
+                        matchPos = new int[res.size()];
+                        matchLength = new int[res.size()];
+                        for (int j = 0; j < res.size(); j++) {
+                            matchPos[j] = res.get(j).index;
+                            matchLength[j] = res.get(j).size;
+                        }
                     }
+                    RIntVector matches = RDataFactory.createIntVector(matchPos, RDataFactory.COMPLETE_VECTOR);
+                    setMatchLengthAttrNode.execute(matches, RDataFactory.createIntVector(matchLength, RDataFactory.COMPLETE_VECTOR));
+                    ret.setElement(i, matches);
                 }
-                RIntVector matches = RDataFactory.createIntVector(matchPos, RDataFactory.COMPLETE_VECTOR);
-                setMatchLengthAttrNode.execute(matches, RDataFactory.createIntVector(matchLength, RDataFactory.COMPLETE_VECTOR));
-                ret.setElement(i, matches);
-            }
-            if (useBytes) {
-                setUseBytesAttrNode.execute(ret, RRuntime.LOGICAL_TRUE);
+                if (useBytes) {
+                    setUseBytesAttrNode.execute(ret, RRuntime.LOGICAL_TRUE);
+                }
+                return ret;
+            } catch (PatternSyntaxException e) {
+                throw error(Message.INVALID_REGEXP_REASON, patternArg, e.getMessage());
             }
-            return ret;
         }
 
         protected List<Info> getInfo(String pattern, String text, boolean ignoreCase, boolean fixed) {
@@ -1069,68 +1081,72 @@ public class GrepFunctions {
         @Override
         protected Object regexp(RAbstractStringVector patternArg, RAbstractStringVector vector, boolean ignoreCaseL, boolean perlL, boolean fixedL, boolean useBytesL,
                         @Cached("createCommon()") CommonCodeNode common) {
-            common.checkExtraArgs(false, false, false, useBytesL, false);
-            boolean ignoreCase = ignoreCaseL;
-            boolean fixed = fixedL;
-            boolean perl = perlL;
-            if (patternArg.getLength() > 1) {
-                throw RInternalError.unimplemented("multi-element patterns in gregexpr not implemented yet");
-            }
-            String pattern = patternArg.getDataAt(0);
-            if (!perl) {
-                pattern = RegExp.checkPreDefinedClasses(pattern);
-            }
-            // TODO: useBytes normally depends on the value of the parameter and (if false) on
-            // whether the string is ASCII
-            boolean useBytes = true;
-            Object[] result = new Object[vector.getLength()];
-            boolean hasAnyCapture = false;
-            RStringVector captureNames = null;
-            for (int i = 0; i < vector.getLength(); i++) {
-                RIntVector res;
-                if (pattern.length() == 0) {
-                    String txt = vector.getDataAt(i);
-                    res = RDataFactory.createIntVector(txt.length());
-                    for (int j = 0; j < txt.length(); j++) {
-                        res.setDataAt(res.getDataWithoutCopying(), j, j + 1);
-                    }
-                    setMatchLengthAttrNode.execute(res, RDataFactory.createIntVector(txt.length()));
-                    if (useBytes) {
-                        setUseBytesAttrNode.execute(res, RRuntime.LOGICAL_TRUE);
-                    }
-                } else {
-                    List<Info> l = getInfo(common, pattern, vector.getDataAt(i), ignoreCase, perl, fixed);
-                    res = toIndexOrSizeVector(l, true);
-                    setMatchLengthAttrNode.execute(res, toIndexOrSizeVector(l, false));
-                    if (useBytes) {
-                        setUseBytesAttrNode.execute(res, RRuntime.LOGICAL_TRUE);
-                    }
-                    RIntVector captureStart = toCaptureStartOrLength(l, true);
-                    if (captureStart != null) {
-                        RIntVector captureLength = toCaptureStartOrLength(l, false);
-                        assert captureLength != null;
-                        captureNames = getCaptureNamesVector(l);
-                        assert captureNames.getLength() > 0;
-                        if (!hasAnyCapture) {
-                            // set previous result list elements to "no capture"
-                            for (int j = 0; j < i; j++) {
-                                setNoCaptureAttributes((RIntVector) result[j], captureNames);
+            try {
+                common.checkExtraArgs(false, false, false, useBytesL, false);
+                boolean ignoreCase = ignoreCaseL;
+                boolean fixed = fixedL;
+                boolean perl = perlL;
+                if (patternArg.getLength() > 1) {
+                    throw RInternalError.unimplemented("multi-element patterns in gregexpr not implemented yet");
+                }
+                String pattern = patternArg.getDataAt(0);
+                if (!perl) {
+                    pattern = RegExp.checkPreDefinedClasses(pattern);
+                }
+                // TODO: useBytes normally depends on the value of the parameter and (if false) on
+                // whether the string is ASCII
+                boolean useBytes = true;
+                Object[] result = new Object[vector.getLength()];
+                boolean hasAnyCapture = false;
+                RStringVector captureNames = null;
+                for (int i = 0; i < vector.getLength(); i++) {
+                    RIntVector res;
+                    if (pattern.length() == 0) {
+                        String txt = vector.getDataAt(i);
+                        res = RDataFactory.createIntVector(txt.length());
+                        for (int j = 0; j < txt.length(); j++) {
+                            res.setDataAt(res.getDataWithoutCopying(), j, j + 1);
+                        }
+                        setMatchLengthAttrNode.execute(res, RDataFactory.createIntVector(txt.length()));
+                        if (useBytes) {
+                            setUseBytesAttrNode.execute(res, RRuntime.LOGICAL_TRUE);
+                        }
+                    } else {
+                        List<Info> l = getInfo(common, pattern, vector.getDataAt(i), ignoreCase, perl, fixed);
+                        res = toIndexOrSizeVector(l, true);
+                        setMatchLengthAttrNode.execute(res, toIndexOrSizeVector(l, false));
+                        if (useBytes) {
+                            setUseBytesAttrNode.execute(res, RRuntime.LOGICAL_TRUE);
+                        }
+                        RIntVector captureStart = toCaptureStartOrLength(l, true);
+                        if (captureStart != null) {
+                            RIntVector captureLength = toCaptureStartOrLength(l, false);
+                            assert captureLength != null;
+                            captureNames = getCaptureNamesVector(l);
+                            assert captureNames.getLength() > 0;
+                            if (!hasAnyCapture) {
+                                // set previous result list elements to "no capture"
+                                for (int j = 0; j < i; j++) {
+                                    setNoCaptureAttributes((RIntVector) result[j], captureNames);
+                                }
                             }
+                            hasAnyCapture = true;
+                            setCaptureStartAttrNode.execute(res, captureStart);
+                            setCaptureLengthAttrNode.execute(res, captureLength);
+                            setCaptureNamesAttrNode.execute(res, captureNames);
+                        } else if (hasAnyCapture) {
+                            assert captureNames != null;
+                            // it's capture names from previous iteration, so copy
+                            setNoCaptureAttributes(res, (RStringVector) captureNames.copy());
                         }
-                        hasAnyCapture = true;
-                        setCaptureStartAttrNode.execute(res, captureStart);
-                        setCaptureLengthAttrNode.execute(res, captureLength);
-                        setCaptureNamesAttrNode.execute(res, captureNames);
-                    } else if (hasAnyCapture) {
-                        assert captureNames != null;
-                        // it's capture names from previous iteration, so copy
-                        setNoCaptureAttributes(res, (RStringVector) captureNames.copy());
                     }
-                }
 
-                result[i] = res;
+                    result[i] = res;
+                }
+                return RDataFactory.createList(result);
+            } catch (PatternSyntaxException e) {
+                throw error(Message.INVALID_REGEXP_REASON, patternArg, e.getMessage());
             }
-            return RDataFactory.createList(result);
         }
 
         private static RIntVector toIndexOrSizeVector(List<Info> list, boolean index) {
@@ -1326,7 +1342,7 @@ public class GrepFunctions {
     @ImportStatic(GrepFunctions.class)
     @RBuiltin(name = "strsplit", kind = INTERNAL, parameterNames = {"x", "split", "fixed", "perl", "useBytes"}, behavior = PURE)
     public abstract static class Strsplit extends RBuiltinNode.Arg5 {
-        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
+        @Child PCRERFFI.ExecNode execNode = RFFIFactory.getPCRERFFI().createExecNode();
 
         static {
             Casts casts = new Casts(Strsplit.class);
@@ -1368,31 +1384,40 @@ public class GrepFunctions {
             }
             for (int i = 0; i < x.getLength(); i++) {
                 String data = x.getDataAt(i);
+                assert data != null;
+                if (data.length() == 0) {
+                    result[i] = RDataFactory.createEmptyStringVector();
+                    continue;
+                }
                 String currentSplit = splits[i % splits.length];
-                if (currentSplit.isEmpty()) {
-                    result[i] = na.check(data) ? RDataFactory.createNAStringVector() : emptySplitIntl(data);
-                } else if (RRuntime.isNA(currentSplit)) {
-                    // NA doesn't split
-                    result[i] = RDataFactory.createStringVectorFromScalar(data);
-                } else {
-                    RStringVector resultItem;
-                    if (na.check(data)) {
-                        resultItem = RDataFactory.createNAStringVector();
+                try {
+                    if (currentSplit.isEmpty()) {
+                        result[i] = na.check(data) ? RDataFactory.createNAStringVector() : emptySplitIntl(data);
+                    } else if (RRuntime.isNA(currentSplit)) {
+                        // NA doesn't split
+                        result[i] = RDataFactory.createStringVectorFromScalar(data);
                     } else {
-                        if (perl) {
-                            resultItem = splitPerl(data, pcreSplits[i % splits.length]);
+                        RStringVector resultItem;
+                        if (na.check(data)) {
+                            resultItem = RDataFactory.createNAStringVector();
                         } else {
-                            resultItem = splitIntl(data, currentSplit, fixed);
-                        }
-                        if (resultItem.getLength() == 0) {
-                            if (fixed) {
-                                resultItem = RDataFactory.createStringVector(data);
+                            if (perl) {
+                                resultItem = splitPerl(data, pcreSplits[i % splits.length]);
                             } else {
-                                resultItem = RDataFactory.createStringVector(data.length());
+                                resultItem = splitIntl(data, currentSplit, fixed);
+                            }
+                            if (resultItem.getLength() == 0) {
+                                if (fixed) {
+                                    resultItem = RDataFactory.createStringVector(data);
+                                } else {
+                                    resultItem = RDataFactory.createStringVector(data.length());
+                                }
                             }
                         }
+                        result[i] = resultItem;
                     }
-                    result[i] = resultItem;
+                } catch (PatternSyntaxException e) {
+                    throw error(Message.INVALID_REGEXP_REASON, currentSplit, e.getMessage());
                 }
             }
             RList ret = RDataFactory.createList(result);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
index 4b75dccff92fd1ddda1fb5943fb4c8361eb1ad68..c4a74c677561cd9277671d5b3fb91cd98eeb0034 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IConv.java
@@ -22,12 +22,15 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import com.oracle.truffle.api.dsl.Cached;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -53,9 +56,15 @@ public abstract class IConv extends RBuiltinNode.Arg6 {
 
     @SuppressWarnings("unused")
     @Specialization
-    protected RStringVector doIConv(RAbstractStringVector x, Object from, Object to, Object sub, byte mark, byte toRaw) {
+    protected RStringVector doIConv(RAbstractStringVector x, Object from, Object to, Object sub, byte mark, byte toRaw,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode,
+                    @Cached("createBinaryProfile()") ConditionProfile xLengthProfile) {
         // TODO implement
         RStringVector xv = x.materialize();
-        return RDataFactory.createStringVector(xv.getDataCopy(), RDataFactory.COMPLETE_VECTOR);
+        RStringVector result = RDataFactory.createStringVector(xv.getDataCopy(), RDataFactory.COMPLETE_VECTOR);
+        if (xLengthProfile.profile(result.getLength() == x.getLength())) {
+            copyAttributesNode.execute(result, x);
+        }
+        return result;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
index 178f29c4816b6bd7125b6db76099c92bba38a8c2..8fbce0e16b3edc0a9c0908402421edf9abbb3a8e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java
@@ -335,11 +335,13 @@ public abstract class Identical extends RBuiltinNode.Arg7 {
         return identicalAttr(x, y, numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment);
     }
 
+    @SuppressWarnings("unused")
     @Specialization
     protected byte doInternalIdenticalForeignObject(RInteropScalar x, RInteropScalar y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
         return RRuntime.asLogical(x == y);
     }
 
+    @SuppressWarnings("unused")
     @Specialization(guards = "areForeignObjects(x, y)")
     protected byte doInternalIdenticalForeignObject(TruffleObject x, TruffleObject y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) {
         return RRuntime.asLogical(x == y);
@@ -353,7 +355,7 @@ public abstract class Identical extends RBuiltinNode.Arg7 {
     }
 
     protected boolean areForeignObjects(TruffleObject x, TruffleObject y) {
-        return RRuntime.isForeignObject(x) && RRuntime.isForeignObject(x);
+        return RRuntime.isForeignObject(x) && RRuntime.isForeignObject(y);
     }
 
     protected boolean vectorsLists(RAbstractVector x, RAbstractVector y) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
index ef734b838ba875c3bec6bb12c9b8be9ba28554fb..ed948ca5730405fa34d8d76ab362d11111af51b7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Interactive.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -34,6 +35,7 @@ import com.oracle.truffle.r.runtime.context.RContext;
 @RBuiltin(name = "interactive", kind = PRIMITIVE, parameterNames = {}, behavior = READS_STATE)
 public abstract class Interactive extends RBuiltinNode.Arg0 {
     @Specialization
+    @TruffleBoundary
     protected byte interactive() {
         return RRuntime.asLogical(RContext.getInstance().isInteractive());
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
index 501d4a283f10f8a9cddbee1d34879ff4cc9c8de8..0977298652e9af68fe7ab8bd7a591b384d8c388f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
@@ -29,13 +30,18 @@ import java.util.Arrays;
 import java.util.function.DoublePredicate;
 import java.util.function.IntPredicate;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -43,6 +49,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -60,6 +67,10 @@ public class IsFiniteFunctions {
 
         @Child private GetDimAttributeNode getDims = GetDimAttributeNode.create();
         @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
+        @Child private GetDimNamesAttributeNode getDimNames = GetDimNamesAttributeNode.create();
+        @Child private SetDimNamesAttributeNode setDimNames;
+
+        @CompilationFinal private ConditionProfile setDimNamesProfile;
 
         @FunctionalInterface
         protected interface ComplexPredicate {
@@ -101,7 +112,7 @@ public class IsFiniteFunctions {
         protected RLogicalVector doFunConstant(RAbstractVector x, byte value) {
             byte[] b = new byte[x.getLength()];
             Arrays.fill(b, value);
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
+            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
         }
 
         protected RLogicalVector doFunDouble(RAbstractDoubleVector x, DoublePredicate fun) {
@@ -109,7 +120,7 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
+            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
         }
 
         protected RLogicalVector doFunLogical(RAbstractLogicalVector x, LogicalPredicate fun) {
@@ -117,7 +128,7 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
+            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
         }
 
         protected RLogicalVector doFunInt(RAbstractIntVector x, IntPredicate fun) {
@@ -125,7 +136,7 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
+            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
         }
 
         protected RLogicalVector doFunComplex(RAbstractComplexVector x, ComplexPredicate fun) {
@@ -133,7 +144,22 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x));
+            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
+        }
+
+        RLogicalVector transferDimNames(RLogicalVector result, RAbstractVector src) {
+            RList dimNames = getDimNames.getDimNames(src);
+            if (setDimNamesProfile == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                setDimNamesProfile = ConditionProfile.createBinaryProfile();
+            }
+            if (setDimNamesProfile.profile(dimNames != null)) {
+                if (setDimNames == null) {
+                    setDimNames = insert(SetDimNamesAttributeNode.create());
+                }
+                setDimNames.setDimNames(result, dimNames);
+            }
+            return result;
         }
     }
 
@@ -203,7 +229,7 @@ public class IsFiniteFunctions {
         }
     }
 
-    @RBuiltin(name = "is.nan", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
+    @RBuiltin(name = "is.nan", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
     public abstract static class IsNaN extends Adapter {
 
         static {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
index 166728e6642771dc131f3944539d2638e4ad2bc0..05cbcbc30395a817ec2ee19a832c87018dced4ef 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java
@@ -207,7 +207,7 @@ public abstract class IsNA extends RBuiltinNode.Arg1 {
     // fallback
     @Fallback
     protected byte isNA(Object value) {
-        warning(RError.Message.IS_NA_TO_NON_VECTOR, ((RTypedValue) value).getRType().getName());
+        warning(RError.Message.IS_NA_TO_NON_VECTOR, value instanceof RTypedValue ? ((RTypedValue) value).getRType().getName() : value);
         return RRuntime.LOGICAL_FALSE;
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
index 9152317546763b55b0cce7c33366cf254e19dfe0..aaaf1f977013dbb5645761a1b3cdfa4e037ee95f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsSingle.java
@@ -42,5 +42,4 @@ public abstract class IsSingle extends RBuiltinNode.Arg1 {
     protected Object isSingle(@SuppressWarnings("unused") Object x) {
         throw error(RError.Message.UNIMPLEMENTED_TYPE_IN_R, "single");
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
index f966c9ab3c357134731cfa5fa331f6379f3c94ce..d2a22a351d88d11fbba782f4486e29afca9b03ba 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
@@ -79,7 +80,7 @@ public class IsTypeFunctions {
         }
     }
 
-    @RBuiltin(name = "is.array", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
+    @RBuiltin(name = "is.array", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
     public abstract static class IsArray extends MissingAdapter {
 
         static {
@@ -391,7 +392,7 @@ public class IsTypeFunctions {
         }
     }
 
-    @RBuiltin(name = "is.matrix", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
+    @RBuiltin(name = "is.matrix", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
     public abstract static class IsMatrix extends MissingAdapter {
 
         private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile();
@@ -430,7 +431,7 @@ public class IsTypeFunctions {
         }
     }
 
-    @RBuiltin(name = "is.numeric", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
+    @RBuiltin(name = "is.numeric", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
     public abstract static class IsNumeric extends MissingAdapter {
 
         static {
@@ -576,14 +577,14 @@ public class IsTypeFunctions {
 
         @TruffleBoundary
         protected static RType typeFromMode(String mode) {
-            return RType.fromMode(mode);
+            return RType.fromMode(mode, true);
         }
 
         @Specialization(limit = "5", guards = "cachedMode == mode")
         protected byte isVectorCached(RAbstractVector x, @SuppressWarnings("unused") String mode,
                         @Cached("mode") @SuppressWarnings("unused") String cachedMode,
                         @Cached("typeFromMode(mode)") RType type) {
-            if (namesOnlyOrNoAttr(x) && (type == RType.Any || x.getRType() == type)) {
+            if (namesOnlyOrNoAttr(x) && (type == RType.Any || typesMatch(type, x.getRType()))) {
                 return RRuntime.LOGICAL_TRUE;
             } else {
                 return RRuntime.LOGICAL_FALSE;
@@ -600,6 +601,10 @@ public class IsTypeFunctions {
             return RRuntime.LOGICAL_FALSE;
         }
 
+        private static boolean typesMatch(RType expected, RType actual) {
+            return expected == RType.Numeric ? actual == RType.Integer || actual == RType.Double : actual == expected;
+        }
+
         private boolean namesOnlyOrNoAttr(RAbstractVector x) {
             DynamicObject attributes = x.getAttributes();
             if (attrNull.profile(attributes == null) || attrEmpty.profile(attributes.size() == 0)) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index e34c53f9cc48f0c2ea0a0498e84044607bd694ce..48044327ef71962c683e810d0c5fffc8d4a0834e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import java.lang.ref.SoftReference;
-import java.lang.ref.WeakReference;
 import java.util.function.Function;
 
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
@@ -76,7 +75,7 @@ public class LaFunctions {
 
     @RBuiltin(name = "La_version", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE)
     public abstract static class Version extends RBuiltinNode.Arg0 {
-        @Child LapackRFFI.IlaverNode ilaverNode = RFFIFactory.getRFFI().getLapackRFFI().createIlaverNode();
+        @Child LapackRFFI.IlaverNode ilaverNode = RFFIFactory.getLapackRFFI().createIlaverNode();
 
         @Specialization
         @TruffleBoundary
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
index 0e8c9f0639a7a21082dbdba6dcedeabae9d49cc4..6c7d0b0488098623f3dbabf3e319dc1b7368bb0c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNames
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.LapplyNodeGen.LapplyInternalNodeGen;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
+import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
@@ -44,12 +45,14 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
@@ -108,7 +111,7 @@ public abstract class Lapply extends RBuiltinNode.Arg2 {
         @Override
         public Object execute(VirtualFrame frame) {
             try {
-                return extractElementNode.apply(frame, FrameSlotChangeMonitor.getObject(vectorSlot, frame), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE);
+                return extractElementNode.apply(FrameSlotChangeMonitor.getObject(vectorSlot, frame), new Object[]{frame.getInt(indexSlot)}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE);
             } catch (FrameSlotTypeException e) {
                 CompilerDirectives.transferToInterpreter();
                 throw RInternalError.shouldNotReachHere("frame type mismatch in lapply");
@@ -152,11 +155,11 @@ public abstract class Lapply extends RBuiltinNode.Arg2 {
                         @Cached("createVectorSlot(frame)") FrameSlot vectorSlot,
                         @Cached("create()") RLengthNode lengthNode,
                         @Cached("createCountingProfile()") LoopConditionProfile loop,
-                        @Cached("createCallNode(vectorSlot, indexSlot)") RCallNode firstCallNode,
-                        @Cached("createCallNode(vectorSlot, indexSlot)") RCallNode callNode) {
+                        @Cached("createCallNode(vectorSlot, indexSlot)") RCallBaseNode firstCallNode,
+                        @Cached("createCallNode(vectorSlot, indexSlot)") RCallBaseNode callNode) {
             // TODO: R switches to double if x.getLength() is greater than 2^31-1
             FrameSlotChangeMonitor.setObject(frame, vectorSlot, vector);
-            int length = lengthNode.executeInteger(frame, vector);
+            int length = lengthNode.executeInteger(vector);
             Object[] result = new Object[length];
             if (length > 0) {
                 reportWork(this, length);
@@ -174,13 +177,14 @@ public abstract class Lapply extends RBuiltinNode.Arg2 {
         /**
          * Creates the {@link RCallNode} for this target and {@code varArgs}.
          */
-        protected RCallNode createCallNode(FrameSlot vectorSlot, FrameSlot indexSlot) {
+        protected RCallBaseNode createCallNode(FrameSlot vectorSlot, FrameSlot indexSlot) {
             CompilerAsserts.neverPartOfCompilation();
 
             ExtractElementInternal element = new ExtractElementInternal(vectorSlot, indexSlot);
-            ReadVariableNode readArgs = ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any);
+            RSyntaxNode readArgs = ReadVariableNode.wrap(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any));
+            RNode function = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, "FUN", false).asRNode();
 
-            return RCallNode.createCall(createCallSourceSection(), ReadVariableNode.create("FUN"), ArgumentsSignature.get(null, "..."), element, readArgs);
+            return RCallNode.createCall(createCallSourceSection(), function, ArgumentsSignature.get(null, "..."), element, readArgs);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java
index 2acf8880970607484d5a3a06dfd7ade019115ea1..6d9d8b5c16a933605bdb2876b8af61da7bd1eefd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Length.java
@@ -28,7 +28,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -36,15 +35,13 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 @RBuiltin(name = "length", kind = PRIMITIVE, dispatch = INTERNAL_GENERIC, parameterNames = {"x"}, behavior = PURE)
 public abstract class Length extends RBuiltinNode.Arg1 {
 
-    public abstract int executeInt(VirtualFrame frame, Object vector);
-
     static {
         Casts.noCasts(Length.class);
     }
 
     @Specialization
-    protected int getLength(VirtualFrame frame, Object vector,
+    protected int getLength(Object vector,
                     @Cached("create()") RLengthNode lengthNode) {
-        return lengthNode.executeInteger(frame, vector);
+        return lengthNode.executeInteger(vector);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
index 69e7498c34e5ed7a06a1bc8be2d2797ba4b76620..05138ba5cec4bfcf2f8dda63e4b38690c496e8b8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lengths.java
@@ -35,7 +35,6 @@ import java.util.Arrays;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -64,12 +63,12 @@ public abstract class Lengths extends RBuiltinNode.Arg2 {
     }
 
     @Specialization
-    protected RIntVector doList(VirtualFrame frame, RList list, boolean useNames) {
+    protected RIntVector doList(RList list, boolean useNames) {
         initLengthNode();
         int[] data = new int[list.getLength()];
         for (int i = 0; i < data.length; i++) {
             Object elem = list.getDataAt(i);
-            data[i] = lengthNode.executeInteger(frame, elem);
+            data[i] = lengthNode.executeInteger(elem);
         }
         return createResult(list, data, useNames);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
index b98566310e2335a0f3afe3a2f291415913467458..4330226b6c428309983f21f97f9d17c1c67c9926 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/License.java
@@ -30,9 +30,9 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -44,7 +44,7 @@ public abstract class License extends RBuiltinNode.Arg0 {
     @TruffleBoundary
     protected Object license() {
         try {
-            StdConnections.getStdout().writeString(RRuntime.LICENSE, true);
+            StdConnections.getStdout().writeString(RVersionNumber.LICENSE, true);
         } catch (IOException ex) {
             throw error(RError.Message.GENERIC, ex.getMessage());
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
index aae947e9a61c705ef829d0a05a3e7835369b7eac..ddbc3242d79084bada22a91dce8a1d158374d687 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LocaleFunctions.java
@@ -34,15 +34,16 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import java.nio.charset.Charset;
+import java.util.Locale;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -51,6 +52,46 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class LocaleFunctions {
 
+    enum LC {
+        COLLATE(stdDefault()),
+        CTYPE(stdDefault()),
+        MONETARY(stdDefault()),
+        NUMERIC("C"),
+        TIME(stdDefault()),
+        MESSAGES(stdDefault()),
+        PAPER(""),
+        MEASUREMENT("");
+
+        private String value;
+        private String defaultValue;
+
+        LC(String defaultValue) {
+            this.defaultValue = defaultValue;
+        }
+
+        static String stdDefault() {
+            String defLocale = Locale.getDefault().toString() + "_";
+            String defCharSet = Charset.defaultCharset().name();
+            return defLocale + defCharSet;
+        }
+
+        private String getLCEnvVar() {
+            if (value != null) {
+                return value;
+            }
+            String val = RContext.getInstance().stateREnvVars.get("LC_" + name());
+            if (val == null) {
+                return defaultValue;
+            } else {
+                return val;
+            }
+        }
+
+        private static int getLCCategory(int category) {
+            return category - 2;
+        }
+    }
+
     @RBuiltin(name = "Sys.getlocale", kind = INTERNAL, parameterNames = {"category"}, behavior = READS_STATE)
     public abstract static class GetLocale extends RBuiltinNode.Arg1 {
 
@@ -59,33 +100,33 @@ public class LocaleFunctions {
             CastsHelper.category(casts);
         }
 
+        private static final int[] ALL_CATEGORIES = new int[]{3, 2, 4, 5, 6, 7, 8, 9};
+
         @Specialization
         @TruffleBoundary
         protected Object getLocale(int category) {
-            // TODO implement all: for now just return not available (NULL)
-            switch (category) {
-                case 3: // "LC_CTYPE",
-                    return RDataFactory.createStringVector(Charset.defaultCharset().name());
-                case 1: // "LC_ALL"
-                    break;
-                case 2: // "LC_COLLATE"
-                    break;
-                case 4: // "LC_MONETARY"
-                    break;
-                case 5: // "LC_NUMERIC"
-                    break;
-                case 6: // "LC_TIME"
-                    break;
-                case 7: // "LC_MESSAGES"
-                    break;
-                case 8: // "LC_PAPER"
-                    return RDataFactory.createStringVectorFromScalar("");
-                case 9: // "LC_MEASUREMENT"
-                    break;
-                default:
-                    throw RInternalError.shouldNotReachHere();
+            return RDataFactory.createStringVector(getLocaleData(category));
+        }
+
+        protected String getLocaleData(int category) {
+            String data = "";
+            if (category == 1) {
+                // "LC_ALL"
+                StringBuilder sb = new StringBuilder();
+                for (int i = 0; i < ALL_CATEGORIES.length; i++) {
+                    String d = getLocaleData(ALL_CATEGORIES[i]);
+                    if (d.length() > 0) {
+                        sb.append(d);
+                        if (i != ALL_CATEGORIES.length - 1) {
+                            sb.append('/');
+                        }
+                    }
+                }
+                data = sb.toString();
+            } else {
+                data = LC.values()[LC.getLCCategory(category)].getLCEnvVar();
             }
-            return RNull.instance;
+            return data;
         }
     }
 
@@ -100,8 +141,8 @@ public class LocaleFunctions {
 
         @Specialization
         @TruffleBoundary
-        protected Object setLocale(@SuppressWarnings("unused") int category, String locale) {
-            // TODO implement properly!!
+        protected Object setLocale(int category, String locale) {
+            LC.values()[LC.getLCCategory(category)].value = locale;
             return locale;
         }
     }
@@ -186,4 +227,8 @@ public class LocaleFunctions {
             casts.arg("category").mustBe(numericValue(), INVALID_ARGUMENT, "category").asIntegerVector().findFirst();
         }
     }
+
+    public static void main(String[] args) {
+        System.out.println(Locale.getDefault());
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index 4a3a38d7134f8499c65c3460719efd9cdac0439e..09bde8d617b02030f4f908522f51447acb1d3173 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -42,7 +42,6 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNames
 import com.oracle.truffle.r.nodes.binary.BinaryMapArithmeticFunctionNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
@@ -57,6 +56,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
@@ -348,19 +348,10 @@ public class LogFunctions {
     }
 
     @RBuiltin(name = "log10", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Log10 extends UnaryArithmeticBuiltinNode {
-
-        public Log10() {
-            super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
-        }
+    public static final class Log10 extends UnaryArithmetic {
 
         private static final double LOG_10 = Math.log(10);
 
-        static {
-            Casts casts = new Casts(Log10.class);
-            casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
-        }
-
         @Override
         public double op(double op) {
             return Math.log10(op);
@@ -375,19 +366,10 @@ public class LogFunctions {
     }
 
     @RBuiltin(name = "log2", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Log2 extends UnaryArithmeticBuiltinNode {
-
-        public Log2() {
-            super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
-        }
+    public static final class Log2 extends UnaryArithmetic {
 
         private static final double LOG_2 = Math.log(2);
 
-        static {
-            Casts casts = new Casts(Log2.class);
-            casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
-        }
-
         @Override
         public double op(double op) {
             return Math.log(op) / LOG_2;
@@ -402,30 +384,11 @@ public class LogFunctions {
     }
 
     @RBuiltin(name = "log1p", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Log1p extends UnaryArithmeticBuiltinNode {
-
-        public Log1p() {
-            super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
-        }
-
-        static {
-            Casts casts = new Casts(Log1p.class);
-            casts.arg("x").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
-        }
-
-        @Override
-        public int op(byte op) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public int op(int op) {
-            throw new UnsupportedOperationException();
-        }
+    public static final class Log1p extends UnaryArithmetic {
 
         @Override
         public double op(double op) {
-            return Math.log(1 + op);
+            return Math.log1p(op);
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
index e649410a8914d9aa6c9bffc3cd69e3e41c9960b0..dc3a03b8f5389ea8e3ec3e811839654de10582ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mapply.java
@@ -28,24 +28,28 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerAsserts;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.MapplyNodeGen.MapplyInternalNodeGen;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
+import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.nodes.function.call.RExplicitCallNode;
 import com.oracle.truffle.r.runtime.AnonymousFrameVariable;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -75,7 +79,7 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
     }
 
     protected static final class ElementNode extends Node {
-        @Child private Length lengthNode;
+        @Child private RLengthNode lengthNode;
         @Child private ExtractVectorNode extractNode;
         @Child private WriteVariableNode writeVectorElementNode;
         private final String vectorElementName;
@@ -84,7 +88,7 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
         private ElementNode(String vectorElementName, String argName) {
             // the name is a hack to treat ReadVariableNode-s as syntax nodes
             this.vectorElementName = "*" + AnonymousFrameVariable.create(vectorElementName);
-            this.lengthNode = insert(LengthNodeGen.create());
+            this.lengthNode = insert(RLengthNode.create());
             this.extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false));
             this.writeVectorElementNode = insert(WriteVariableNode.createAnonymous(this.vectorElementName, Mode.REGULAR, null));
             this.argName = argName;
@@ -117,52 +121,74 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
             }
         }
 
-        @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
+        @Child private GetNamesAttributeNode getNamesDots = GetNamesAttributeNode.create();
+        @Child private GetNamesAttributeNode getNamesMoreArgs = GetNamesAttributeNode.create();
+
+        private final BranchProfile nonPerfectMatch = BranchProfile.create();
 
         public abstract Object[] execute(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector additionalArguments);
 
-        private static Object getVecElement(VirtualFrame frame, RAbstractListVector dots, int i, int listIndex, int[] lengths, ExtractVectorNode extractNode) {
-            return extractNode.apply(frame, dots.getDataAt(listIndex), new Object[]{i % lengths[listIndex] + 1}, RLogical.TRUE, RLogical.TRUE);
+        private static Object getVecElement(RAbstractListVector dots, int i, int listIndex, int[] lengths, ExtractVectorNode extractNode) {
+            return extractNode.apply(dots.getDataAt(listIndex), new Object[]{i % lengths[listIndex] + 1}, RLogical.TRUE, RLogical.TRUE);
         }
 
-        @SuppressWarnings("unused")
-        @Specialization(limit = "5", guards = {"dots.getLength() == cachedDots.getLength()",
-                        "moreArgs.getLength() == cachedMoreArgs.getLength()", "sameNames(dots, cachedDots)",
-                        "sameNames(moreArgs, cachedMoreArgs)"})
+        @Specialization(limit = "5", guards = {"dots.getLength() == dotsLength", "moreArgs.getLength() == moreArgsLength",
+                        "sameNames(dots, cachedDotsNames)", "sameNames(moreArgs, cachedMoreArgsNames)"})
         protected Object[] cachedMApply(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector moreArgs,
-                        @Cached("dots") RAbstractListVector cachedDots,
-                        @Cached("moreArgs") RAbstractListVector cachedMoreArgs,
-                        @Cached("createElementNodeArray(cachedDots, cachedMoreArgs)") ElementNode[] cachedElementNodeArray,
-                        @Cached("createCallNode(cachedElementNodeArray)") RCallNode callNode) {
-            int dotsLength = dots.getLength();
-            int moreArgsLength = moreArgs.getLength();
+                        @Cached("dots.getLength()") int dotsLength,
+                        @Cached("moreArgs.getLength()") int moreArgsLength,
+                        @SuppressWarnings("unused") @Cached(value = "extractNames(dots)", dimensions = 1) String[] cachedDotsNames,
+                        @SuppressWarnings("unused") @Cached(value = "extractNames(moreArgs)", dimensions = 1) String[] cachedMoreArgsNames,
+                        @Cached("createElementNodeArray(dotsLength, moreArgsLength, cachedDotsNames, cachedMoreArgsNames)") ElementNode[] cachedElementNodeArray,
+                        @Cached("createCallNode(cachedElementNodeArray)") RCallBaseNode callNode) {
             int[] lengths = new int[dotsLength];
-            int maxLength = -1;
-            for (int i = 0; i < dotsLength; i++) {
-                int length = cachedElementNodeArray[i].lengthNode.executeInt(frame, dots.getDataAt(i));
-                if (length > maxLength) {
-                    maxLength = length;
-                }
-                lengths[i] = length;
-            }
-            for (int listIndex = dotsLength; listIndex < dotsLength + moreArgsLength; listIndex++) {
-                // store additional arguments
-                cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame,
-                                moreArgs.getDataAt(listIndex - dotsLength));
-            }
+            int maxLength = getDotsLengths(dots, dotsLength, cachedElementNodeArray, lengths);
+            storeAdditionalArguments(frame, moreArgs, dotsLength, moreArgsLength, cachedElementNodeArray);
             Object[] result = new Object[maxLength];
             for (int i = 0; i < maxLength; i++) {
                 /* Evaluate and store the arguments */
-                for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
-                    Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, cachedElementNodeArray[listIndex].extractNode);
-                    cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, vecElement);
-                }
+                prepareElements(frame, dots, dotsLength, cachedElementNodeArray, lengths, i);
                 /* Now call the function */
                 result[i] = callNode.execute(frame, function);
             }
             return result;
         }
 
+        @ExplodeLoop
+        private static void prepareElements(VirtualFrame frame, RAbstractListVector dots, int dotsLength, ElementNode[] cachedElementNodeArray, int[] lengths, int i) {
+            for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
+                Object vecElement = getVecElement(dots, i, listIndex, lengths, cachedElementNodeArray[listIndex].extractNode);
+                cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, vecElement);
+            }
+        }
+
+        @ExplodeLoop
+        private static void storeAdditionalArguments(VirtualFrame frame, RAbstractListVector moreArgs, int dotsLength, int moreArgsLength, ElementNode[] cachedElementNodeArray) {
+            for (int listIndex = dotsLength; listIndex < dotsLength + moreArgsLength; listIndex++) {
+                // store additional arguments
+                cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, moreArgs.getDataAt(listIndex - dotsLength));
+            }
+        }
+
+        @ExplodeLoop
+        private static int getDotsLengths(RAbstractListVector dots, int dotsLength, ElementNode[] cachedElementNodeArray, int[] lengths) {
+            int maxLength = -1;
+            for (int i = 0; i < dotsLength; i++) {
+                int length = cachedElementNodeArray[i].lengthNode.executeInteger(dots.getDataAt(i));
+                if (length > maxLength) {
+                    maxLength = length;
+                }
+                lengths[i] = length;
+            }
+            return maxLength;
+        }
+
+        protected static String[] extractNames(RAbstractListVector list) {
+            CompilerAsserts.neverPartOfCompilation();
+            RStringVector names = list.getNames();
+            return names == null ? null : names.getDataCopy();
+        }
+
         @Specialization(replaces = "cachedMApply")
         protected Object[] mApply(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector moreArgs,
                         @Cached("create()") RLengthNode lengthNode,
@@ -173,7 +199,7 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
             int[] lengths = new int[dotsLength];
             int maxLength = -1;
             for (int i = 0; i < dotsLength; i++) {
-                int length = lengthNode.executeInteger(frame, dots.getDataAt(i));
+                int length = lengthNode.executeInteger(dots.getDataAt(i));
                 if (length > maxLength) {
                     maxLength = length;
                 }
@@ -181,13 +207,13 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
             }
             Object[] values = new Object[dotsLength + moreArgsLength];
             String[] names = new String[dotsLength + moreArgsLength];
-            RStringVector dotsNames = getNames.getNames(dots);
+            RStringVector dotsNames = getNamesDots.getNames(dots);
             if (dotsNames != null) {
                 for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
                     names[listIndex] = dotsNames.getDataAt(listIndex).isEmpty() ? null : dotsNames.getDataAt(listIndex);
                 }
             }
-            RStringVector moreArgsNames = getNames.getNames(moreArgs);
+            RStringVector moreArgsNames = getNamesMoreArgs.getNames(moreArgs);
             for (int listIndex = dotsLength; listIndex < dotsLength + moreArgsLength; listIndex++) {
                 values[listIndex] = moreArgs.getDataAt(listIndex - dotsLength);
                 names[listIndex] = moreArgsNames == null ? null : (moreArgsNames.getDataAt(listIndex - dotsLength).isEmpty() ? null : moreArgsNames.getDataAt(listIndex - dotsLength));
@@ -197,7 +223,7 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
             for (int i = 0; i < maxLength; i++) {
                 /* Evaluate and store the arguments */
                 for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
-                    Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, extractNode);
+                    Object vecElement = getVecElement(dots, i, listIndex, lengths, extractNode);
                     values[listIndex] = vecElement;
                 }
                 /* Now call the function */
@@ -209,29 +235,27 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
         /**
          * Creates the {@link RCallNode} for this target.
          */
-        protected RCallNode createCallNode(ElementNode[] elementNodeArray) {
+        protected RCallBaseNode createCallNode(ElementNode[] elementNodeArray) {
             CompilerAsserts.neverPartOfCompilation();
             RSyntaxNode[] syntaxNodes = new RSyntaxNode[elementNodeArray.length];
             String[] names = new String[elementNodeArray.length];
             for (int i = 0; i < syntaxNodes.length; i++) {
-                syntaxNodes[i] = ReadVariableNode.create(elementNodeArray[i].vectorElementName).asRSyntaxNode();
+                syntaxNodes[i] = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, elementNodeArray[i].vectorElementName, false);
                 names[i] = elementNodeArray[i].argName;
             }
             // Errors can be thrown from the modified call so a SourceSection is required
             return RCallNode.createCall(Lapply.createCallSourceSection(), null, ArgumentsSignature.get(names), syntaxNodes);
         }
 
-        protected ElementNode[] createElementNodeArray(RAbstractListVector dots, RAbstractListVector moreArgs) {
-            int length = dots.getLength() + moreArgs.getLength();
+        protected ElementNode[] createElementNodeArray(int dotsLength, int moreArgsLength, String[] cachedDotsNames, String[] cachedMoreArgsNames) {
+            int length = dotsLength + moreArgsLength;
             ElementNode[] elementNodes = new ElementNode[length];
-            RStringVector dotsNames = getNames.getNames(dots);
-            for (int i = 0; i < dots.getLength(); i++) {
-                elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1), dotsNames == null ? null : (dotsNames.getDataAt(i).isEmpty() ? null : dotsNames.getDataAt(i))));
+            for (int i = 0; i < dotsLength; i++) {
+                elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1), cachedDotsNames == null ? null : (cachedDotsNames[i].isEmpty() ? null : cachedDotsNames[i])));
             }
-            RStringVector moreArgsNames = getNames.getNames(moreArgs);
-            for (int i = dots.getLength(); i < dots.getLength() + moreArgs.getLength(); i++) {
-                elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1),
-                                moreArgsNames == null ? null : moreArgsNames.getDataAt(i - dots.getLength()).isEmpty() ? null : moreArgsNames.getDataAt(i - dots.getLength())));
+            for (int i = 0; i < moreArgsLength; i++) {
+                elementNodes[i + dotsLength] = insert(
+                                new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1 + dotsLength), cachedMoreArgsNames == null ? null : cachedMoreArgsNames[i].isEmpty() ? null : cachedMoreArgsNames[i]));
             }
             return elementNodes;
         }
@@ -240,29 +264,34 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
             return ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
         }
 
-        protected boolean sameNames(RAbstractListVector list, RAbstractListVector cachedList) {
-            RStringVector listNames = getNames.getNames(list);
-            RStringVector cachedListNames = getNames.getNames(cachedList);
-            if (listNames == null && cachedListNames == null) {
+        protected boolean sameNames(RAbstractListVector list, String[] cachedNames) {
+            RStringVector listNames = getNamesDots.getNames(list);
+            if (listNames == null && cachedNames == null) {
                 return true;
-            } else if (listNames == null || cachedListNames == null) {
+            } else if (listNames == null || cachedNames == null) {
                 return false;
             } else {
-
-                for (int i = 0; i < list.getLength(); i++) {
+                for (int i = 0; i < cachedNames.length; i++) {
                     String name = listNames.getDataAt(i);
-                    String cachedName = cachedListNames.getDataAt(i);
-
+                    String cachedName = cachedNames[i];
                     if (name == cachedName) {
                         continue;
-                    } else if (name == null || cachedName == null) {
-                        return false;
-                    } else if (!(name.equals(cachedName))) {
-                        return false;
+                    } else {
+                        nonPerfectMatch.enter();
+                        if (name == null || cachedName == null) {
+                            return false;
+                        } else if (!equals(name, cachedName)) {
+                            return false;
+                        }
                     }
                 }
                 return true;
             }
         }
+
+        @TruffleBoundary
+        private static boolean equals(String name, String cachedName) {
+            return name.equals(cachedName);
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
index 00ba7a002e1d50f9bdce1032ff260260630b6d7d..149dcdb68df06499c12812db715ae17b15e5fb00 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java
@@ -32,6 +32,7 @@ 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.dsl.TypeSystemReference;
+import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
@@ -103,7 +104,7 @@ public abstract class MatchFun extends RBuiltinNode.Arg2 {
         }
 
         protected static ReadVariableNode createLookup(String name, boolean descend) {
-            return descend ? ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, name) : ReadVariableNode.create(RSyntaxNode.INTERNAL, name, false);
+            return descend ? ReadVariableNode.createFunctionLookup(name) : ReadVariableNode.create(name);
         }
 
         protected static String firstString(RAbstractStringVector vec) {
@@ -124,9 +125,10 @@ public abstract class MatchFun extends RBuiltinNode.Arg2 {
         }
 
         @SuppressWarnings("unused")
-        @Specialization(limit = "LIMIT", guards = {"funValue.getLength() == 1", "funValue.getDataAt(0) == cachedName"})
+        @Specialization(limit = "LIMIT", guards = {"funValue.getLength() == 1", "funValue.getDataAt(0) == cachedName", "getCallerFrameDescriptor(frame) == cachedCallerFrameDescriptor"})
         protected RFunction matchfunCached(VirtualFrame frame, RPromise funPromise, RAbstractStringVector funValue, boolean descend,
                         @Cached("firstString(funValue)") String cachedName,
+                        @Cached("getCallerFrameDescriptor(frame)") FrameDescriptor cachedCallerFrameDescriptor,
                         @Cached("createLookup(cachedName, descend)") ReadVariableNode lookup) {
             return checkResult(lookup.execute(frame, getCallerFrame.execute(frame)));
         }
@@ -137,9 +139,10 @@ public abstract class MatchFun extends RBuiltinNode.Arg2 {
         }
 
         @SuppressWarnings("unused")
-        @Specialization(limit = "LIMIT", guards = {"funValue.getName() == cachedName"})
+        @Specialization(limit = "LIMIT", guards = {"funValue.getName() == cachedName", "getCallerFrameDescriptor(frame) == cachedCallerFrameDescriptor"})
         protected RFunction matchfunCached(VirtualFrame frame, RPromise funPromise, RSymbol funValue, boolean descend,
                         @Cached("firstString(funValue)") String cachedName,
+                        @Cached("getCallerFrameDescriptor(frame)") FrameDescriptor cachedCallerFrameDescriptor,
                         @Cached("createLookup(cachedName, descend)") ReadVariableNode lookup) {
             return checkResult(lookup.execute(frame, getCallerFrame.execute(frame)));
         }
@@ -198,5 +201,9 @@ public abstract class MatchFun extends RBuiltinNode.Arg2 {
                 return FrameSlotChangeMonitor.getValue(slot, frame);
             }
         }
+
+        protected FrameDescriptor getCallerFrameDescriptor(VirtualFrame frame) {
+            return getCallerFrame.execute(frame).getFrameDescriptor();
+        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
index 6c3556db61b99058eb0ce292cdc5ea1522b12b79..ce41444d9eea5376957d227c1d7c315b486fc9bd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Max.java
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RDispatch.SUMMARY_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUMMARY;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
@@ -39,11 +39,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
-@RBuiltin(name = "max", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
+@RBuiltin(name = "max", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE_SUMMARY)
 public abstract class Max extends RBuiltinNode.Arg2 {
 
     private static final ReduceSemantics semantics = new ReduceSemantics(RRuntime.INT_MIN_VALUE, Double.NEGATIVE_INFINITY, false, RError.Message.NO_NONMISSING_MAX,
-                    RError.Message.NO_NONMISSING_MAX_NA, false, true);
+                    RError.Message.NO_NONMISSING_MAX_NA, null, false, true, true);
 
     @Child private UnaryArithmeticReduceNode reduce = UnaryArithmeticReduceNodeGen.create(semantics, BinaryArithmetic.MAX);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java
index 3cd1cf689cf244c73adb9abffd2365191b523a40..53a91f171580ab9796ecd04558e257dbee5a5ac3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java
@@ -23,7 +23,7 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUMMARY;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.dsl.Specialization;
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
-@RBuiltin(name = "mean", kind = INTERNAL, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
+@RBuiltin(name = "mean", kind = INTERNAL, parameterNames = {"x"}, dispatch = INTERNAL_GENERIC, behavior = PURE_SUMMARY)
 public abstract class Mean extends RBuiltinNode.Arg1 {
 
     private final BranchProfile emptyProfile = BranchProfile.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
index 1f14fbafc416a9542bbf07fbae9a57a5055ff25b..7be389e2d1f9a0d5c6dd8173392cb9134c48f45f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Min.java
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RDispatch.SUMMARY_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUMMARY;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
@@ -39,11 +39,11 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 
-@RBuiltin(name = "min", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
+@RBuiltin(name = "min", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE_SUMMARY)
 public abstract class Min extends RBuiltinNode.Arg2 {
 
     private static final ReduceSemantics semantics = new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN,
-                    RError.Message.NO_NONMISSING_MIN_NA, false, true);
+                    RError.Message.NO_NONMISSING_MIN_NA, null, false, true, true);
 
     @Child private UnaryArithmeticReduceNode reduce = UnaryArithmeticReduceNodeGen.create(semantics, BinaryArithmetic.MIN);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
index 741fd707d609a55def54d55a22ea9f646e9fb288..39f4f5109ec5f1b07d9a15b321e3f2296d0d3fd1 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NZChar.java
@@ -75,5 +75,4 @@ public abstract class NZChar extends RBuiltinNode.Arg2 {
     protected RLogicalVector rev(@SuppressWarnings("unused") RMissing value, @SuppressWarnings("unused") boolean keepNA) {
         throw RError.error(this, RError.Message.ARGUMENT_NOT_MATCH, "keepNA", "x");
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
index e90f8a20c60ff347e62ae27981b65baf4a78a082..cc09614f38e9b177055a10306df953c5685e74c0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Names.java
@@ -83,8 +83,7 @@ public abstract class Names extends RBuiltinNode.Arg1 {
                     @Cached("KEYS.createNode()") Node keysNode,
                     @Cached("READ.createNode()") Node readNode,
                     @Cached("IS_BOXED.createNode()") Node isBoxedNode,
-                    @Cached("UNBOX.createNode()") Node unboxNode,
-                    @Cached("createExecute(0).createNode()") Node callNode) {
+                    @Cached("UNBOX.createNode()") Node unboxNode) {
 
         try {
             String[] names;
@@ -97,8 +96,7 @@ public abstract class Names extends RBuiltinNode.Arg1 {
             String[] staticNames = new String[0];
             try {
                 if (JavaInterop.isJavaObject(Object.class, obj)) {
-                    TruffleObject clazz = JavaInterop.toJavaClass(obj);
-                    staticNames = readKeys(keysNode, clazz, getSizeNode, readNode, isBoxedNode, unboxNode);
+                    staticNames = readKeys(keysNode, toJavaClass(obj), getSizeNode, readNode, isBoxedNode, unboxNode);
                 }
             } catch (UnknownIdentifierException | NoSuchFieldError | UnsupportedMessageException e) {
                 // because it is a class ... ?
@@ -115,7 +113,12 @@ public abstract class Names extends RBuiltinNode.Arg1 {
         }
     }
 
-    private String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode, Node isBoxedNode, Node unboxNode)
+    @TruffleBoundary
+    private static TruffleObject toJavaClass(TruffleObject obj) {
+        return JavaInterop.toJavaClass(obj);
+    }
+
+    private static String[] readKeys(Node keysNode, TruffleObject obj, Node getSizeNode, Node readNode, Node isBoxedNode, Node unboxNode)
                     throws UnknownIdentifierException, InteropException, UnsupportedMessageException {
         TruffleObject keys = (TruffleObject) ForeignAccess.send(keysNode, obj);
         if (keys != null) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
index c540de96876e1e0f56e5c95b70328fa1988ebc5d..23b64ce4b665737c930521e53549ffc9c3f67a71 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NumericalFunctions.java
@@ -22,58 +22,32 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.runtime.RDispatch.COMPLEX_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 
 public class NumericalFunctions {
 
-    /**
-     * This node is only a workaround that makes the annotation processor process the other inner
-     * node classes. These classes would be ignored otherwise, since they do not contain any
-     * specialization, which would trigger the code generation performed by the annotation
-     * processor.
-     */
-    public abstract static class DummyNode extends RBuiltinNode.Arg1 {
-
-        @Specialization
-        protected Object dummySpec(@SuppressWarnings("unused") Object value) {
-            return null;
-        }
-    }
-
     @RBuiltin(name = "abs", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Abs extends UnaryArithmeticBuiltinNode {
+    public static final class Abs extends UnaryArithmetic {
 
-        public Abs() {
-            super(RType.Integer, RError.Message.NON_NUMERIC_MATH, null);
-        }
-
-        static {
-            Casts casts = new Casts(Abs.class);
-            casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(numericValue().or(complexValue()));
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            return argumentType == RType.Complex ? RType.Double : argumentType;
         }
 
         @Override
-        public RType calculateResultType(RType argumentType) {
-            switch (argumentType) {
-                case Complex:
-                    return RType.Double;
-                default:
-                    return super.calculateResultType(argumentType);
-            }
+        public RType getMinPrecedence() {
+            return RType.Integer;
         }
 
         @Override
@@ -98,25 +72,16 @@ public class NumericalFunctions {
     }
 
     @RBuiltin(name = "Re", kind = PRIMITIVE, parameterNames = {"z"}, dispatch = COMPLEX_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Re extends UnaryArithmeticBuiltinNode {
-
-        public Re() {
-            super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
-        }
+    public static final class Re extends UnaryArithmetic {
 
-        static {
-            Casts casts = new Casts(Re.class);
-            casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            return argumentType == RType.Complex ? RType.Double : argumentType;
         }
 
         @Override
-        public RType calculateResultType(RType argumentType) {
-            switch (argumentType) {
-                case Complex:
-                    return RType.Double;
-                default:
-                    return super.calculateResultType(argumentType);
-            }
+        public Message getArgumentError() {
+            return RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION;
         }
 
         @Override
@@ -141,25 +106,16 @@ public class NumericalFunctions {
     }
 
     @RBuiltin(name = "Im", kind = PRIMITIVE, parameterNames = {"z"}, dispatch = COMPLEX_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Im extends UnaryArithmeticBuiltinNode {
+    public static final class Im extends UnaryArithmetic {
 
-        public Im() {
-            super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
-        }
-
-        static {
-            Casts casts = new Casts(Im.class);
-            casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            return argumentType == RType.Complex ? RType.Double : argumentType;
         }
 
         @Override
-        public RType calculateResultType(RType argumentType) {
-            switch (argumentType) {
-                case Complex:
-                    return RType.Double;
-                default:
-                    return super.calculateResultType(argumentType);
-            }
+        public Message getArgumentError() {
+            return RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION;
         }
 
         @Override
@@ -184,15 +140,11 @@ public class NumericalFunctions {
     }
 
     @RBuiltin(name = "Conj", kind = PRIMITIVE, parameterNames = {"z"}, dispatch = COMPLEX_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Conj extends UnaryArithmeticBuiltinNode {
-
-        public Conj() {
-            super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
-        }
+    public static final class Conj extends UnaryArithmetic {
 
-        static {
-            Casts casts = new Casts(Conj.class);
-            casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
+        @Override
+        public Message getArgumentError() {
+            return RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION;
         }
 
         @Override
@@ -217,25 +169,16 @@ public class NumericalFunctions {
     }
 
     @RBuiltin(name = "Mod", kind = PRIMITIVE, parameterNames = {"z"}, dispatch = COMPLEX_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Mod extends UnaryArithmeticBuiltinNode {
-
-        public Mod() {
-            super(RType.Double, RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION, null);
-        }
+    public static final class Mod extends UnaryArithmetic {
 
-        static {
-            Casts casts = new Casts(Mod.class);
-            casts.arg("z").defaultError(RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION).mustBe(numericValue().or(complexValue()));
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            return argumentType == RType.Complex ? RType.Double : argumentType;
         }
 
         @Override
-        public RType calculateResultType(RType argumentType) {
-            switch (argumentType) {
-                case Complex:
-                    return RType.Double;
-                default:
-                    return super.calculateResultType(argumentType);
-            }
+        public Message getArgumentError() {
+            return RError.Message.NON_NUMERIC_ARGUMENT_FUNCTION;
         }
 
         @Override
@@ -259,18 +202,42 @@ public class NumericalFunctions {
         }
     }
 
-    @RBuiltin(name = "sign", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Sign extends UnaryArithmeticBuiltinNode {
+    @RBuiltin(name = "Arg", kind = PRIMITIVE, parameterNames = {"z"}, dispatch = COMPLEX_GROUP_GENERIC, behavior = PURE)
+    public static final class Arg extends UnaryArithmetic {
+
+        @Override
+        public RType calculateResultType(RType argumentType) {
+            return argumentType == RType.Complex ? RType.Double : argumentType;
+        }
+
+        @Override
+        public int op(byte op) {
+            return 0;
+        }
 
-        public Sign() {
-            super(RType.Double, RError.Message.NON_NUMERIC_MATH, null);
+        @Override
+        public int op(int op) {
+            return op;
         }
 
-        static {
-            Casts casts = new Casts(Sign.class);
-            casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue());
+        @Override
+        public double op(double op) {
+            if (op >= 0) {
+                return 0;
+            } else {
+                return Math.PI;
+            }
         }
 
+        @Override
+        public double opd(double re, double im) {
+            return Math.atan2(im, re);
+        }
+    }
+
+    @RBuiltin(name = "sign", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
+    public static final class Sign extends UnaryArithmetic {
+
         @Override
         public int op(byte op) {
             return op == RRuntime.LOGICAL_TRUE ? 1 : 0;
@@ -285,19 +252,15 @@ public class NumericalFunctions {
         public double op(double op) {
             return Math.signum(op);
         }
-    }
 
-    @RBuiltin(name = "sqrt", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Sqrt extends UnaryArithmeticBuiltinNode {
-
-        public Sqrt() {
-            super(RType.Double, RError.Message.NON_NUMERIC_MATH, null);
+        @Override
+        public RComplex op(double re, double im) {
+            throw error(Message.UNIMPLEMENTED_COMPLEX_FUN);
         }
+    }
 
-        static {
-            Casts casts = new Casts(Sqrt.class);
-            casts.arg("x").defaultError(RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue().or(complexValue()));
-        }
+    @RBuiltin(name = "sqrt", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
+    public static final class Sqrt extends UnaryArithmetic {
 
         @Override
         public int op(byte op) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OldClass.java
similarity index 67%
rename from com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
rename to com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OldClass.java
index a0e3caa5659487e3fd021c13191e4756a508ce73..14fa5968ae185f36753702ceeff1ba52718fdb24 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OldClass.java
@@ -25,50 +25,37 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RSymbol;
-import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 
 @RBuiltin(name = "oldClass", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
-public abstract class GetOldClass extends RBuiltinNode.Arg1 {
+public abstract class OldClass extends RBuiltinNode.Arg1 {
 
     private final ConditionProfile isObjectProfile = ConditionProfile.createBinaryProfile();
     @Child private GetClassAttributeNode getClassNode = GetClassAttributeNode.create();
 
     static {
-        Casts.noCasts(GetOldClass.class);
+        Casts.noCasts(OldClass.class);
     }
 
     @Specialization
-    protected Object getOldClass(RAbstractContainer arg,
-                    @Cached("createWithImplicit()") ClassHierarchyNode hierarchy) {
-        if (isObjectProfile.profile(getClassNode.isObject(arg))) {
-            return hierarchy.execute(arg);
+    protected Object getOldClass(RAttributable arg) {
+        Object clazz = getClassNode.execute(arg);
+        if (isObjectProfile.profile(clazz != null)) {
+            return clazz;
         } else {
             return RNull.instance;
         }
     }
 
-    @Specialization
-    protected Object getOldClass(@SuppressWarnings("unused") RSymbol arg) {
-        return RNull.instance;
-    }
-
-    @Specialization
-    protected Object getOldClass(@SuppressWarnings("unused") RFunction arg) {
-        return RNull.instance;
-    }
-
-    @Specialization
-    protected Object getOldClass(@SuppressWarnings("unused") RNull arg) {
+    @Fallback
+    protected Object getOldClass(@SuppressWarnings("unused") Object arg) {
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
index 3f472f67aa7dc31602afc451a53ba2d9e38f1da6..39096d59aa6f3d7f194d358ba94ad1ab34e0af76 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OnExit.java
@@ -77,19 +77,19 @@ public abstract class OnExit extends RBuiltinNode.Arg2 {
         // the empty (RNull.instance) expression is used to clear on.exit
         if (emptyPromiseProfile.profile(expr.isDefaultArgument())) {
             assert expr.getRep() instanceof ConstantNode : "only ConstantNode expected for defaulted promise";
-            frame.setObject(onExitSlot, RDataFactory.createPairList());
+            FrameSlotChangeMonitor.setObject(frame, onExitSlot, RDataFactory.createPairList());
         } else {
             assert !expr.isEvaluated() : "promise cannot already be evaluated";
             Object value;
             try {
-                value = frame.getObject(onExitSlot);
+                value = FrameSlotChangeMonitor.getObject(onExitSlot, frame);
             } catch (FrameSlotTypeException e) {
                 throw RInternalError.shouldNotReachHere();
             }
             RPairList list;
             if (newProfile.profile(value == null)) {
                 // initialize the list of exit handlers
-                frame.setObject(onExitSlot, list = RDataFactory.createPairList());
+                FrameSlotChangeMonitor.setObject(frame, onExitSlot, list = RDataFactory.createPairList());
             } else {
                 list = (RPairList) value;
                 if (addProfile.profile(!add)) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
index f79c0a4863229b0c2c95824a014272c403e26b2d..27deb99948450b5b52e7f1084238b4ba342e1c98 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/OptionsFunctions.java
@@ -136,7 +136,7 @@ public class OptionsFunctions {
                         if (nn instanceof RStringVector) {
                             thisListnames = (RStringVector) nn;
                         } else {
-                            throw RInternalError.shouldNotReachHere();
+                            throw RError.error(RError.SHOW_CALLER, Message.LIST_NO_VALID_NAMES);
                         }
                         Object[] listData = new Object[list.getLength()];
                         String[] listNames = new String[listData.length];
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
index 7f2f5708175ad714b72a416c566ffb7528aa5840..4dd253311b7c9e9d38b53349e1821f391d4225f7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PMinMax.java
@@ -341,28 +341,26 @@ public abstract class PMinMax extends RBuiltinNode.Arg2 {
     public abstract static class PMax extends PMinMax {
 
         public PMax() {
-            super(new ReduceSemantics(RRuntime.INT_MIN_VALUE, Double.NEGATIVE_INFINITY, false, RError.Message.NO_NONMISSING_MAX, RError.Message.NO_NONMISSING_MAX_NA, false, true),
+            super(new ReduceSemantics(RRuntime.INT_MIN_VALUE, Double.NEGATIVE_INFINITY, false, RError.Message.NO_NONMISSING_MAX, RError.Message.NO_NONMISSING_MAX_NA, null, false, true, true),
                             BinaryArithmetic.MAX);
         }
 
         static {
             createCasts(PMax.class);
         }
-
     }
 
     @RBuiltin(name = "pmin", kind = INTERNAL, parameterNames = {"na.rm", "..."}, behavior = PURE)
     public abstract static class PMin extends PMinMax {
 
         public PMin() {
-            super(new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN, RError.Message.NO_NONMISSING_MIN_NA, false, true),
+            super(new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN, RError.Message.NO_NONMISSING_MIN_NA, null, false, true, true),
                             BinaryArithmetic.MIN);
         }
 
         static {
             createCasts(PMin.class);
         }
-
     }
 
     protected boolean isIntegerPrecedence(RArgsValuesAndNames args) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
index d39308b1ce11a881d5752fedf1fc500ba68ae365..5d38f5473f74d870b7c4c5d4ca30384b1758c9b2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Parse.java
@@ -112,7 +112,7 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
 
     @TruffleBoundary
     @Specialization
-    protected Object parse(int conn, int n, @SuppressWarnings("unused") RNull text, String prompt, Object srcFile, String encoding) {
+    protected RExpression parse(int conn, int n, @SuppressWarnings("unused") RNull text, String prompt, Object srcFile, String encoding) {
         String[] lines;
         RConnection connection = RConnection.fromIndex(conn);
         if (connection == StdConnections.getStdin()) {
@@ -128,12 +128,12 @@ public abstract class Parse extends RBuiltinNode.Arg6 {
 
     @TruffleBoundary
     @Specialization
-    protected Object parse(int conn, int n, RAbstractStringVector text, String prompt, Object srcFile, String encoding) {
+    protected RExpression parse(int conn, int n, RAbstractStringVector text, String prompt, Object srcFile, String encoding) {
         RConnection connection = RConnection.fromIndex(conn);
         return doParse(connection, n, text.materialize().getDataWithoutCopying(), prompt, srcFile, encoding);
     }
 
-    private Object doParse(RConnection conn, int n, String[] lines, @SuppressWarnings("unused") String prompt, Object srcFile, @SuppressWarnings("unused") String encoding) {
+    private RExpression doParse(RConnection conn, int n, String[] lines, @SuppressWarnings("unused") String prompt, Object srcFile, @SuppressWarnings("unused") String encoding) {
         String coalescedLines = coalesce(lines);
         if (coalescedLines.length() == 0 || n == 0) {
             return RDataFactory.createExpression(new Object[0]);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
index d128c387dc169ba7cfa2d328ed306a3a136d7214..afaa35a46f4ee13c6dd42ce27f0755e5700d3660 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java
@@ -105,7 +105,11 @@ public abstract class Paste extends RBuiltinNode.Arg3 {
         int length = lengthProfile.profile(values.getLength());
         if (hasNonNullElements(values, length)) {
             String[] result = pasteListElements(frame, values, sep, length);
-            return RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+            if (result == ONE_EMPTY_STRING) {
+                return RDataFactory.createEmptyStringVector();
+            } else {
+                return RDataFactory.createStringVector(result, RDataFactory.COMPLETE_VECTOR);
+            }
         } else {
             return RDataFactory.createEmptyStringVector();
         }
@@ -136,13 +140,21 @@ public abstract class Paste extends RBuiltinNode.Arg3 {
     private String[] pasteListElements(VirtualFrame frame, RAbstractListVector values, String sep, int length) {
         String[][] converted = new String[length][];
         int maxLength = 1;
+        int emptyCnt = 0;
         for (int i = 0; i < length; i++) {
             Object element = values.getDataAt(i);
             String[] array = castCharacterVector(frame, element).materialize().getDataWithoutCopying();
             maxLength = Math.max(maxLength, array.length);
-            converted[i] = array.length == 0 ? ONE_EMPTY_STRING : array;
+            if (array.length == 0) {
+                converted[i] = ONE_EMPTY_STRING;
+                emptyCnt++;
+            } else {
+                converted[i] = array;
+            }
         }
-        if (length == 1) {
+        if (emptyCnt == length) {
+            return ONE_EMPTY_STRING;
+        } else if (length == 1) {
             return converted[0];
         } else {
             return prepareResult(sep, length, converted, maxLength);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
index 3dcea15589c1caa75e692575d74107077b8c9f2d..de206ce3cdddbc206ebe8f2eb64de944e8e2b0fc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Primitive.java
@@ -61,7 +61,7 @@ public abstract class Primitive extends RBuiltinNode.Arg1 {
 
     @TruffleBoundary
     protected RFunction lookup(String name) {
-        RFunction function = RContext.lookupBuiltin(name);
+        RFunction function = RContext.getInstance().lookupBuiltin(name);
         if (function == null || function.getRBuiltin() != null && function.getRBuiltin().getKind() != RBuiltinKind.PRIMITIVE) {
             throw error(RError.Message.NO_SUCH_PRIMITIVE, name);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
index cc8bb51840f6ba32e8df0069bd2637e80d157460..da39fe9bdec0bf28a7259cf9f31fb90fe5b65302 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java
@@ -11,28 +11,30 @@
 package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RDispatch.SUMMARY_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUMMARY;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 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.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-@RBuiltin(name = "prod", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
+@RBuiltin(name = "prod", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE_SUMMARY)
 public abstract class Prod extends RBuiltinNode.Arg2 {
 
     // TODO: handle multiple arguments, handle na.rm
@@ -62,8 +64,8 @@ public abstract class Prod extends RBuiltinNode.Arg2 {
             CompilerDirectives.transferToInterpreterAndInvalidate();
             prodRecursive = insert(ProdNodeGen.create());
         }
-        Object ret = prodRecursive.executeObject(args.getArgument(0));
-        if (argsLen != 1) {
+        Object ret = 1d;
+        if (argsLen > 0) {
             double prodReal;
             double prodImg;
             boolean complex;
@@ -77,18 +79,24 @@ public abstract class Prod extends RBuiltinNode.Arg2 {
                 prodImg = 0d;
                 complex = false;
             }
-            for (int i = 1; i < argsLen; i++) {
+            for (int i = 0; i < argsLen; i++) {
                 Object aProd = prodRecursive.executeObject(args.getArgument(i));
                 double aProdReal;
                 double aProdImg;
                 if (aProd instanceof RComplex) {
                     RComplex c = (RComplex) aProd;
+                    if (RRuntime.isNA(c)) {
+                        return c;
+                    }
                     aProdReal = c.getRealPart();
                     aProdImg = c.getImaginaryPart();
                     complex = true;
                 } else {
                     aProdReal = (Double) aProd;
                     aProdImg = 0d;
+                    if (RRuntime.isNA(aProdReal)) {
+                        return aProd;
+                    }
                 }
                 if (complex) {
                     RComplex c = prod.op(prodReal, prodImg, aProdReal, aProdImg);
@@ -104,13 +112,19 @@ public abstract class Prod extends RBuiltinNode.Arg2 {
     }
 
     private final ValueProfile intVecProfile = ValueProfile.createClassProfile();
+    private final NACheck naCheck = NACheck.create();
 
     @Specialization
     protected double prod(RAbstractDoubleVector x) {
         RAbstractDoubleVector profiledVec = intVecProfile.profile(x);
-        double product = profiledVec.getDataAt(0);
-        for (int k = 1; k < profiledVec.getLength(); k++) {
-            product = prod.op(product, profiledVec.getDataAt(k));
+        double product = 1;
+        naCheck.enable(x);
+        for (int k = 0; k < profiledVec.getLength(); k++) {
+            double value = profiledVec.getDataAt(k);
+            if (naCheck.check(value)) {
+                return RRuntime.DOUBLE_NA;
+            }
+            product = prod.op(product, value);
         }
         return product;
     }
@@ -118,9 +132,14 @@ public abstract class Prod extends RBuiltinNode.Arg2 {
     @Specialization
     protected double prod(RAbstractIntVector x) {
         RAbstractIntVector profiledVec = intVecProfile.profile(x);
-        double product = profiledVec.getDataAt(0);
-        for (int k = 1; k < profiledVec.getLength(); k++) {
-            product = prod.op(product, profiledVec.getDataAt(k));
+        double product = 1;
+        naCheck.enable(x);
+        for (int k = 0; k < profiledVec.getLength(); k++) {
+            int data = profiledVec.getDataAt(k);
+            if (naCheck.check(data)) {
+                return RRuntime.DOUBLE_NA;
+            }
+            product = prod.op(product, data);
         }
         return product;
     }
@@ -128,9 +147,14 @@ public abstract class Prod extends RBuiltinNode.Arg2 {
     @Specialization
     protected double prod(RAbstractLogicalVector x) {
         RAbstractLogicalVector profiledVec = intVecProfile.profile(x);
-        double product = profiledVec.getDataAt(0);
-        for (int k = 1; k < profiledVec.getLength(); k++) {
-            product = prod.op(product, profiledVec.getDataAt(k));
+        double product = 1;
+        naCheck.enable(x);
+        for (int k = 0; k < profiledVec.getLength(); k++) {
+            byte value = profiledVec.getDataAt(k);
+            if (naCheck.check(value)) {
+                return RRuntime.DOUBLE_NA;
+            }
+            product = prod.op(product, value);
         }
         return product;
     }
@@ -138,9 +162,13 @@ public abstract class Prod extends RBuiltinNode.Arg2 {
     @Specialization
     protected RComplex prod(RAbstractComplexVector x) {
         RAbstractComplexVector profiledVec = intVecProfile.profile(x);
-        RComplex product = profiledVec.getDataAt(0);
-        for (int k = 1; k < profiledVec.getLength(); k++) {
+        RComplex product = RDataFactory.createComplexRealOne();
+        naCheck.enable(x);
+        for (int k = 0; k < profiledVec.getLength(); k++) {
             RComplex a = profiledVec.getDataAt(k);
+            if (naCheck.check(a)) {
+                return a;
+            }
             product = prod.op(product.getRealPart(), product.getImaginaryPart(), a.getRealPart(), a.getImaginaryPart());
         }
         return product;
@@ -153,6 +181,6 @@ public abstract class Prod extends RBuiltinNode.Arg2 {
 
     @Fallback
     protected Object prod(Object o) {
-        throw RError.error(this, RError.Message.INVALID_TYPE_ARGUMENT, ((RTypedValue) RRuntime.asAbstractVector(o)).getRType().getName());
+        throw error(RError.Message.INVALID_TYPE_ARGUMENT, Predef.typeName().apply(o));
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
index 9d9aa1803a2339befd7fb842563c88c81b026a7b..015e798f80e183440ee7f6c1efc25a05a8bfb595 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java
@@ -24,11 +24,10 @@ import com.oracle.truffle.r.runtime.RCleanUp;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.gnur.SA_TYPE;
 
 @RBuiltin(name = "quit", visibility = OFF, kind = INTERNAL, parameterNames = {"save", "status", "runLast"}, behavior = COMPLEX)
 public abstract class Quit extends RBuiltinNode.Arg3 {
@@ -41,9 +40,9 @@ public abstract class Quit extends RBuiltinNode.Arg3 {
     }
 
     private SA_TYPE checkSaveValue(String save) throws RError {
-        for (String saveValue : SA_TYPE.SAVE_VALUES) {
-            if (saveValue.equals(save)) {
-                return SA_TYPE.fromString(save);
+        for (SA_TYPE saveValue : SA_TYPE.values()) {
+            if (saveValue.getName().equals(save)) {
+                return saveValue;
             }
         }
         throw error(RError.Message.QUIT_SAVE);
@@ -57,8 +56,8 @@ public abstract class Quit extends RBuiltinNode.Arg3 {
             warning(RError.Message.BROWSER_QUIT);
             return RNull.instance;
         }
-        RStartParams.SA_TYPE ask = checkSaveValue(save);
-        if (ask == SA_TYPE.SAVEASK && !RContext.getInstance().getConsoleHandler().isInteractive()) {
+        SA_TYPE ask = checkSaveValue(save);
+        if (ask == SA_TYPE.SAVEASK && !RContext.getInstance().isInteractive()) {
             warning(RError.Message.QUIT_ASK_INTERACTIVE);
         }
         if (status == RRuntime.INT_NA) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/base_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/base_overrides.R
new file mode 100644
index 0000000000000000000000000000000000000000..9b10332922a25ad440fb1fae00a2f2f92fb17920
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/R/base_overrides.R
@@ -0,0 +1,29 @@
+#
+# This material is distributed under the GNU General Public License
+# Version 2. You may review the terms of this license at
+# http://www.gnu.org/licenses/gpl-2.0.html
+#
+# Copyright (c) 1995-2014, The R Core Team
+# Copyright (c) 2016, Oracle and/or its affiliates
+#
+# All rights reserved.
+#
+
+eval(expression({
+.libPaths <- local({
+    .lib.loc <- character()            # Profiles need to set this.
+    function(new) {
+        if(!missing(new)) {
+            ## paths don't really need to be unique, but searching
+            ## large library trees repeatedly would be inefficient.
+            ## Use normalizePath for display: but also does path.expand
+            new <- Sys.glob(path.expand(new))
+            paths <- unique(normalizePath(c(new, .Library.site, .Library), '/'))
+            .lib.loc <<- paths[dir.exists(paths)]
+            .fastr.libPaths(.lib.loc)
+        }
+        else
+            .lib.loc
+    }
+})
+}), asNamespace("base"))
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
index f80721c116078771e8f6c3d76fc83e37d56d96b1..9395c6682ce00d2918381fb53a963329567b0bf6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Range.java
@@ -45,9 +45,9 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 public abstract class Range extends RBuiltinNode.Arg3 {
 
     private static final ReduceSemantics minSemantics = new ReduceSemantics(RRuntime.INT_MAX_VALUE, Double.POSITIVE_INFINITY, false, RError.Message.NO_NONMISSING_MIN,
-                    RError.Message.NO_NONMISSING_MIN_NA, false, true);
+                    RError.Message.NO_NONMISSING_MIN_NA, null, false, true, true);
     private static final ReduceSemantics maxSemantics = new ReduceSemantics(RRuntime.INT_MIN_VALUE, Double.NEGATIVE_INFINITY, false, RError.Message.NO_NONMISSING_MAX,
-                    RError.Message.NO_NONMISSING_MAX_NA, false, true);
+                    RError.Message.NO_NONMISSING_MAX_NA, null, false, true, true);
 
     @Child private UnaryArithmeticReduceNode minReduce = UnaryArithmeticReduceNodeGen.create(minSemantics, BinaryArithmetic.MIN);
     @Child private UnaryArithmeticReduceNode maxReduce = UnaryArithmeticReduceNodeGen.create(maxSemantics, BinaryArithmetic.MAX);
@@ -73,8 +73,10 @@ public abstract class Range extends RBuiltinNode.Arg3 {
     private static RVector<?> createResult(Object min, Object max) {
         if (min instanceof Integer) {
             return RDataFactory.createIntVector(new int[]{(Integer) min, (Integer) max}, false);
-        } else {
+        } else if (min instanceof Double) {
             return RDataFactory.createDoubleVector(new double[]{(Double) min, (Double) max}, false);
+        } else {
+            return RDataFactory.createStringVector(new String[]{(String) min, (String) max}, false);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
index f5d72cb3b60930338de975a7ebcd8e7a0a3e3862..c83f0c38996e3e777ea05c6bf968e6afd553aea7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Readline.java
@@ -29,8 +29,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 @RBuiltin(name = "readline", kind = INTERNAL, parameterNames = "prompt", behavior = IO)
@@ -47,7 +47,7 @@ public abstract class Readline extends RBuiltinNode.Arg1 {
         if (!RContext.getInstance().isInteractive()) {
             return "";
         }
-        ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
+        ConsoleIO consoleHandler = RContext.getInstance().getConsole();
         String savedPrompt = consoleHandler.getPrompt();
         consoleHandler.setPrompt(prompt.getDataAt(0));
         String input = consoleHandler.readLine();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
index 91f3883d1e6ee06c3d2c4ae1e02c761aa660b6c2..31fe3578cee1faaadbfaa7d10246c416f2c114c9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java
@@ -70,7 +70,7 @@ public abstract class RepeatLength extends RBuiltinNode.Arg2 {
     @Specialization
     protected RIntVector repLen(int value, int length) {
         int[] array = new int[length];
-        Arrays.fill(array, length);
+        Arrays.fill(array, value);
         return RDataFactory.createIntVector(array, !RRuntime.isNA(value));
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
index 0b5877e50cca45d3da955ba762198481a9f58718..ec058295772e1fd4df8aa0c514bcf36fe3c7086f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Round.java
@@ -25,11 +25,12 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -44,15 +45,11 @@ 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.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
-import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
-import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-@RBuiltin(name = "round", kind = PRIMITIVE, parameterNames = {"x", "digits"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
+@RBuiltin(name = "round", kind = PRIMITIVE, parameterNames = {"x", "digits"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
 public abstract class Round extends RBuiltinNode.Arg2 {
 
-    public static final UnaryArithmeticFactory ROUND = RoundArithmetic::new;
-
     @Child private RoundArithmetic roundOp = new RoundArithmetic();
 
     private final NACheck check = NACheck.create();
@@ -146,7 +143,7 @@ public abstract class Round extends RBuiltinNode.Arg2 {
     @Specialization(guards = "digits == 0")
     protected RComplex round(RComplex x, @SuppressWarnings("unused") int digits) {
         check.enable(x);
-        return check.check(x) ? RComplex.createNA() : roundOp.op(x.getRealPart(), x.getImaginaryPart());
+        return check.check(x) ? RComplex.createNA() : RComplex.valueOf(roundOp.op(x.getRealPart()), roundOp.op(x.getImaginaryPart()));
     }
 
     @Specialization(guards = "digits != 0")
@@ -187,30 +184,25 @@ public abstract class Round extends RBuiltinNode.Arg2 {
         return ret;
     }
 
-    public static class RoundArithmetic extends UnaryArithmetic {
+    public static final class RoundArithmetic extends Node {
 
         @Child private BinaryArithmetic pow;
 
-        @Override
+        @SuppressWarnings("static-method")
         public int op(int op) {
             return op;
         }
 
-        @Override
+        @SuppressWarnings("static-method")
         public double op(double op) {
             return Math.rint(op);
         }
 
-        @Override
+        @SuppressWarnings("static-method")
         public int op(byte op) {
             return op;
         }
 
-        @Override
-        public RComplex op(double re, double im) {
-            return RDataFactory.createComplex(op(re), op(im));
-        }
-
         public double opd(double op, int digits) {
             return fround(op, digits);
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
index b5303c48c00d30ff72135915d7318e26659be3ff..fc804c04e3aea6da8a615888a113b1a3d5d46a36 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java
@@ -29,8 +29,9 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.ffi.impl.nodes.AsRealNode;
+import com.oracle.truffle.r.ffi.impl.nodes.AsRealNodeGen;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.SeqFunctions.SeqInt.IsIntegralNumericNode;
@@ -40,8 +41,6 @@ import com.oracle.truffle.r.nodes.builtin.base.SeqFunctionsFactory.IsNumericNode
 import com.oracle.truffle.r.nodes.builtin.base.SeqFunctionsFactory.SeqIntNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.SeqFunctionsFactory.SeqIntNodeGen.IsIntegralNumericNodeGen;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
-import com.oracle.truffle.r.nodes.ffi.AsRealNode;
-import com.oracle.truffle.r.nodes.ffi.AsRealNodeGen;
 import com.oracle.truffle.r.nodes.function.CallMatcherNode.CallMatcherGenericNode;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.nodes.function.call.RExplicitBaseEnvCallDispatcher;
@@ -168,7 +167,6 @@ public final class SeqFunctions {
         protected int getIntegralNumeric(@SuppressWarnings("unused") Object obj) {
             throw RInternalError.shouldNotReachHere();
         }
-
     }
 
     public static GetIntegralNumericNode createGetIntegralNumericNode() {
@@ -188,7 +186,7 @@ public final class SeqFunctions {
     public abstract static class SeqFastPath extends FastPathAdapter {
         @Specialization(guards = {"!hasClass(args, getClassAttributeNode)", "lengthSpecials(args)"})
         @SuppressWarnings("unused")
-        protected Object seqNoClassFromAndLength(VirtualFrame frame, RArgsValuesAndNames args, //
+        protected Object seqNoClassFromAndLength(RArgsValuesAndNames args, //
                         @Cached("createSeqIntForFastPath()") SeqInt seqInt,
                         @Cached("lookupSeqInt()") RFunction seqIntFunction,
                         @Cached("createBinaryProfile()") ConditionProfile isNumericProfile,
@@ -196,9 +194,9 @@ public final class SeqFunctions {
                         @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode fromCheck) {
             if (isNumericProfile.profile(fromCheck.execute(args.getArgument(0)))) {
                 if (args.getLength() == 1) {
-                    return seqInt.execute(frame, RMissing.instance, RMissing.instance, RMissing.instance, args.getArgument(0), RMissing.instance, RMissing.instance);
+                    return seqInt.execute(RMissing.instance, RMissing.instance, RMissing.instance, args.getArgument(0), RMissing.instance, RMissing.instance);
                 } else {
-                    return seqInt.execute(frame, args.getArgument(0), RMissing.instance, RMissing.instance, args.getArgument(1), RMissing.instance, RMissing.instance);
+                    return seqInt.execute(args.getArgument(0), RMissing.instance, RMissing.instance, args.getArgument(1), RMissing.instance, RMissing.instance);
                 }
             } else {
                 return null;
@@ -206,7 +204,7 @@ public final class SeqFunctions {
         }
 
         @Specialization(guards = {"!hasClass(args, getClassAttributeNode)"})
-        protected Object seqNoClassAndNumeric(VirtualFrame frame, RArgsValuesAndNames args,
+        protected Object seqNoClassAndNumeric(RArgsValuesAndNames args,
                         @Cached("createSeqIntForFastPath()") SeqInt seqInt,
                         @Cached("lookupSeqInt()") RFunction seqIntFunction,
                         @Cached("createBinaryProfile()") ConditionProfile isNumericProfile,
@@ -216,7 +214,7 @@ public final class SeqFunctions {
                         @Cached("createIsMissingOrNumericNode()") @SuppressWarnings("unused") IsMissingOrNumericNode byCheck) {
             Object[] rargs = reorderedArguments(args, seqIntFunction);
             if (isNumericProfile.profile(fromCheck.execute(rargs[0]) && toCheck.execute(rargs[1]) && toCheck.execute(rargs[2]))) {
-                return seqInt.execute(frame, rargs[0], rargs[1], rargs[2], rargs[3], rargs[4], RMissing.instance);
+                return seqInt.execute(rargs[0], rargs[1], rargs[2], rargs[3], rargs[4], RMissing.instance);
             } else {
                 return null;
             }
@@ -228,7 +226,7 @@ public final class SeqFunctions {
         }
 
         public static RFunction lookupSeqInt() {
-            return RContext.lookupBuiltin("seq.int");
+            return RContext.getInstance().lookupBuiltin("seq.int");
         }
 
         public static GetClassAttributeNode createGetClassAttributeNode() {
@@ -303,12 +301,12 @@ public final class SeqFunctions {
     public abstract static class SeqDefaultFastPath extends FastPathAdapter {
         @SuppressWarnings("unused")
         @Specialization(guards = {"fromCheck.execute(fromObj)", "toCheck.execute(toObj)", "byCheck.execute(byObj)"})
-        protected Object seqDefaultNumeric(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith,
+        protected Object seqDefaultNumeric(Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith,
                         @Cached("createSeqIntForFastPath()") SeqInt seqInt,
                         @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode fromCheck,
                         @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode toCheck,
                         @Cached("createIsMissingOrNumericNode()") IsMissingOrNumericNode byCheck) {
-            return seqInt.execute(frame, fromObj, toObj, byObj, lengthOut, alongWith, RMissing.instance);
+            return seqInt.execute(fromObj, toObj, byObj, lengthOut, alongWith, RMissing.instance);
         }
 
         /**
@@ -316,7 +314,7 @@ public final class SeqFunctions {
          */
         @SuppressWarnings("unused")
         @Fallback
-        protected Object seqDefaultFallback(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith) {
+        protected Object seqDefaultFallback(Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith) {
             return null;
         }
     }
@@ -331,9 +329,9 @@ public final class SeqFunctions {
         }
 
         @Specialization(guards = "!hasClass(value)")
-        protected RIntSequence seq(VirtualFrame frame, Object value,
+        protected RIntSequence seq(Object value,
                         @Cached("create()") RLengthNode length) {
-            return RDataFactory.createIntSequence(1, 1, length.executeInteger(frame, value));
+            return RDataFactory.createIntSequence(1, 1, length.executeInteger(value));
         }
 
         /**
@@ -402,12 +400,11 @@ public final class SeqFunctions {
      *
      * N.B. javac gives error "cannot find symbol" on plain "@RBuiltin".
      */
-    @SuppressWarnings("unused")
     @ImportStatic({AsRealNodeGen.class, SeqFunctions.class})
+    @SuppressWarnings("unused")
     @com.oracle.truffle.r.runtime.builtins.RBuiltin(name = "seq.int", kind = PRIMITIVE, parameterNames = {"from", "to", "by", "length.out", "along.with",
                     "..."}, dispatch = INTERNAL_GENERIC, genericName = "seq", behavior = PURE)
     public abstract static class SeqInt extends RBuiltinNode.Arg6 {
-        private final BranchProfile error = BranchProfile.create();
         private final boolean seqFastPath;
 
         /**
@@ -427,6 +424,8 @@ public final class SeqFunctions {
         @Override
         public abstract Object execute(VirtualFrame frame, Object start, Object to, Object by, Object lengthOut, Object alongWith, Object dotdotdot);
 
+        public abstract Object execute(Object start, Object to, Object by, Object lengthOut, Object alongWith, Object dotdotdot);
+
         protected SeqInt(boolean seqFastPath) {
             this.seqFastPath = seqFastPath;
         }
@@ -460,8 +459,8 @@ public final class SeqFunctions {
         /**
          * Irrespective of the R type, if the length is zero the result is an empty sequence.
          */
-        @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) == 0"})
-        protected RIntVector emptySeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
+        @Specialization(guards = {"!isMissing(from)", "getLength(from) == 0"})
+        protected RIntVector emptySeqFromOneArg(Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             return RDataFactory.createEmptyIntVector();
         }
 
@@ -471,9 +470,9 @@ public final class SeqFunctions {
          * builtins take the </i>value</i> of the first element and warn about ignoring the rest,
          * but the value likely could not be coerced.
          */
-        @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) > 1"})
-        protected RIntSequence lenSeqFromOneArg(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
-            return RDataFactory.createIntSequence(1, 1, getLength(frame, from));
+        @Specialization(guards = {"!isMissing(from)", "getLength(from) > 1"})
+        protected RIntSequence lenSeqFromOneArg(Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
+            return RDataFactory.createIntSequence(1, 1, getLength(from));
         }
 
         /**
@@ -512,8 +511,8 @@ public final class SeqFunctions {
          * {@code !isNumeric(from)} guard this would "contain" the previous two specializations,
          * which would be incorrect as the result is different.
          */
-        @Specialization(guards = {"!isMissing(from)", "getLength(frame, from) == 1", "!isNumeric(from)"})
-        protected RIntSequence seqFromOneArgObj(VirtualFrame frame, Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
+        @Specialization(guards = {"!isMissing(from)", "getLength(from) == 1", "!isNumeric(from)"})
+        protected RIntSequence seqFromOneArgObj(Object from, RMissing to, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot) {
             return RDataFactory.createIntSequence(1, 1, 1);
         }
 
@@ -528,8 +527,7 @@ public final class SeqFunctions {
          */
 
         @Specialization(guards = "validDoubleParams(fromVec, toVec)")
-        protected RAbstractVector seqLengthByMissingDouble(VirtualFrame frame, RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith,
-                        Object dotdotdot,
+        protected RAbstractVector seqLengthByMissingDouble(RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("createBinaryProfile()") ConditionProfile directionProfile) {
             double from = fromVec.getDataAt(0);
             double to = toVec.getDataAt(0);
@@ -538,7 +536,7 @@ public final class SeqFunctions {
         }
 
         @Specialization(guards = "validIntParams(fromVec, toVec)")
-        protected RAbstractVector seqLengthByMissingInt(VirtualFrame frame, RAbstractIntVector fromVec, RAbstractIntVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
+        protected RAbstractVector seqLengthByMissingInt(RAbstractIntVector fromVec, RAbstractIntVector toVec, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("createBinaryProfile()") ConditionProfile directionProfile) {
             int from = fromVec.getDataAt(0);
             int to = toVec.getDataAt(0);
@@ -554,7 +552,7 @@ public final class SeqFunctions {
          * previous specializations.
          */
         @Specialization(guards = {"!isMissing(toObj)"})
-        protected RAbstractVector seqLengthByMissing(VirtualFrame frame, Object fromObj, Object toObj, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
+        protected RAbstractVector seqLengthByMissing(Object fromObj, Object toObj, RMissing by, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealFrom,
                         @Cached("create()") AsRealNode asRealTo,
                         @Cached("createBinaryProfile()") ConditionProfile directionProfile) {
@@ -562,15 +560,14 @@ public final class SeqFunctions {
             if (isMissing(fromObj)) {
                 from = 1.0;
             } else {
-                validateLength(frame, fromObj, "from");
+                validateLength(fromObj, "from");
                 from = asRealFrom.execute(fromObj);
                 validateDoubleParam(from, fromObj, "from");
             }
-            validateLength(frame, toObj, "to");
+            validateLength(toObj, "to");
             double to = asRealTo.execute(toObj);
             validateDoubleParam(to, toObj, "to");
-            RAbstractVector result = createRSequence(from, to, directionProfile);
-            return result;
+            return createRSequence(from, to, directionProfile);
         }
 
         /*
@@ -580,16 +577,15 @@ public final class SeqFunctions {
          */
 
         @Specialization(guards = {"validDoubleParams(fromVec, toVec)", "!isMissing(byObj)"})
-        protected Object seqLengthMissing(VirtualFrame frame, RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, Object byObj, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
+        protected Object seqLengthMissing(RAbstractDoubleVector fromVec, RAbstractDoubleVector toVec, Object byObj, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealby) {
-            validateLength(frame, byObj, "by");
+            validateLength(byObj, "by");
             double by = asRealby.execute(byObj);
             return doSeqLengthMissing(fromVec.getDataAt(0), toVec.getDataAt(0), by, false);
         }
 
         @Specialization(guards = {"validIntParams(fromVec, toVec)", "validIntParam(byVec)", "byVec.getDataAt(0) != 0"})
-        protected RAbstractVector seqLengthMissing(VirtualFrame frame, RAbstractIntVector fromVec, RAbstractIntVector toVec, RAbstractIntVector byVec, RMissing lengthOut, RMissing alongWith,
-                        Object dotdotdot,
+        protected RAbstractVector seqLengthMissing(RAbstractIntVector fromVec, RAbstractIntVector toVec, RAbstractIntVector byVec, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("createBinaryProfile()") ConditionProfile directionProfile) {
             int by = byVec.getDataAt(0);
             int from = fromVec.getDataAt(0);
@@ -597,7 +593,6 @@ public final class SeqFunctions {
             RIntSequence result;
             if (directionProfile.profile(from < to)) {
                 if (by < 0) {
-                    error.enter();
                     throw error(RError.Message.WRONG_SIGN_IN_BY);
                 }
                 result = RDataFactory.createIntSequence(from, by, (to - from) / by + 1);
@@ -606,7 +601,6 @@ public final class SeqFunctions {
                     return RDataFactory.createIntVectorFromScalar(from);
                 }
                 if (by > 0) {
-                    error.enter();
                     throw error(RError.Message.WRONG_SIGN_IN_BY);
                 }
                 result = RDataFactory.createIntSequence(from, by, (from - to) / (-by) + 1);
@@ -618,7 +612,7 @@ public final class SeqFunctions {
          * See comment in {@link #seqLengthByMissing}.
          */
         @Specialization(guards = {"!isMissing(byObj)"})
-        protected Object seqLengthMissing(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
+        protected Object seqLengthMissing(Object fromObj, Object toObj, Object byObj, RMissing lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealFrom,
                         @Cached("create()") AsRealNode asRealTo,
                         @Cached("create()") AsRealNode asRealby) {
@@ -628,7 +622,7 @@ public final class SeqFunctions {
                 from = 1.0;
                 allInt = false;
             } else {
-                validateLength(frame, fromObj, "from");
+                validateLength(fromObj, "from");
                 from = asRealFrom.execute(fromObj);
                 validateDoubleParam(from, fromObj, "from");
                 allInt &= isInt(fromObj);
@@ -638,12 +632,12 @@ public final class SeqFunctions {
                 to = 1.0;
                 allInt = false;
             } else {
-                validateLength(frame, toObj, "to");
-                to = asRealFrom.execute(toObj);
+                validateLength(toObj, "to");
+                to = asRealTo.execute(toObj);
                 validateDoubleParam(to, toObj, "to");
                 allInt &= isInt(toObj);
             }
-            validateLength(frame, byObj, "by");
+            validateLength(byObj, "by");
             allInt &= isInt(byObj);
             double by = asRealby.execute(byObj);
             return doSeqLengthMissing(from, to, by, allInt);
@@ -662,7 +656,6 @@ public final class SeqFunctions {
                     // N.B. GNU R returns the original "from" argument (which might be missing)
                     return RDataFactory.createDoubleVectorFromScalar(from);
                 } else {
-                    error.enter();
                     // This should go away in an upcoming GNU R release
                     throw error(seqFastPath ? RError.Message.INVALID_TFB_SD : RError.Message.INVALID_TFB);
                 }
@@ -673,11 +666,9 @@ public final class SeqFunctions {
                 return RDataFactory.createDoubleVectorFromScalar(from);
             }
             if (n > Integer.MAX_VALUE) {
-                error.enter();
                 throw error(RError.Message.BY_TOO_SMALL);
             }
             if (n < -FEPS) {
-                error.enter();
                 throw error(RError.Message.WRONG_SIGN_IN_BY);
             }
             RAbstractVector result;
@@ -714,17 +705,17 @@ public final class SeqFunctions {
          */
 
         @Specialization(guards = "!isMissing(lengthOut)")
-        protected RAbstractVector seqJustLength(VirtualFrame frame, RMissing from, RMissing to, RMissing by, Object lengthOut, RMissing alongWith, Object dotdotdot,
+        protected RAbstractVector seqJustLength(RMissing from, RMissing to, RMissing by, Object lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealLen) {
-            int n = checkLength(frame, lengthOut, asRealLen);
+            int n = checkLength(lengthOut, asRealLen);
             return n == 0 ? RDataFactory.createEmptyIntVector() : RDataFactory.createIntSequence(1, 1, n);
         }
 
         // seq(along,with=)
 
         @Specialization(guards = "!isMissing(alongWith)")
-        protected RAbstractVector seqFromJustAlong(VirtualFrame frame, RMissing from, RMissing to, RMissing by, RMissing lengthOut, Object alongWith, Object dotdotdot) {
-            int len = getLength(frame, alongWith);
+        protected RAbstractVector seqFromJustAlong(RMissing from, RMissing to, RMissing by, RMissing lengthOut, Object alongWith, Object dotdotdot) {
+            int len = getLength(alongWith);
             return len == 0 ? RDataFactory.createEmptyIntVector() : RDataFactory.createIntSequence(1, 1, len);
         }
 
@@ -760,7 +751,7 @@ public final class SeqFunctions {
             }
 
             @Specialization
-            protected boolean isIntegralNumericNode(Integer obj) {
+            protected boolean isIntegralNumericNode(int obj) {
                 if (checkLength) {
                     return obj >= 0;
                 } else {
@@ -774,7 +765,7 @@ public final class SeqFunctions {
             }
 
             @Specialization
-            protected boolean isIntegralNumericNode(Double obj) {
+            protected boolean isIntegralNumericNode(double obj) {
                 double d = obj;
                 return d == (int) d && (checkLength ? d >= 0 : true);
             }
@@ -797,7 +788,7 @@ public final class SeqFunctions {
 
         // common idiom
         @Specialization(guards = {"fromCheck.execute(fromObj)", "lengthCheck.execute(lengthOut)"})
-        protected RAbstractVector seqWithFromLengthIntegralNumeric(VirtualFrame frame, Object fromObj, RMissing toObj, RMissing byObj, Object lengthOut, RMissing alongWith, Object dotdotdot,
+        protected RAbstractVector seqWithFromLengthIntegralNumeric(Object fromObj, RMissing toObj, RMissing byObj, Object lengthOut, RMissing alongWith, Object dotdotdot,
                         @Cached("createGetIntegralNumericNode()") GetIntegralNumericNode getIntegralNumericNode,
                         @Cached("createIsIntegralNumericNodeNoLengthCheck()") IsIntegralNumericNode fromCheck,
                         @Cached("createIsIntegralNumericNodeLengthCheck()") IsIntegralNumericNode lengthCheck) {
@@ -812,18 +803,18 @@ public final class SeqFunctions {
 
         // "by" missing
         @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(fromObj, toObj)"})
-        protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, Object toObj, RMissing byObj, Object lengthOut, Object alongWith, Object dotdotdot,
+        protected RAbstractVector seqWithLength(Object fromObj, Object toObj, RMissing byObj, Object lengthOut, Object alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealFrom,
                         @Cached("create()") AsRealNode asRealTo,
                         @Cached("create()") AsRealNode asRealLen) {
-            int lout = checkLengthAlongWith(frame, lengthOut, alongWith, asRealLen);
+            int lout = checkLengthAlongWith(lengthOut, alongWith, asRealLen);
             if (lout == 0) {
                 return RDataFactory.createEmptyIntVector();
             }
             boolean fromMissing = isMissing(fromObj);
             boolean toMissing = isMissing(toObj);
             double from = asRealFrom.execute(fromObj);
-            double to = asRealFrom.execute(toObj);
+            double to = asRealTo.execute(toObj);
             if (toMissing) {
                 to = from + lout - 1;
             }
@@ -866,11 +857,11 @@ public final class SeqFunctions {
 
         // "to" missing
         @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(fromObj, byObj)"})
-        protected RAbstractVector seqWithLength(VirtualFrame frame, Object fromObj, RMissing toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot,
+        protected RAbstractVector seqWithLength(Object fromObj, RMissing toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealFrom,
                         @Cached("create()") AsRealNode asRealby,
                         @Cached("create()") AsRealNode asRealLen) {
-            int lout = checkLengthAlongWith(frame, lengthOut, alongWith, asRealLen);
+            int lout = checkLengthAlongWith(lengthOut, alongWith, asRealLen);
             if (lout == 0) {
                 return RDataFactory.createEmptyIntVector();
             }
@@ -893,11 +884,11 @@ public final class SeqFunctions {
 
         // "from" missing
         @Specialization(guards = {"oneNotMissing(alongWith, lengthOut)", "oneNotMissing(toObj, byObj)"})
-        protected RAbstractVector seqWithLength(VirtualFrame frame, RMissing fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot,
+        protected RAbstractVector seqWithLength(RMissing fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot,
                         @Cached("create()") AsRealNode asRealTo,
                         @Cached("create()") AsRealNode asRealby,
                         @Cached("create()") AsRealNode asRealLen) {
-            int lout = checkLengthAlongWith(frame, lengthOut, alongWith, asRealLen);
+            int lout = checkLengthAlongWith(lengthOut, alongWith, asRealLen);
             if (lout == 0) {
                 return RDataFactory.createEmptyIntVector();
             }
@@ -914,8 +905,7 @@ public final class SeqFunctions {
         }
 
         @Fallback
-        protected RAbstractVector seqFallback(VirtualFrame frame, Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot) {
-            error.enter();
+        protected RAbstractVector seqFallback(Object fromObj, Object toObj, Object byObj, Object lengthOut, Object alongWith, Object dotdotdot) {
             throw error(RError.Message.TOO_MANY_ARGS);
         }
 
@@ -933,8 +923,8 @@ public final class SeqFunctions {
             return vec.getLength() == 1 && vec.getDataAt(0) != RRuntime.INT_NA;
         }
 
-        public final int getLength(VirtualFrame frame, Object obj) {
-            return lengthNode.executeInteger(frame, obj);
+        public final int getLength(Object obj) {
+            return lengthNode.executeInteger(obj);
         }
 
         public static boolean isNumeric(Object obj) {
@@ -966,7 +956,6 @@ public final class SeqFunctions {
 
         private int validateIntParam(int v, String vName) {
             if (RRuntime.isNA(v)) {
-                error.enter();
                 throw error(RError.Message.CANNOT_BE_INVALID, vName);
             }
             return v;
@@ -979,7 +968,6 @@ public final class SeqFunctions {
         private double validateDoubleParam(double v, Object vObj, String vName) {
             if (vObj != RMissing.instance) {
                 if (!isFinite(v)) {
-                    error.enter();
                     throw error(RError.Message.CANNOT_BE_INVALID, vName);
                 }
             }
@@ -989,22 +977,20 @@ public final class SeqFunctions {
         /**
          * Unless {@code obj} is missing, check whether length is 1.
          */
-        private void validateLength(VirtualFrame frame, Object obj, String vName) {
+        private void validateLength(Object obj, String vName) {
             if (obj != RMissing.instance) {
-                if (getLength(frame, obj) != 1) {
-                    error.enter();
+                if (getLength(obj) != 1) {
                     throw error(RError.Message.MUST_BE_SCALAR, vName);
                 }
             }
         }
 
-        private int checkLength(VirtualFrame frame, Object lengthOut, AsRealNode asRealLen) {
+        private int checkLength(Object lengthOut, AsRealNode asRealLen) {
             double len = asRealLen.execute(lengthOut);
             if (RRuntime.isNAorNaN(len) || len <= -0.5) {
-                error.enter();
                 throw error(seqFastPath ? RError.Message.MUST_BE_POSITIVE_SD : RError.Message.MUST_BE_POSITIVE, seqFastPath ? "length" : "length.out");
             }
-            if (getLength(frame, lengthOut) != 1) {
+            if (getLength(lengthOut) != 1) {
                 warning(RError.Message.FIRST_ELEMENT_USED, "length.out");
             }
             return (int) Math.ceil(len);
@@ -1018,11 +1004,11 @@ public final class SeqFunctions {
             return (int) by == by && isInIntRange(from) && isInIntRange(to);
         }
 
-        private int checkLengthAlongWith(VirtualFrame frame, Object lengthOut, Object alongWith, AsRealNode asRealLen) {
+        private int checkLengthAlongWith(Object lengthOut, Object alongWith, AsRealNode asRealLen) {
             if (alongWith != RMissing.instance) {
-                return getLength(frame, alongWith);
+                return getLength(alongWith);
             } else if (lengthOut != RMissing.instance) {
-                return checkLength(frame, lengthOut, asRealLen);
+                return checkLength(lengthOut, asRealLen);
             } else {
                 throw RInternalError.shouldNotReachHere();
             }
@@ -1036,7 +1022,6 @@ public final class SeqFunctions {
         private int checkVecLength(double from, double to) {
             double r = Math.abs(to - from);
             if (r > Integer.MAX_VALUE) {
-                error.enter();
                 throw error(RError.Message.TOO_LONG_VECTOR);
             }
             int length = (int) (r + 1 + FLT_EPSILON);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
index 92ca9352eafb946d049bb19e5cbcd3defa9289bd..0965acbef02e3ea24c704d0bc2dead29d08211f4 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Setwd.java
@@ -30,13 +30,13 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
 @RBuiltin(name = "setwd", visibility = OFF, kind = INTERNAL, parameterNames = "path", behavior = IO)
 public abstract class Setwd extends RBuiltinNode.Arg1 {
@@ -46,11 +46,12 @@ public abstract class Setwd extends RBuiltinNode.Arg1 {
         casts.arg("path").defaultError(CHAR_ARGUMENT).mustBe(stringValue()).asStringVector().mustBe(notEmpty()).findFirst();
     }
 
+    @Child private BaseRFFI.GetwdNode getwdNode = RFFIFactory.getBaseRFFI().createGetwdNode();
+    @Child private BaseRFFI.SetwdNode setwdNode = RFFIFactory.getBaseRFFI().createSetwdNode();
+
     @Specialization
     @TruffleBoundary
-    protected Object setwd(String path,
-                    @Cached("create()") BaseRFFI.GetwdNode getwdNode,
-                    @Cached("create()") BaseRFFI.SetwdNode setwdNode) {
+    protected Object setwd(String path) {
         String owd = getwdNode.execute();
         String nwd = Utils.tildeExpand(path);
         int rc = setwdNode.execute(nwd);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
index 1ef56ebc6b17357b39cb72c0b879006c7038d680..1bf082778ce46bdd4ea5ab5aab2ef9e5434c9d59 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Signif.java
@@ -137,7 +137,7 @@ public abstract class Signif extends RBuiltinNode.Arg2 {
 
     @TruffleBoundary
     private static double bigIntegerSignif(int digits, double val) {
-        BigDecimal bigDecimalVal = new BigDecimal(val, new MathContext(digits, RoundingMode.HALF_UP));
+        BigDecimal bigDecimalVal = new BigDecimal(val, new MathContext(digits, RoundingMode.HALF_EVEN));
         return bigDecimalVal.doubleValue();
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
index 98c7e6420098a0b05fac67463bd3adf6275a0cf2..52efddcdd4fbd4c2a2eda5c01ba82ab1a0bf23ce 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java
@@ -23,7 +23,6 @@ import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.access.AccessSlotNode;
 import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.WrapArgumentNode;
 import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode;
@@ -32,6 +31,7 @@ import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 
 @RBuiltin(name = "@", kind = PRIMITIVE, parameterNames = {"", ""}, nonEvalArgs = 1, behavior = COMPLEX)
 public abstract class Slot extends RBuiltinNode.Arg2 {
@@ -58,8 +58,8 @@ public abstract class Slot extends RBuiltinNode.Arg2 {
                 if (val instanceof RSymbol) {
                     return ((RSymbol) val).getName();
                 }
-            } else if (rep instanceof ReadVariableNode) {
-                return ((ReadVariableNode) rep).getIdentifier();
+            } else if (rep instanceof RSyntaxLookup) {
+                return ((RSyntaxLookup) rep).getIdentifier();
             }
         }
         CompilerDirectives.transferToInterpreter();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
index 1cbef88f119a988783ab30f87c7841653f9714b4..2b74f0c39a4845d04edb71fca3e90ebdb7db1411 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SortFunctions.java
@@ -195,7 +195,6 @@ public class SortFunctions {
         protected RNull sort(@SuppressWarnings("unused") RNull vec, @SuppressWarnings("unused") boolean decreasing) {
             return RNull.instance;
         }
-
     }
 
     @RBuiltin(name = "qsort", kind = INTERNAL, parameterNames = {"x", "decreasing"}, behavior = PURE)
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 f309975878a3af3f16c66c8e2a099601b24bb498..0069d9e8851782c95f4c4ac00845a5c264c49550 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
@@ -29,6 +29,7 @@ import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.helpers.RFactorNodes;
 import com.oracle.truffle.r.runtime.Utils;
@@ -42,6 +43,7 @@ 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;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 
 /**
  * The {@code split} internal. Internal version of 'split' is invoked from 'split.default' function
@@ -57,8 +59,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 public abstract class Split extends RBuiltinNode.Arg2 {
 
     @Child private RFactorNodes.GetLevels getLevelNode = new RFactorNodes.GetLevels();
+    @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
     @SuppressWarnings("unused") private final ConditionProfile noStringLevels = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile namesProfile = ConditionProfile.createBinaryProfile();
 
     private static final int INITIAL_SIZE = 5;
     private static final int SCALE_FACTOR = 2;
@@ -91,12 +95,12 @@ public abstract class Split extends RBuiltinNode.Arg2 {
             collect[collectResultSize[resultIndex]++] = x.getDataAt(i);
         }
 
-        // assemble result vectors and level names
         Object[] results = new Object[nLevels];
+        RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize);
         for (int i = 0; i < nLevels; i++) {
-            results[i] = RDataFactory.createList(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]));
+            results[i] = RDataFactory.createList(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]),
+                            (resultNames != null) ? resultNames[i] : null);
         }
-
         return RDataFactory.createList(results, names);
     }
 
@@ -124,12 +128,12 @@ public abstract class Split extends RBuiltinNode.Arg2 {
             collect[collectResultSize[resultIndex]++] = x.getDataAt(i);
         }
 
-        // assemble result vectors and level names
         Object[] results = new Object[nLevels];
+        RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize);
         for (int i = 0; i < nLevels; i++) {
-            results[i] = RDataFactory.createIntVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), x.isComplete());
+            results[i] = RDataFactory.createIntVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), x.isComplete(),
+                            (resultNames != null) ? resultNames[i] : null);
         }
-
         return RDataFactory.createList(results, names);
     }
 
@@ -157,12 +161,12 @@ public abstract class Split extends RBuiltinNode.Arg2 {
             collect[collectResultSize[resultIndex]++] = x.getDataAt(i);
         }
 
-        // assemble result vectors and level names
         Object[] results = new Object[nLevels];
+        RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize);
         for (int i = 0; i < nLevels; i++) {
-            results[i] = RDataFactory.createDoubleVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), RDataFactory.COMPLETE_VECTOR);
+            results[i] = RDataFactory.createDoubleVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), RDataFactory.COMPLETE_VECTOR,
+                            (resultNames != null) ? resultNames[i] : null);
         }
-
         return RDataFactory.createList(results, names);
     }
 
@@ -190,12 +194,12 @@ public abstract class Split extends RBuiltinNode.Arg2 {
             collect[collectResultSize[resultIndex]++] = x.getDataAt(i);
         }
 
-        // assemble result vectors and level names
         Object[] results = new Object[nLevels];
+        RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize);
         for (int i = 0; i < nLevels; i++) {
-            results[i] = RDataFactory.createStringVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), RDataFactory.COMPLETE_VECTOR);
+            results[i] = RDataFactory.createStringVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), RDataFactory.COMPLETE_VECTOR,
+                            (resultNames != null) ? resultNames[i] : null);
         }
-
         return RDataFactory.createList(results, names);
     }
 
@@ -223,12 +227,12 @@ public abstract class Split extends RBuiltinNode.Arg2 {
             collect[collectResultSize[resultIndex]++] = x.getDataAt(i);
         }
 
-        // assemble result vectors and level names
         Object[] results = new Object[nLevels];
+        RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize);
         for (int i = 0; i < nLevels; i++) {
-            results[i] = RDataFactory.createLogicalVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), x.isComplete());
+            results[i] = RDataFactory.createLogicalVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), x.isComplete(),
+                            (resultNames != null) ? resultNames[i] : null);
         }
-
         return RDataFactory.createList(results, names);
     }
 
@@ -256,15 +260,36 @@ public abstract class Split extends RBuiltinNode.Arg2 {
             collect[collectResultSize[resultIndex]++] = x.getDataAt(i).getValue();
         }
 
-        // assemble result vectors and level names
         Object[] results = new Object[nLevels];
+        RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize);
         for (int i = 0; i < nLevels; i++) {
-            results[i] = RDataFactory.createRawVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]));
+            results[i] = RDataFactory.createRawVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]),
+                            (resultNames != null) ? resultNames[i] : null);
         }
-
         return RDataFactory.createList(results, names);
     }
 
+    private RStringVector[] getNames(RAbstractVector x, int[] factor, int nLevels, int[] collectResultSize) {
+        RStringVector xNames = getNamesNode.getNames(x);
+        if (namesProfile.profile(xNames != null)) {
+            String[][] namesArr = new String[nLevels][];
+            int[] resultNamesIdxs = new int[nLevels];
+            for (int i = 0; i < nLevels; i++) {
+                namesArr[i] = new String[collectResultSize[i]];
+            }
+            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
+                namesArr[resultIndex][resultNamesIdxs[resultIndex]++] = xNames.getDataAt(i);
+            }
+            RStringVector[] resultNames = new RStringVector[nLevels];
+            for (int i = 0; i < nLevels; i++) {
+                resultNames[i] = RDataFactory.createStringVector(namesArr[i], xNames.isComplete());
+            }
+            return resultNames;
+        }
+        return null;
+    }
+
     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/Strtoi.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
index 57d4d6171b68c21d7dae1079de4df35e69db4542..d08b8e788681eb0c04ceeea634209f3092d3f887 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtoi.java
@@ -30,7 +30,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
-import com.oracle.truffle.api.ExactMath;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
@@ -127,7 +126,7 @@ public abstract class Strtoi extends RBuiltinNode.Arg2 {
                             }
                         }
                         try {
-                            dataValue = ExactMath.addExact(ExactMath.multiplyExact(dataValue, base), digit);
+                            dataValue = Math.addExact(Math.multiplyExact(dataValue, base), digit);
                         } catch (ArithmeticException e) {
                             dataValue = RRuntime.INT_NA;
                             break;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
index 5f20186adf19dec50fb43938b0e92e0081f7c3f9..a7744efb76a1dd7fcab5b153ab7c4510f3141605 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substitute.java
@@ -109,11 +109,10 @@ public abstract class Substitute extends RBuiltinNode.Arg2 {
 
         // The "expr" promise comes from the no-evalarg aspect of the builtin,
         // so get the actual expression (AST) from that
-        return RASTUtils.createLanguageElement(RSubstitute.substitute(env, expr.getRep()));
+        return RASTUtils.createLanguageElement(RSubstitute.substitute(env, expr.getRep(), getRLanguage()));
     }
 
     protected static RList2EnvNode createList2EnvNode() {
         return new RList2EnvNode(true);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
index f3c3760c13d7ecc8a04fb997746daf8b64f216e8..968038ad0204bf0211e1bd98d71518de1328a2c2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Substr.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
+import com.oracle.truffle.api.dsl.Cached;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
@@ -29,6 +30,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -59,13 +61,15 @@ public abstract class Substr extends RBuiltinNode.Arg3 {
 
     @SuppressWarnings("unused")
     @Specialization(guards = {"!emptyArg(arg)", "wrongParams(start, stop)"})
-    protected RNull substrWrongParams(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop) {
+    protected RNull substrWrongParams(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         RInternalError.shouldNotReachHere();
         return RNull.instance; // dummy
     }
 
     @Specialization(guards = {"!emptyArg(arg)", "!wrongParams(start, stop)"})
-    protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop) {
+    protected RStringVector substr(RAbstractStringVector arg, RAbstractIntVector start, RAbstractIntVector stop,
+                    @Cached("create()") UnaryCopyAttributesNode copyAttributesNode) {
         String[] res = new String[arg.getLength()];
         na.enable(arg);
         na.enable(start);
@@ -77,7 +81,9 @@ public abstract class Substr extends RBuiltinNode.Arg3 {
             // Checkstyle: resume modified control variable check
             res[i] = substr0(arg.getDataAt(i), start.getDataAt(j), stop.getDataAt(k));
         }
-        return RDataFactory.createStringVector(res, na.neverSeenNA());
+        RStringVector result = RDataFactory.createStringVector(res, na.neverSeenNA());
+        copyAttributesNode.execute(result, arg);
+        return result;
     }
 
     private String substr0(String x, int start, int stop) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
index aa347076a2f0e0fcf512add9cbaac212438da4a8..00fbadeb93c2ed6e3bb8c7923f10a38ebf9865c7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
 import static com.oracle.truffle.r.runtime.RDispatch.SUMMARY_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUMMARY;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
@@ -49,12 +49,12 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
 /**
  * Sum has combine semantics (TBD: exactly?) and uses a reduce operation on the resulting array.
  */
-@RBuiltin(name = "sum", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE)
+@RBuiltin(name = "sum", kind = PRIMITIVE, parameterNames = {"...", "na.rm"}, dispatch = SUMMARY_GROUP_GENERIC, behavior = PURE_SUMMARY)
 public abstract class Sum extends RBuiltinNode.Arg2 {
 
     protected static final boolean FULL_PRECISION = FastROptions.FullPrecisionSum.getBooleanValue();
 
-    private static final ReduceSemantics semantics = new ReduceSemantics(0, 0.0, true, null, null, Message.INTEGER_OVERFLOW_USE_SUM_NUMERIC, true, false);
+    private static final ReduceSemantics semantics = new ReduceSemantics(0, 0.0, true, null, null, Message.INTEGER_OVERFLOW_USE_SUM_NUMERIC, true, false, false);
 
     @Child private UnaryArithmeticReduceNode reduce = UnaryArithmeticReduceNodeGen.create(semantics, BinaryArithmetic.ADD);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
index 586af6390e9cb6b0c51eb4469843aa07fc998031..69d421843f509817fb28b6c594a7625e9d6adf23 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java
@@ -109,7 +109,6 @@ public class TraceFunctions {
             }
             return RNull.instance;
         }
-
     }
 
     @RBuiltin(name = ".primUntrace", visibility = OFF, kind = PRIMITIVE, parameterNames = "what", behavior = COMPLEX)
@@ -134,7 +133,6 @@ public class TraceFunctions {
             }
             return RNull.instance;
         }
-
     }
 
     @RBuiltin(name = "traceOnOff", kind = INTERNAL, parameterNames = "state", behavior = COMPLEX)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
index db4fa2a7fa41ad40cb1ac8117e331075c79ba5be..abad492f9edd0a6c2fb3d83f0a84797ae82fcc5d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
@@ -30,6 +30,7 @@ import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RError.Message;
@@ -37,6 +38,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -62,6 +64,7 @@ public abstract class Transpose extends RBuiltinNode.Arg1 {
     @Child private SetFixedAttributeNode putDimensions = SetFixedAttributeNode.createDim();
     @Child private SetFixedAttributeNode putDimNames = SetFixedAttributeNode.createDimNames();
     @Child private GetDimNamesAttributeNode getDimNamesNode = GetDimNamesAttributeNode.create();
+    @Child private GetNamesAttributeNode getAxisNamesNode = GetNamesAttributeNode.create();
     @Child private GetDimAttributeNode getDimNode;
 
     static {
@@ -113,7 +116,9 @@ public abstract class Transpose extends RBuiltinNode.Arg1 {
         if (dimNames != null) {
             hasDimNamesProfile.enter();
             assert dimNames.getLength() == 2;
-            RList newDimNames = RDataFactory.createList(new Object[]{dimNames.getDataAt(1), dimNames.getDataAt(0)});
+            RStringVector axisNames = getAxisNamesNode.getNames(dimNames);
+            RStringVector transAxisNames = axisNames == null ? null : RDataFactory.createStringVector(new String[]{axisNames.getDataAt(1), axisNames.getDataAt(0)}, true);
+            RList newDimNames = RDataFactory.createList(new Object[]{dimNames.getDataAt(1), dimNames.getDataAt(0)}, transAxisNames);
             putDimNames.execute(r.getAttributes(), newDimNames);
         }
         return r;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
index ac25b54d6af35464384e56095b67c3eadead91ee..1cef368c45a90755cc8b9eed0265a6a24d0c0a62 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
@@ -26,26 +26,22 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asDoubleVect
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.AcosNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.AsinNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.AtanNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.CosNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.SinNodeGen;
-import com.oracle.truffle.r.nodes.builtin.base.TrigExpFunctionsFactory.TanNodeGen;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -54,17 +50,13 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic.Pow.CHypot;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
 public class TrigExpFunctions {
 
-    @RBuiltin(name = "exp", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Exp extends UnaryArithmeticBuiltinNode {
-
-        public Exp() {
-            super(RType.Double);
-        }
-
+    @RBuiltin(name = "exp", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Exp extends UnaryArithmetic {
         @Child private BinaryArithmetic calculatePowNode;
 
         @Override
@@ -82,12 +74,8 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "expm1", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class ExpM1 extends UnaryArithmeticBuiltinNode {
-
-        public ExpM1() {
-            super(RType.Double);
-        }
+    @RBuiltin(name = "expm1", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class ExpM1 extends UnaryArithmetic {
 
         @Child private BinaryArithmetic calculatePowNode;
 
@@ -107,12 +95,8 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "sin", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Sin extends UnaryArithmeticBuiltinNode {
-
-        public Sin() {
-            super(RType.Double);
-        }
+    @RBuiltin(name = "sin", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Sin extends UnaryArithmetic {
 
         @Override
         public double op(double op) {
@@ -127,12 +111,8 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "sinh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Sinh extends UnaryArithmeticBuiltinNode {
-
-        public Sinh() {
-            super(RType.Double);
-        }
+    @RBuiltin(name = "sinh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Sinh extends UnaryArithmetic {
 
         @Override
         public double op(double op) {
@@ -147,13 +127,8 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "sinpi", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Sinpi extends UnaryArithmeticBuiltinNode {
-
-        public Sinpi() {
-            super(RType.Double);
-        }
-
+    @RBuiltin(name = "sinpi", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Sinpi extends UnaryArithmetic {
         @Override
         public double op(double op) {
             double norm = op % 2d;
@@ -168,15 +143,15 @@ public class TrigExpFunctions {
             }
             return Math.sin(norm * Math.PI);
         }
-    }
-
-    @RBuiltin(name = "cos", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Cos extends UnaryArithmeticBuiltinNode {
 
-        public Cos() {
-            super(RType.Double);
+        @Override
+        public RComplex op(double re, double im) {
+            throw error(Message.UNIMPLEMENTED_COMPLEX_FUN);
         }
+    }
 
+    @RBuiltin(name = "cos", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Cos extends UnaryArithmetic {
         @Override
         public double op(double op) {
             return Math.cos(op);
@@ -190,13 +165,8 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "cosh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Cosh extends UnaryArithmeticBuiltinNode {
-
-        public Cosh() {
-            super(RType.Double);
-        }
-
+    @RBuiltin(name = "cosh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Cosh extends UnaryArithmetic {
         @Override
         public double op(double op) {
             return Math.cosh(op);
@@ -210,13 +180,8 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "cospi", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Cospi extends UnaryArithmeticBuiltinNode {
-
-        public Cospi() {
-            super(RType.Double);
-        }
-
+    @RBuiltin(name = "cospi", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Cospi extends UnaryArithmetic {
         @Override
         public double op(double op) {
             double norm = op % 2d;
@@ -238,15 +203,10 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "tan", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Tan extends UnaryArithmeticBuiltinNode {
-
-        public Tan() {
-            super(RType.Double);
-        }
-
-        @Child private Sin sinNode = SinNodeGen.create();
-        @Child private Cos cosNode = CosNodeGen.create();
+    @RBuiltin(name = "tan", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Tan extends UnaryArithmetic {
+        @Child private Sin sinNode = new Sin();
+        @Child private Cos cosNode = new Cos();
 
         @Override
         public double op(double op) {
@@ -264,14 +224,9 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "tanh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Tanh extends UnaryArithmeticBuiltinNode {
-
-        public Tanh() {
-            super(RType.Double);
-        }
-
-        @Child private Tan tanNode = TanNodeGen.create();
+    @RBuiltin(name = "tanh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Tanh extends UnaryArithmetic {
+        @Child private Tan tanNode = new Tan();
 
         @Override
         public double op(double op) {
@@ -285,13 +240,8 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "tanpi", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Tanpi extends UnaryArithmeticBuiltinNode {
-
-        public Tanpi() {
-            super(RType.Double);
-        }
-
+    @RBuiltin(name = "tanpi", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Tanpi extends UnaryArithmetic {
         @Override
         public double op(double op) {
             double norm = op % 1d;
@@ -310,15 +260,11 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "asin", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Asin extends UnaryArithmeticBuiltinNode {
+    @RBuiltin(name = "asin", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Asin extends UnaryArithmetic {
 
         @Child private CHypot chypot;
 
-        public Asin() {
-            super(RType.Double);
-        }
-
         private void ensureChypot() {
             if (chypot == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -369,14 +315,9 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "asinh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Asinh extends UnaryArithmeticBuiltinNode {
-
-        @Child private Asin asinNode = AsinNodeGen.create();
-
-        public Asinh() {
-            super(RType.Double);
-        }
+    @RBuiltin(name = "asinh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Asinh extends UnaryArithmetic {
+        @Child private Asin asinNode = new Asin();
 
         @Override
         public double op(double x) {
@@ -390,14 +331,9 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "acos", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Acos extends UnaryArithmeticBuiltinNode {
-
-        public Acos() {
-            super(RType.Double);
-        }
-
-        @Child private Asin asinNode = AsinNodeGen.create();
+    @RBuiltin(name = "acos", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Acos extends UnaryArithmetic {
+        @Child private Asin asinNode = new Asin();
 
         @Override
         public double op(double op) {
@@ -411,14 +347,10 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "acosh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Acosh extends UnaryArithmeticBuiltinNode {
+    @RBuiltin(name = "acosh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Acosh extends UnaryArithmetic {
 
-        public Acosh() {
-            super(RType.Double);
-        }
-
-        @Child private Acos acosNode = AcosNodeGen.create();
+        @Child private Acos acosNode = new Acos();
 
         @Override
         public double op(double x) {
@@ -432,13 +364,8 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "atan", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Atan extends UnaryArithmeticBuiltinNode {
-
-        public Atan() {
-            super(RType.Double);
-        }
-
+    @RBuiltin(name = "atan", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Atan extends UnaryArithmetic {
         @Override
         public double op(double x) {
             return Math.atan(x);
@@ -462,14 +389,10 @@ public class TrigExpFunctions {
         }
     }
 
-    @RBuiltin(name = "atanh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-    public abstract static class Atanh extends UnaryArithmeticBuiltinNode {
-
-        public Atanh() {
-            super(RType.Double);
-        }
+    @RBuiltin(name = "atanh", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+    public static final class Atanh extends UnaryArithmetic {
 
-        @Child private Atan atanNode = AtanNodeGen.create();
+        @Child private Atan atanNode = new Atan();
 
         @Override
         public double op(double x) {
@@ -492,19 +415,12 @@ public class TrigExpFunctions {
 
         private final NACheck yNACheck = NACheck.create();
         private final NACheck xNACheck = NACheck.create();
+        private final LoopConditionProfile profile = LoopConditionProfile.createCountingProfile();
 
         static {
             Casts casts = new Casts(Atan2.class);
-            casts.arg(0).mapIf(numericValue(), asDoubleVector());
-            casts.arg(1).mapIf(numericValue(), asDoubleVector());
-        }
-
-        private double doFunDouble(double y, double x) {
-            double result = x;
-            if (!yNACheck.check(y) && !xNACheck.check(x)) {
-                result = Math.atan2(y, x);
-            }
-            return result;
+            casts.arg(0).mapIf(numericValue(), asDoubleVector(true, true, true));
+            casts.arg(1).mapIf(numericValue(), asDoubleVector(true, true, true));
         }
 
         @FunctionalInterface
@@ -513,20 +429,13 @@ public class TrigExpFunctions {
             double apply(int i);
         }
 
-        private RDoubleVector doFun(int length, IntDoubleFunction yFun, IntDoubleFunction xFun,
-                        LoopConditionProfile profile) {
-            double[] resultVector = new double[length];
+        private double[] prepareArray(int length) {
             reportWork(length);
             profile.profileCounted(length);
-            for (int i = 0; profile.inject(i < length); i++) {
-                double y = yFun.apply(i);
-                double x = xFun.apply(i);
-                if (xNACheck.check(y) || yNACheck.check(x)) {
-                    resultVector[i] = RRuntime.DOUBLE_NA;
-                } else {
-                    resultVector[i] = Math.atan2(y, x);
-                }
-            }
+            return new double[length];
+        }
+
+        private RDoubleVector createResult(double[] resultVector) {
             return RDataFactory.createDoubleVector(resultVector, xNACheck.neverSeenNA() && yNACheck.neverSeenNA());
         }
 
@@ -534,47 +443,97 @@ public class TrigExpFunctions {
         protected double atan2(double y, double x) {
             xNACheck.enable(x);
             yNACheck.enable(y);
-            return doFunDouble(y, x);
+            if (yNACheck.check(y) || xNACheck.check(x)) {
+                return RRuntime.DOUBLE_NA;
+            } else {
+                return Math.atan2(y, x);
+            }
         }
 
-        @Specialization
+        @Specialization(guards = "x.getLength() > 0")
         protected RDoubleVector atan2(double y, RAbstractDoubleVector x,
-                        @Cached("createCountingProfile()") LoopConditionProfile profile) {
+                        @Cached("create()") UnaryCopyAttributesNode copyAttributesNode,
+                        @Cached("createBinaryProfile()") ConditionProfile xLengthProfile) {
             xNACheck.enable(x);
             yNACheck.enable(y);
-            return doFun(x.getLength(), i -> y, i -> x.getDataAt(i), profile);
+            double[] array = prepareArray(x.getLength());
+            for (int i = 0; profile.inject(i < array.length); i++) {
+                double xValue = x.getDataAt(i);
+                if (xNACheck.check(y) || yNACheck.check(xValue)) {
+                    array[i] = RRuntime.DOUBLE_NA;
+                } else {
+                    array[i] = Math.atan2(y, xValue);
+                }
+            }
+            RDoubleVector result = createResult(array);
+            if (xLengthProfile.profile(result.getLength() == x.getLength())) {
+                copyAttributesNode.execute(result, x);
+            }
+            return result;
         }
 
-        @Specialization
+        @Specialization(guards = "y.getLength() > 0")
         protected RDoubleVector atan2(RAbstractDoubleVector y, double x,
-                        @Cached("createCountingProfile()") LoopConditionProfile profile) {
+                        @Cached("create()") UnaryCopyAttributesNode copyAttributesNode,
+                        @Cached("createBinaryProfile()") ConditionProfile yLengthProfile) {
             xNACheck.enable(x);
             yNACheck.enable(y);
-            return doFun(y.getLength(), i -> y.getDataAt(i), i -> x, profile);
+            double[] array = prepareArray(y.getLength());
+            for (int i = 0; profile.inject(i < array.length); i++) {
+                double yValue = y.getDataAt(i);
+                if (xNACheck.check(yValue) || yNACheck.check(x)) {
+                    array[i] = RRuntime.DOUBLE_NA;
+                } else {
+                    array[i] = Math.atan2(yValue, x);
+                }
+            }
+            RDoubleVector result = createResult(array);
+            if (yLengthProfile.profile(result.getLength() == y.getLength())) {
+                copyAttributesNode.execute(result, y);
+            }
+            return result;
         }
 
-        @Specialization
+        @Specialization(guards = {"y.getLength() > 0", "x.getLength() > 0"})
         protected RDoubleVector atan2(RAbstractDoubleVector y, RAbstractDoubleVector x,
-                        @Cached("createCountingProfile()") LoopConditionProfile profile) {
+                        @Cached("create()") UnaryCopyAttributesNode copyAttributesNode,
+                        @Cached("createBinaryProfile()") ConditionProfile yLengthProfile) {
             int xLength = x.getLength();
             int yLength = y.getLength();
             xNACheck.enable(x);
             yNACheck.enable(y);
-            return doFun(Math.max(yLength, xLength), i -> y.getDataAt(i % yLength), i -> x.getDataAt(i % xLength),
-                            profile);
+            double[] array = prepareArray(Math.max(yLength, xLength));
+            for (int i = 0; profile.inject(i < array.length); i++) {
+                double yValue = y.getDataAt(i % yLength);
+                double xValue = x.getDataAt(i % xLength);
+                if (xNACheck.check(yValue) || yNACheck.check(xValue)) {
+                    array[i] = RRuntime.DOUBLE_NA;
+                } else {
+                    array[i] = Math.atan2(yValue, xValue);
+                }
+            }
+            RDoubleVector result = createResult(array);
+            if (yLengthProfile.profile(result.getLength() == y.getLength())) {
+                copyAttributesNode.execute(result, y);
+            } else {
+                assert (result.getLength() == x.getLength()) : "Result length=" + result.getLength() + " != x.getLength()=" + x.getLength();
+                copyAttributesNode.execute(result, x);
+            }
+            return result;
+        }
+
+        @Specialization(guards = "y.getLength() == 0 || x.getLength() == 0")
+        protected RDoubleVector atan2Empty(@SuppressWarnings("unused") RAbstractDoubleVector y, @SuppressWarnings("unused") RAbstractDoubleVector x) {
+            return RDataFactory.createEmptyDoubleVector();
         }
 
-        @Specialization(guards = {"!isDouble(x) || !isDouble(y)"})
-        @TruffleBoundary
+        @Fallback
         protected Object atan2(Object x, Object y) {
+            CompilerDirectives.transferToInterpreter();
             if (x instanceof RAbstractComplexVector || y instanceof RAbstractComplexVector) {
                 throw RInternalError.unimplemented("atan2 for complex values");
             }
             throw error(RError.Message.NON_NUMERIC_MATH);
         }
-
-        protected static boolean isDouble(Object x) {
-            return x instanceof Double || x instanceof RAbstractDoubleVector;
-        }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
index 6f499ded2d781c258e95c69f223582d9d1d8a810..7cc77fc5a68beca55a1a37d3001f7b3b99cfe2f8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Trunc.java
@@ -22,51 +22,25 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.complexValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.runtime.RDispatch.MATH_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
-import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
-import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
-import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
-@RBuiltin(name = "trunc", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE)
-public abstract class Trunc extends RBuiltinNode.Arg1 {
+@RBuiltin(name = "trunc", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = MATH_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
+public final class Trunc extends UnaryArithmetic {
 
-    private static final UnaryArithmeticFactory TRUNC = TruncArithmetic::new;
+    public static final UnaryArithmeticFactory TRUNC = Trunc::new;
 
-    @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
-    @Child private UnaryArithmeticNode trunc = UnaryArithmeticNodeGen.create(TRUNC, RError.Message.NON_NUMERIC_MATH, RType.Double);
-
-    static {
-        Casts casts = new Casts(Trunc.class);
-        casts.arg("x").defaultError(RError.Message.NON_NUMERIC_MATH).mustNotBeNull().mustBe(complexValue().not(), RError.Message.UNIMPLEMENTED_COMPLEX_FUN).mustBe(numericValue()).asDoubleVector(true,
-                        true, true);
-    }
-
-    @Specialization
-    protected Object trunc(Object value) {
-        return trunc.execute(boxPrimitive.execute(value));
-    }
-
-    private static final class TruncArithmetic extends Round.RoundArithmetic {
-
-        @Override
-        public double op(double op) {
-            if (op > 0) {
-                return Math.floor(op);
-            } else {
-                return Math.ceil(op);
-            }
+    @Override
+    public double op(double op) {
+        if (op > 0) {
+            return Math.floor(op);
+        } else {
+            return Math.ceil(op);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
index aeee8fa4fe146c22d85af9c824d5cb1261411b31..626821a38aa55082fb3aaa99c9751aa448a45d17 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unlist.java
@@ -17,17 +17,29 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.ArityException;
+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.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.UnlistNodeGen.RecursiveLengthNodeGen;
+import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.nodes.unary.PrecedenceNode;
 import com.oracle.truffle.r.nodes.unary.PrecedenceNodeGen;
 import com.oracle.truffle.r.runtime.RDispatch;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
@@ -44,8 +56,13 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypes;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 
+@ImportStatic({Message.class, RRuntime.class})
 @RBuiltin(name = "unlist", kind = INTERNAL, dispatch = RDispatch.INTERNAL_GENERIC, parameterNames = {"x", "recursive", "use.names"}, behavior = PURE)
 public abstract class Unlist extends RBuiltinNode.Arg3 {
 
@@ -58,20 +75,23 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
     }
 
     @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create();
-    @Child private Length lengthNode;
+    @Child private RLengthNode lengthNode;
     @Child private RecursiveLength recursiveLengthNode;
     @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
+    @Child private Node hasSizeNode;
+    @Child private ForeignArray2R foreignArray2RNode;
 
+    @ImportStatic({Message.class, RRuntime.class, ForeignArray2R.class})
     @TypeSystemReference(RTypes.class)
     protected abstract static class RecursiveLength extends Node {
 
-        public abstract int executeInt(VirtualFrame frame, Object vector);
+        public abstract int execute(Object vector);
 
         @Child private RecursiveLength recursiveLengthNode;
 
-        private int getRecursiveLength(VirtualFrame frame, Object operand) {
+        private int getRecursiveLength(Object operand) {
             initRecursiveLengthNode();
-            return recursiveLengthNode.executeInt(frame, operand);
+            return recursiveLengthNode.execute(operand);
         }
 
         private void initRecursiveLengthNode() {
@@ -109,44 +129,106 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
         }
 
         @Specialization(guards = "isVectorList(vector)")
-        protected int getLengthList(VirtualFrame frame, RAbstractVector vector) {
+        protected int getLengthList(RAbstractVector vector) {
             int totalSize = 0;
             for (int i = 0; i < vector.getLength(); i++) {
                 Object data = vector.getDataAtAsObject(i);
-                totalSize += getRecursiveLength(frame, data);
+                totalSize += getRecursiveLength(data);
             }
             return totalSize;
         }
 
+        protected boolean isVectorList(RAbstractVector vector) {
+            return vector instanceof RList;
+        }
+
         @Specialization
-        protected int getLengthPairList(VirtualFrame frame, RPairList list) {
+        protected int getLengthPairList(RPairList list) {
             int totalSize = 0;
             for (RPairList item : list) {
-                totalSize += getRecursiveLength(frame, item.car());
+                totalSize += getRecursiveLength(item.car());
             }
             return totalSize;
         }
 
-        protected boolean isVectorList(RAbstractVector vector) {
-            return vector instanceof RList;
+        @Specialization(guards = {"isForeignArray(obj, hasSize)"})
+        protected int getForeignArrayLength(TruffleObject obj,
+                        @Cached("READ.createNode()") Node read,
+                        @SuppressWarnings("unused") @Cached("HAS_SIZE.createNode()") Node hasSize,
+                        @Cached("GET_SIZE.createNode()") Node getSize,
+                        @Cached("createForeign2R()") Foreign2R foreign2R) {
+            int totalSize = 0;
+            try {
+                int size = (int) ForeignAccess.sendGetSize(getSize, obj);
+
+                if (JavaInterop.isJavaObject(obj)) {
+                    Object o = JavaInterop.asJavaObject(Object.class, obj);
+                    Class<?> ct = o.getClass().getComponentType();
+                    // check array component type, if not array of:
+                    // arrays, iterables or Objects then no need to recurse
+
+                    // TODO well that is not exactly correct, but would be quite crazy
+                    if (!(ct.isArray() || ct.isAssignableFrom(Iterable.class) || ct == Object.class)) {
+                        return size;
+                    }
+                }
+
+                for (int i = 0; i < size; i++) {
+                    Object element = ForeignAccess.sendRead(read, obj, i);
+                    element = foreign2R.execute(element);
+                    totalSize += getRecursiveLength(element);
+                }
+            } catch (UnknownIdentifierException | UnsupportedMessageException ex) {
+                throw RError.interopError(RError.findParentRBase(this), ex, obj);
+            }
+            return totalSize;
+        }
+
+        @Specialization(guards = {"isJavaIterable(obj)"})
+        protected int getJavaIterableLength(TruffleObject obj,
+                        @Cached("READ.createNode()") Node read,
+                        @Cached("createExecute(0).createNode()") Node execute,
+                        @Cached("createForeign2R()") Foreign2R foreign2R) {
+            int totalSize = 0;
+            try {
+                TruffleObject itFunction = (TruffleObject) ForeignAccess.sendRead(read, obj, "iterator");
+                TruffleObject it = (TruffleObject) ForeignAccess.sendExecute(execute, itFunction);
+                TruffleObject hasNextFunction = (TruffleObject) ForeignAccess.sendRead(read, it, "hasNext");
+
+                while ((boolean) ForeignAccess.sendExecute(execute, hasNextFunction)) {
+                    TruffleObject nextFunction = (TruffleObject) ForeignAccess.sendRead(read, it, "next");
+                    Object element = ForeignAccess.sendExecute(execute, nextFunction);
+                    element = foreign2R.execute(element);
+                    totalSize += getRecursiveLength(element);
+                }
+            } catch (ArityException | UnsupportedTypeException | UnsupportedMessageException | UnknownIdentifierException ex) {
+                throw RError.interopError(RError.findParentRBase(this), ex, obj);
+            }
+            return totalSize;
+        }
+
+        @Specialization(guards = {"isForeignObject(obj)", "!isForeignArray(obj, hasSize)", "!isJavaIterable(obj)"})
+        protected int getForeignObject(@SuppressWarnings("unused") TruffleObject obj,
+                        @SuppressWarnings("unused") @Cached("HAS_SIZE.createNode()") Node hasSize) {
+            return 1;
         }
     }
 
-    private int getLength(VirtualFrame frame, Object operand) {
+    private int getLength(Object operand) {
         initLengthNode();
-        return lengthNode.executeInt(frame, operand);
+        return lengthNode.executeInteger(operand);
     }
 
     private void initLengthNode() {
         if (lengthNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            lengthNode = insert(LengthNodeGen.create());
+            lengthNode = insert(RLengthNode.create());
         }
     }
 
-    private int getRecursiveLength(VirtualFrame frame, Object operand) {
+    private int getRecursiveLength(Object operand) {
         initRecursiveLengthNode();
-        return recursiveLengthNode.executeInt(frame, operand);
+        return recursiveLengthNode.execute(operand);
     }
 
     private void initRecursiveLengthNode() {
@@ -177,16 +259,16 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
     // TODO: initially unlist was on the slow path - hence initial recursive implementation is on
     // the slow path as well; ultimately we may consider (non-recursive) optimization
     @Specialization(guards = "!isEmpty(list)")
-    protected Object unlistList(VirtualFrame frame, RList list, boolean recursive, boolean useNames) {
+    protected Object unlistList(RList list, boolean recursive, boolean useNames) {
         int precedence = PrecedenceNode.NO_PRECEDENCE;
         int totalSize = 0;
         for (int i = 0; i < list.getLength(); i++) {
             Object data = list.getDataAt(i);
             precedence = Math.max(precedence, precedenceNode.executeInteger(data, recursive));
             if (recursive) {
-                totalSize += getRecursiveLength(frame, data);
+                totalSize += getRecursiveLength(data);
             } else {
-                totalSize += getLength(frame, data);
+                totalSize += getLength(data);
             }
         }
         // If the precedence is still NO_PRECEDENCE the result is RNull.instance
@@ -198,11 +280,37 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
     }
 
     @Specialization(guards = "!isEmpty(list)")
-    protected Object unlistPairList(VirtualFrame frame, RPairList list, boolean recursive, boolean useNames) {
+    protected Object unlistPairList(RPairList list, boolean recursive, boolean useNames) {
         // TODO: unlist((pairlist(pairlist(1)), recursive=FALSE), see unit tests
         // Note: currently, we convert to list any pair-list that we encounter along the way, this
         // is sub-optimal, but the assumption is that pair-lists do not show up a lot
-        return unlistList(frame, list.toRList(), recursive, useNames);
+        return unlistList(list.toRList(), recursive, useNames);
+    }
+
+    @Specialization(guards = {"isForeignArray(obj)"})
+    protected Object unlistForeignArray(VirtualFrame frame, TruffleObject obj, boolean recursive, boolean useNames,
+                    @SuppressWarnings("unused") @Cached("HAS_SIZE.createNode()") Node hasSize,
+                    @Cached("createForeignArray2R()") ForeignArray2R foreignArray2R) {
+        return unlistForeign(frame, obj, recursive, useNames, foreignArray2R);
+    }
+
+    @Specialization(guards = {"isJavaIterable(obj)"})
+    protected Object unlistJavaIterable(VirtualFrame frame, TruffleObject obj, boolean recursive, boolean useNames,
+                    @Cached("createForeignArray2R()") ForeignArray2R foreignArray2R) {
+        return unlistForeign(frame, obj, recursive, useNames, foreignArray2R);
+    }
+
+    private Object unlistForeign(VirtualFrame frame, TruffleObject obj, boolean recursive, boolean useNames, ForeignArray2R foreignArray2R) {
+        Object result = foreignArray2R.execute(obj, recursive);
+        if (result instanceof RAbstractListVector) {
+            result = execute(frame, result, recursive, useNames);
+        }
+        return result;
+    }
+
+    @Specialization(guards = {"isForeignObject(obj)", "!isForeignVector(obj)"})
+    protected Object unlistForeign(TruffleObject obj, @SuppressWarnings("unused") boolean recursive, @SuppressWarnings("unused") boolean useNames) {
+        return obj;
     }
 
     @SuppressWarnings("unused")
@@ -211,6 +319,48 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
         return o;
     }
 
+    protected ForeignArray2R createForeignArray2R() {
+        return ForeignArray2RNodeGen.create();
+    }
+
+    protected boolean isForeignVector(Object obj) {
+        return ForeignArray2R.isForeignVector(obj, getHasSizeNode());
+    }
+
+    protected boolean isJavaIterable(Object obj) {
+        return ForeignArray2R.isJavaIterable(obj);
+    }
+
+    protected boolean isForeignArray(Object obj) {
+        return ForeignArray2R.isForeignArray(obj, getHasSizeNode());
+    }
+
+    /**
+     * Converts foreign object to RAbstractVector.
+     *
+     * @param obj the foreign object. Has to be ensured it is a foreign array or java iterable.
+     */
+    private RAbstractVector foreignToVector(TruffleObject obj, boolean recursive) {
+        assert isForeignVector(obj);
+        return (RAbstractVector) getForeignArray2RNode().execute(obj, recursive);
+    }
+
+    private ForeignArray2R getForeignArray2RNode() {
+        if (foreignArray2RNode == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            foreignArray2RNode = insert(ForeignArray2R.createForeignArray2R());
+        }
+        return foreignArray2RNode;
+    }
+
+    private Node getHasSizeNode() {
+        if (hasSizeNode == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            hasSizeNode = insert(Message.HAS_SIZE.createNode());
+        }
+        return hasSizeNode;
+    }
+
     @TruffleBoundary
     private RAbstractVector unlistHelper(RList list, boolean recursive, boolean useNames, int precedence, int totalSize) {
         String[] namesData = useNames ? new String[totalSize] : null;
@@ -418,13 +568,17 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
             for (int i = 0; i < v.getLength(); i++) {
                 String name = itemName(listNames, i);
                 Object cur = v.getDataAtAsObject(i);
-                if (v instanceof RList && recursive) {
+                if (RRuntime.isForeignObject(cur)) {
+                    position = unlistHelperForeignLogical(result, position, (TruffleObject) cur, recursive);
+                } else if (v instanceof RList && recursive) {
                     position = unlistHelperLogical(result, namesData, position, namesInfo, cur, base, name, recursive, useNames);
                 } else {
                     assignName(name, base, position, namesData, namesInfo, useNames);
                     result[position++] = unlistValueLogical(cur);
                 }
             }
+        } else if (RRuntime.isForeignObject(o)) {
+            position = unlistHelperForeignLogical(result, position, (TruffleObject) o, recursive);
         } else if (o != RNull.instance) {
             assignName(null, base, position, namesData, namesInfo, useNames);
             result[position++] = unlistValueLogical(o);
@@ -456,13 +610,17 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
             for (int i = 0; i < v.getLength(); i++) {
                 String name = itemName(listNames, i);
                 Object cur = v.getDataAtAsObject(i);
-                if (v instanceof RList && recursive) {
+                if (RRuntime.isForeignObject(cur)) {
+                    position = unlistHelperForeignInt(result, position, (TruffleObject) cur, recursive);
+                } else if (v instanceof RList && recursive) {
                     position = unlistHelperInt(result, namesData, position, namesInfo, cur, base, name, recursive, useNames);
                 } else {
                     assignName(name, base, position, namesData, namesInfo, useNames);
                     result[position++] = unlistValueInt(cur);
                 }
             }
+        } else if (RRuntime.isForeignObject(o)) {
+            position = unlistHelperForeignInt(result, position, (TruffleObject) o, recursive);
         } else if (o != RNull.instance) {
             assignName(null, base, position, namesData, namesInfo, useNames);
             result[position++] = unlistValueInt(o);
@@ -494,13 +652,17 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
             for (int i = 0; i < v.getLength(); i++) {
                 String name = itemName(listNames, i);
                 Object cur = v.getDataAtAsObject(i);
-                if (v instanceof RList && recursive) {
+                if (RRuntime.isForeignObject(cur)) {
+                    position = unlistHelperForeignDouble(result, position, (TruffleObject) cur, recursive);
+                } else if (v instanceof RList && recursive) {
                     position = unlistHelperDouble(result, namesData, position, namesInfo, cur, base, name, recursive, useNames);
                 } else {
                     assignName(name, base, position, namesData, namesInfo, useNames);
                     result[position++] = unlistValueDouble(cur);
                 }
             }
+        } else if (RRuntime.isForeignObject(o)) {
+            position = unlistHelperForeignDouble(result, position, (TruffleObject) o, recursive);
         } else if (o != RNull.instance) {
             assignName(null, base, position, namesData, namesInfo, useNames);
             result[position++] = unlistValueDouble(o);
@@ -553,7 +715,12 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
 
     @TruffleBoundary
     private int unlistHelperList(Object[] result, String[] namesData, int pos, NamesInfo namesInfo, Object obj, String outerBase, String tag, boolean recursive, boolean useNames) {
-        Object o = handlePairList(obj);
+        Object o;
+        if (isForeignVector(obj)) {
+            o = foreignToVector((TruffleObject) obj, recursive);
+        } else {
+            o = handlePairList(obj);
+        }
         int position = pos;
         int saveFirstPos = 0;
         int saveSeqNo = 0;
@@ -574,7 +741,9 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
             for (int i = 0; i < v.getLength(); i++) {
                 String name = itemName(listNames, i);
                 Object cur = v.getDataAtAsObject(i);
-                if (v instanceof RList && recursive) {
+                if (recursive && isForeignVector(obj)) {
+                    position = unlistHelperForeign(result, position, (TruffleObject) cur, recursive);
+                } else if (v instanceof RList && recursive) {
                     position = unlistHelperList(result, namesData, position, namesInfo, cur, base, name, recursive, useNames);
                 } else {
                     assignName(name, base, position, namesData, namesInfo, useNames);
@@ -589,6 +758,91 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
         return position;
     }
 
+    @TruffleBoundary
+    private int unlistHelperForeign(Object[] result, int pos, TruffleObject obj, boolean recursive) {
+        int position = pos;
+        if (recursive && isForeignVector(obj)) {
+            RAbstractVector v = foreignToVector(obj, recursive);
+            for (int i = 0; i < v.getLength(); i++) {
+                Object cur = v.getDataAtAsObject(i);
+                if (isForeignVector(cur)) {
+                    position = unlistHelperForeign(result, position, (TruffleObject) cur, recursive);
+                } else {
+                    result[position++] = cur;
+                }
+            }
+        }
+        return position;
+    }
+
+    @TruffleBoundary
+    private int unlistHelperForeignLogical(byte[] result, int pos, TruffleObject obj, boolean recursive) {
+        int position = pos;
+        RAbstractVector v = foreignToVector(obj, recursive);
+        for (int i = 0; i < v.getLength(); i++) {
+            Object cur = v.getDataAtAsObject(i);
+            if (!RRuntime.isForeignObject(cur)) {
+                result[position++] = unlistValueLogical(cur);
+            } else if (recursive && isForeignVector(cur)) {
+                position = unlistHelperForeignLogical(result, position, (TruffleObject) cur, recursive);
+            } else {
+                assert false : "recursive=" + recursive + ", isIterable=" + ForeignArray2R.isJavaIterable(cur) + ", isArray=" + isForeignArray(cur);
+            }
+        }
+        return position;
+    }
+
+    @TruffleBoundary
+    private int unlistHelperForeignInt(int[] result, int pos, TruffleObject obj, boolean recursive) {
+        int position = pos;
+        RAbstractVector v = foreignToVector(obj, recursive);
+        for (int i = 0; i < v.getLength(); i++) {
+            Object cur = v.getDataAtAsObject(i);
+            if (!RRuntime.isForeignObject(cur)) {
+                result[position++] = unlistValueInt(cur);
+            } else if (recursive && isForeignVector(cur)) {
+                position = unlistHelperForeignInt(result, position, (TruffleObject) cur, recursive);
+            } else {
+                assert false : "recursive=" + recursive + ", isIterable=" + ForeignArray2R.isJavaIterable(cur) + ", isArray=" + isForeignArray(cur);
+            }
+        }
+        return position;
+    }
+
+    @TruffleBoundary
+    private int unlistHelperForeignDouble(double[] result, int pos, TruffleObject obj, boolean recursive) {
+        int position = pos;
+        RAbstractVector v = foreignToVector(obj, recursive);
+        for (int i = 0; i < v.getLength(); i++) {
+            Object cur = v.getDataAtAsObject(i);
+            if (!RRuntime.isForeignObject(cur)) {
+                result[position++] = unlistValueDouble(cur);
+            } else if (recursive && isForeignVector(cur)) {
+                position = unlistHelperForeignDouble(result, position, (TruffleObject) cur, recursive);
+            } else {
+                assert false : "recursive=" + recursive + ", isIterable=" + ForeignArray2R.isJavaIterable(cur) + ", isArray=" + isForeignArray(cur);
+            }
+        }
+        return position;
+    }
+
+    @TruffleBoundary
+    private int unlistHelperForeignString(String[] result, int pos, TruffleObject obj, boolean recursive) {
+        int position = pos;
+        RAbstractVector v = foreignToVector(obj, recursive);
+        for (int i = 0; i < v.getLength(); i++) {
+            Object cur = v.getDataAtAsObject(i);
+            if (!RRuntime.isForeignObject(cur)) {
+                result[position++] = unlistValueString(cur);
+            } else if (recursive && isForeignVector(cur)) {
+                position = unlistHelperForeignString(result, position, (TruffleObject) cur, recursive);
+            } else {
+                assert false : "recursive=" + recursive + ", isIterable=" + ForeignArray2R.isJavaIterable(cur) + ", isArray=" + isForeignArray(cur);
+            }
+        }
+        return position;
+    }
+
     @TruffleBoundary
     private int unlistHelperString(String[] result, String[] namesData, int pos, NamesInfo namesInfo, Object oIn, String outerBase, String tag, boolean recursive, boolean useNames) {
         int position = pos;
@@ -612,13 +866,17 @@ public abstract class Unlist extends RBuiltinNode.Arg3 {
             for (int i = 0; i < v.getLength(); i++) {
                 String name = itemName(listNames, i);
                 Object cur = v.getDataAtAsObject(i);
-                if (v instanceof RList && recursive) {
+                if (RRuntime.isForeignObject(cur)) {
+                    position = unlistHelperForeignString(result, position, (TruffleObject) cur, recursive);
+                } else if (v instanceof RList && recursive) {
                     position = unlistHelperString(result, namesData, position, namesInfo, cur, base, name, recursive, useNames);
                 } else {
                     assignName(name, base, position, namesData, namesInfo, useNames);
                     result[position++] = unlistValueString(v.getDataAtAsObject(i));
                 }
             }
+        } else if (RRuntime.isForeignObject(o)) {
+            position = unlistHelperForeignString(result, position, (TruffleObject) o, recursive);
         } else if (o != RNull.instance) {
             assignName(null, base, position, namesData, namesInfo, useNames);
             result[position++] = unlistValueString(o);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index c28a5e5175b19cd4c05ea67391d872e3e04005b1..fc662f9acea716e14fc6c82927acfe1f593a609d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode;
@@ -50,8 +49,10 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RRaw;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
@@ -247,16 +248,14 @@ public abstract class UpdateAttributes extends RBuiltinNode.Arg2 {
      * All other, non-performance centric, {@link RAttributable} types, or error case for RNull
      * value.
      */
-    @Fallback
+    @Specialization(guards = "!isRAbstractContainer(o)")
     @TruffleBoundary
-    protected Object doOtherNull(Object o, Object operand) {
-        checkAttributable(o);
-        Object obj = getNonShared(o);
-        RAttributable attrObj = (RAttributable) obj;
-        attrObj.removeAllAttributes();
+    protected Object doOtherNull(RAttributable o, Object operand) {
+        RAttributable obj = getNonShared(o);
+        obj.removeAllAttributes();
 
         if (operand == RNull.instance) {
-            attrObj.setClassAttr(null);
+            obj.setClassAttr(null);
         } else {
             RList list = (RList) operand;
             RStringVector listNames = list.getNames();
@@ -273,24 +272,27 @@ public abstract class UpdateAttributes extends RBuiltinNode.Arg2 {
                     if (attrValue == null) {
                         throw error(RError.Message.SET_INVALID_CLASS_ATTR);
                     }
-                    attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue));
+                    obj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue));
                 } else {
-                    attrObj.setAttr(attrName.intern(), list.getDataAt(i));
+                    obj.setAttr(attrName.intern(), list.getDataAt(i));
                 }
             }
         }
         return obj;
     }
 
-    private void checkAttributable(Object obj) {
-        if (!(obj instanceof RAttributable)) {
-            throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
-        }
+    @Specialization(guards = {"!isRAttributable(o)", "!isScalar(o)"})
+    protected Object doFallback(@SuppressWarnings("unused") Object o, @SuppressWarnings("unused") Object operand) {
+        throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
+    }
+
+    protected static boolean isScalar(Object o) {
+        return o instanceof Integer || o instanceof Double || o instanceof Byte || o instanceof RRaw || o instanceof RComplex;
     }
 
-    private static Object getNonShared(Object obj) {
+    private static RAttributable getNonShared(RAttributable obj) {
         if (obj instanceof RShareable) {
-            return ((RShareable) obj).getNonShared();
+            return (RAttributable) ((RShareable) obj).getNonShared();
         }
         return obj;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
index b32345f7ff7d7d80c006a9356eaf8cdabfcf0617..e45147319f4d1608535cd35788ef28dc61a80b2f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java
@@ -90,7 +90,7 @@ public abstract class UpdateClass extends RBuiltinNode.Arg2 {
         if (!getClassNode.isObject(arg)) {
             initTypeof();
             RType argType = typeof.execute(arg);
-            if (argType.equals(className) || (mode == RType.Double && (argType == RType.Integer || argType == RType.Double))) {
+            if (argType.getClazz().equals(className) || (mode == RType.Double && (argType == RType.Integer || argType == RType.Double))) {
                 // "explicit" attribute might have been set (e.g. by oldClass<-)
                 return setClass(arg, RNull.instance);
             }
@@ -127,7 +127,16 @@ public abstract class UpdateClass extends RBuiltinNode.Arg2 {
         return result;
     }
 
-    @Specialization
+    @Specialization(guards = "className.getLength() == 1")
+    @TruffleBoundary
+    protected Object setClassLengthOne(RAbstractContainer arg, RStringVector className,
+                    @Cached("create()") TypeFromModeNode typeFromMode,
+                    @Cached("create()") GetClassAttributeNode getClassNode) {
+        RType mode = typeFromMode.execute(className.getDataAt(0));
+        return setClassInternal(arg, className.getDataAt(0), mode, getClassNode);
+    }
+
+    @Specialization(guards = "className.getLength() != 1")
     @TruffleBoundary
     protected Object setClass(RAbstractContainer arg, RStringVector className) {
         RAbstractContainer result = reuseNonShared(arg);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
index d161c6383775de582b12f109d93730547cc9aede..851e8053676665a50ea3523d3b4f979016d563d7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClass
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -89,4 +90,14 @@ public abstract class UpdateOldClass extends RBuiltinNode.Arg2 {
         setClassAttributeNode.reset(result);
         return result;
     }
+
+    @Specialization
+    protected Object setOldClass(@SuppressWarnings("unused") RNull arg, @SuppressWarnings("unused") RNull className) {
+        return RNull.instance;
+    }
+
+    @Specialization
+    protected Object setOldClass(@SuppressWarnings("unused") RNull arg, @SuppressWarnings("unused") Object className) {
+        throw error(Message.INVALID_NULL_LHS);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
index 083a7bcbe272cfe059e3f61900662e65c0c086fc..135fea29b3990a92cf73aa9ca525e24c8f2eb8b0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java
@@ -42,7 +42,6 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @RBuiltin(name = "@<-", kind = PRIMITIVE, parameterNames = {"", "", "value"}, nonEvalArgs = 1, behavior = COMPLEX)
 public abstract class UpdateSlot extends RBuiltinNode.Arg3 {
@@ -79,7 +78,7 @@ public abstract class UpdateSlot extends RBuiltinNode.Arg3 {
         @CompilationFinal private RFunction checkSlotAssignFunction;
         @Child private ClassHierarchyNode objClassHierarchy;
         @Child private ClassHierarchyNode valClassHierarchy;
-        @Child private ReadVariableNode checkAtAssignmentFind = ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, "checkAtAssignment");
+        @Child private ReadVariableNode checkAtAssignmentFind = ReadVariableNode.createFunctionLookup("checkAtAssignment");
         @Child private CallRFunctionNode checkAtAssignmentCall;
 
         private final ConditionProfile cached = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
index 56d5d6be3ed430851ed4a990bbc6cab9c95fe72e..6383859deaab3e59577068cda6b109e6c62c2447 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
@@ -36,6 +36,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.Lapply.LapplyInternalNode;
@@ -50,13 +51,14 @@ import com.oracle.truffle.r.nodes.unary.CastLogicalNode;
 import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.CastStringNodeGen;
+import com.oracle.truffle.r.nodes.unary.CastToVectorNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -83,6 +85,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
 
     private final ConditionProfile useNamesProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile dimsProfile = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile zeroLengthProfile = ConditionProfile.createBinaryProfile();
     private final NACheck naCheck = NACheck.create();
 
     @Child private LapplyInternalNode doApply = LapplyInternalNodeGen.create();
@@ -93,9 +96,13 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
     @Child private CastLogicalNode castLogical;
     @Child private CastStringNode castString;
     @Child private SetDimAttributeNode setDimNode;
-    @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
+    @Child private GetNamesAttributeNode getColNamesNode = GetNamesAttributeNode.create();
+    @Child private GetNamesAttributeNode getRowNamesNode = GetNamesAttributeNode.create();
+    @Child private SetDimNamesAttributeNode setDimNamesNode = SetDimNamesAttributeNode.create();
     @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
 
+    @Child private CastToVectorNode castToVector = CastToVectorNode.create();
+
     static {
         Casts casts = new Casts(VApply.class);
         casts.arg("X").mapNull(emptyList());
@@ -104,44 +111,44 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
         casts.arg("USE.NAMES").defaultError(RError.Message.INVALID_VALUE, "USE.NAMES").mustBe(numericValue()).asLogicalVector().findFirst().mustNotBeNA().map(toBoolean());
     }
 
-    private Object castComplex(Object operand, boolean preserveAllAttr) {
+    private Object castComplex(Object operand) {
         if (castComplex == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castComplex = insert(CastComplexNodeGen.create(true, preserveAllAttr, preserveAllAttr));
+            castComplex = insert(CastComplexNodeGen.create(true, false, false));
         }
-        return castComplex.doCast(operand);
+        return castToVector.doCast(castComplex.doCast(operand));
     }
 
-    private Object castDouble(Object operand, boolean preserveAllAttr) {
+    private Object castDouble(Object operand) {
         if (castDouble == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castDouble = insert(CastDoubleNodeGen.create(true, preserveAllAttr, preserveAllAttr));
+            castDouble = insert(CastDoubleNodeGen.create(true, false, false));
         }
-        return castDouble.doCast(operand);
+        return castToVector.doCast(castDouble.doCast(operand));
     }
 
-    private Object castInteger(Object operand, boolean preserveAllAttr) {
+    private Object castInteger(Object operand) {
         if (castInteger == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castInteger = insert(CastIntegerNodeGen.create(true, preserveAllAttr, preserveAllAttr));
+            castInteger = insert(CastIntegerNodeGen.create(true, false, false));
         }
-        return castInteger.doCast(operand);
+        return castToVector.doCast(castInteger.doCast(operand));
     }
 
-    private Object castLogical(Object operand, boolean preserveAllAttr) {
+    private Object castLogical(Object operand) {
         if (castLogical == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castLogical = insert(CastLogicalNodeGen.create(true, preserveAllAttr, preserveAllAttr));
+            castLogical = insert(CastLogicalNodeGen.create(true, false, false));
         }
-        return castLogical.doCast(operand);
+        return castToVector.doCast(castLogical.doCast(operand));
     }
 
-    private Object castString(Object operand, boolean preserveAllAttr) {
+    private Object castString(Object operand) {
         if (castString == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            castString = insert(CastStringNodeGen.create(true, preserveAllAttr, preserveAllAttr));
+            castString = insert(CastStringNodeGen.create(true, false, false));
         }
-        return castString.doCast(operand);
+        return castToVector.doCast(castString.doCast(operand));
     }
 
     @Specialization
@@ -172,7 +179,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
         Object[] applyResult = doApply.execute(frame, vecMat, fun);
 
         RVector<?> result;
-        boolean applyResultZeroLength = applyResult.length == 0;
+        boolean applyResultZeroLength = zeroLengthProfile.profile(applyResult.length == 0);
 
         naCheck.enable(true);
         // TODO check funValueLen against length of result
@@ -201,11 +208,30 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
                 setDimNode = insert(SetDimAttributeNode.create());
             }
             setDimNode.setDimensions(result, new int[]{funValueVecLen, applyResult.length});
-        }
 
-        // TODO: handle names in case of matrices
-        if (useNamesProfile.profile(useNames)) {
-            RStringVector names = getNamesNode.getNames(vecMat);
+            if (useNamesProfile.profile(useNames)) {
+                // the names from the input vector are used as the column names in the result
+                RStringVector names = getColNamesNode.getNames(vecMat);
+                RStringVector colNames = null;
+                if (names != null) {
+                    colNames = names;
+                } else if (vecMat instanceof RStringVector) {
+                    colNames = (RStringVector) vecMat.copy();
+                }
+                Object rowNames = RNull.instance;
+                if (!applyResultZeroLength) {
+                    // take the names from the first input vector and use it as the row names in the
+                    // result
+                    Object firstVec = applyResult[0];
+                    Object rn = getRowNamesNode.getNames(firstVec);
+                    rowNames = rn == null ? RNull.instance : rn;
+                }
+                if (colNames != null) {
+                    setDimNamesNode.setDimNames(result, RDataFactory.createList(new Object[]{rowNames, colNames}));
+                }
+            }
+        } else if (useNamesProfile.profile(useNames)) {
+            RStringVector names = getColNamesNode.getNames(vecMat);
             RStringVector newNames = null;
             if (names != null) {
                 newNames = names;
@@ -216,6 +242,8 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
                 setNamesNode.setNames(result, newNames);
             }
         }
+
+        // TODO: handle names in case of matrices
         return result;
     }
 
@@ -223,7 +251,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
         double[] newArray = new double[values.length * len];
         int ind = 0;
         for (int i = 0; i < values.length; i++) {
-            RAbstractDoubleVector v = (RAbstractDoubleVector) RRuntime.asAbstractVector(castDouble(values[i], false));
+            RAbstractDoubleVector v = (RAbstractDoubleVector) castDouble(values[i]);
             for (int j = 0; j < v.getLength(); j++) {
                 double val = v.getDataAt(j);
                 naCheck.check(val);
@@ -237,7 +265,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
         int[] newArray = new int[values.length * len];
         int ind = 0;
         for (int i = 0; i < values.length; i++) {
-            RAbstractIntVector v = (RAbstractIntVector) RRuntime.asAbstractVector(castInteger(values[i], false));
+            RAbstractIntVector v = (RAbstractIntVector) castInteger(values[i]);
             for (int j = 0; j < v.getLength(); j++) {
                 int val = v.getDataAt(j);
                 naCheck.check(val);
@@ -251,7 +279,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
         byte[] newArray = new byte[values.length * len];
         int ind = 0;
         for (int i = 0; i < values.length; i++) {
-            RAbstractLogicalVector v = (RAbstractLogicalVector) RRuntime.asAbstractVector(castLogical(values[i], false));
+            RAbstractLogicalVector v = (RAbstractLogicalVector) castLogical(values[i]);
             for (int j = 0; j < v.getLength(); j++) {
                 byte val = v.getDataAt(j);
                 naCheck.check(val);
@@ -265,7 +293,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
         String[] newArray = new String[values.length * len];
         int ind = 0;
         for (int i = 0; i < values.length; i++) {
-            RAbstractStringVector v = (RAbstractStringVector) RRuntime.asAbstractVector(castString(values[i], false));
+            RAbstractStringVector v = (RAbstractStringVector) castString(values[i]);
             for (int j = 0; j < v.getLength(); j++) {
                 String val = v.getDataAt(j);
                 naCheck.check(val);
@@ -279,7 +307,7 @@ public abstract class VApply extends RBuiltinNode.Arg4 {
         double[] newArray = new double[values.length * len * 2];
         int ind = 0;
         for (int i = 0; i < values.length; i++) {
-            RAbstractComplexVector v = (RAbstractComplexVector) RRuntime.asAbstractVector(castComplex(values[i], false));
+            RAbstractComplexVector v = (RAbstractComplexVector) castComplex(values[i]);
             for (int j = 0; j < v.getLength(); j++) {
                 RComplex val = v.getDataAt(j);
                 naCheck.check(val);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
index 1be6fc9e6c8e5123c859945c0eaf5ca457b8a672..48f97b147f36682ec368ac5e61fe3914693c4765 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/MatrixFastPath.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.r.nodes.builtin.base.MatrixNodeGen;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
 import com.oracle.truffle.r.nodes.unary.FirstIntNode;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
@@ -58,8 +59,8 @@ public abstract class MatrixFastPath extends RFastPathNode {
                     @Cached("createBinaryProfile()") ConditionProfile dimMissingProfile,
                     @Cached("createMatrix()") Matrix matrix,
                     @Cached("createClassProfile()") ValueProfile classProfile) {
-        boolean rowMissing = rowMissingProfile.profile(nrow == RMissing.instance);
-        boolean colMissing = colMissingProfile.profile(ncol == RMissing.instance);
+        boolean rowMissing = rowMissingProfile.profile(nrow == RMissing.instance || nrow == REmpty.instance);
+        boolean colMissing = colMissingProfile.profile(ncol == RMissing.instance || ncol == REmpty.instance);
         int row = rowMissing ? 1 : firstRow.executeInt(castRow.doCast(nrow));
         int col = colMissing ? 1 : firstCol.executeInt(castCol.doCast(ncol));
         Object dim = dimMissingProfile.profile(dimnames == RMissing.instance) ? RNull.instance : dimnames;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/SubscriptDataFrameFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/SubscriptDataFrameFastPath.java
new file mode 100644
index 0000000000000000000000000000000000000000..b4f2b8a9ba6e73fc9612509b4863dae406a07d05
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/SubscriptDataFrameFastPath.java
@@ -0,0 +1,106 @@
+/*
+ * 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.nodes.builtin.base.fastpaths;
+
+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.nodes.Node;
+import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
+import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+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.nodes.RFastPathNode;
+
+abstract class AsScalarNode extends Node {
+    public abstract Object execute(Object value);
+
+    @Specialization
+    protected static int asScalar(int value) {
+        return value;
+    }
+
+    @Specialization
+    protected static double asScalar(double value) {
+        return value;
+    }
+
+    @Specialization(guards = {"value.getLength() == 1", "value.getAttributes() == null"})
+    protected static int asScalar(RAbstractIntVector value) {
+        return value.getDataAt(0);
+    }
+
+    @Specialization(guards = {"value.getLength() == 1", "value.getAttributes() == null"})
+    protected static double asScalar(RAbstractDoubleVector value) {
+        return value.getDataAt(0);
+    }
+
+    @Fallback
+    protected static Object asScalar(@SuppressWarnings("unused") Object value) {
+        return null;
+    }
+
+    public static AsScalarNode create() {
+        return AsScalarNodeGen.create();
+    }
+}
+
+public abstract class SubscriptDataFrameFastPath extends RFastPathNode {
+
+    @Child private ExtractVectorNode extractNode = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
+
+    @Specialization(guards = {"positions.getLength() == 1", "positions.getSignature().getNonNullCount() == 0"})
+    protected Object subscript1(RAbstractListVector df, RArgsValuesAndNames positions, Object exact,
+                    @Cached("create()") AsScalarNode asScalar) {
+        Object pos = asScalar.execute(positions.getArgument(0));
+        if (pos == null) {
+            return null;
+        }
+        return extractNode.apply(df, new Object[]{pos}, exact, RRuntime.LOGICAL_TRUE);
+    }
+
+    @Specialization(guards = {"positions.getLength() == 2", "positions.getSignature().getNonNullCount() == 0"})
+    protected Object subscript2(RAbstractListVector df, RArgsValuesAndNames positions, Object exact,
+                    @Cached("create()") AsScalarNode asScalar1,
+                    @Cached("create()") AsScalarNode asScalar2) {
+        Object pos2 = asScalar2.execute(positions.getArgument(1));
+        if (pos2 == null) {
+            return null;
+        }
+        Object extracted = extractNode.apply(df, new Object[]{pos2}, exact, RRuntime.LOGICAL_TRUE);
+        Object pos1 = asScalar1.execute(positions.getArgument(0));
+        if (pos1 == null) {
+            return null;
+        }
+        return extractNode.apply(extracted, new Object[]{pos1}, exact, RRuntime.LOGICAL_TRUE);
+    }
+
+    @Fallback
+    @SuppressWarnings("unused")
+    protected Object fallback(Object df, Object positions, Object exact) {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/SubsetDataFrameFastPath.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/SubsetDataFrameFastPath.java
new file mode 100644
index 0000000000000000000000000000000000000000..cb2f35532f5c3fca034aa675e141f48ae00763db
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/fastpaths/SubsetDataFrameFastPath.java
@@ -0,0 +1,60 @@
+/*
+ * 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.nodes.builtin.base.fastpaths;
+
+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.r.nodes.access.vector.ElementAccessMode;
+import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
+import com.oracle.truffle.r.runtime.nodes.RFastPathNode;
+
+public abstract class SubsetDataFrameFastPath extends RFastPathNode {
+
+    @Child private ExtractVectorNode extractNode = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
+
+    @Specialization(guards = {"positions.getLength() == 2", "positions.getSignature().getNonNullCount() == 0"})
+    protected Object subscript2(RAbstractListVector df, RArgsValuesAndNames positions, Object exact,
+                    @Cached("create()") AsScalarNode asScalar1,
+                    @Cached("create()") AsScalarNode asScalar2) {
+        Object pos2 = asScalar2.execute(positions.getArgument(1));
+        if (pos2 == null) {
+            return null;
+        }
+        Object extracted = extractNode.apply(df, new Object[]{pos2}, exact, RRuntime.LOGICAL_TRUE);
+        Object pos1 = asScalar1.execute(positions.getArgument(0));
+        if (pos1 == null) {
+            return null;
+        }
+        return extractNode.apply(extracted, new Object[]{pos1}, exact, RRuntime.LOGICAL_TRUE);
+    }
+
+    @Fallback
+    @SuppressWarnings("unused")
+    protected Object fallback(Object df, Object positions, Object exact) {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
index a498b2d75c9388fa293795c0cf030f46688d9b76..2eb33a9b1299a8e003ef3c6a189b701c63599768 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java
@@ -62,6 +62,7 @@ import com.oracle.truffle.r.library.tools.ToolsTextFactory.DoTabExpandNodeGen;
 import com.oracle.truffle.r.library.utils.CountFieldsNodeGen;
 import com.oracle.truffle.r.library.utils.Crc64NodeGen;
 import com.oracle.truffle.r.library.utils.DownloadNodeGen;
+import com.oracle.truffle.r.library.utils.UnzipNodeGen;
 import com.oracle.truffle.r.library.utils.MenuNodeGen;
 import com.oracle.truffle.r.library.utils.ObjectSizeNodeGen;
 import com.oracle.truffle.r.library.utils.RprofNodeGen;
@@ -79,6 +80,7 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RExternalPtr;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -219,7 +221,7 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".Call", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotCall extends LookupAdapter {
 
-        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotCall.class);
@@ -698,6 +700,11 @@ public class CallAndExternalFunctions {
             return callRFFINode.execute(new NativeCallInfo(symbol, func, rns.getDllInfo()), args.getArguments());
         }
 
+        @Specialization
+        protected Object callNamedFunctionWithPackage(RExternalPtr symbol, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) {
+            return callRFFINode.execute(new NativeCallInfo("", symbol.getAddr(), null), args.getArguments());
+        }
+
         @SuppressWarnings("unused")
         @Fallback
         protected Object dotCallFallback(Object symbol, Object args, Object packageName) {
@@ -712,7 +719,7 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".External", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotExternal extends LookupAdapter {
 
-        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotExternal.class);
@@ -754,6 +761,7 @@ public class CallAndExternalFunctions {
                 case "signrank_free":
                     return new SignrankFreeNode();
                 case "unzip":
+                    return UnzipNodeGen.create();
                 case "addhistory":
                 case "loadhistory":
                 case "savehistory":
@@ -822,18 +830,18 @@ public class CallAndExternalFunctions {
          * native function that is eventually invoked will always get SPECIALSXP reprenting the
          * .External2, becuase functions exported as .External do not take the "op" argument.
          */
-        @CompilationFinal private static Object op = null;
+        @CompilationFinal private Object op = null;
 
-        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotExternal2.class);
         }
 
-        private static Object getOp() {
+        private Object getOp() {
             if (op == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                op = RContext.lookupBuiltin(".External2");
+                op = RContext.getInstance().lookupBuiltin(".External2");
             }
             return op;
         }
@@ -909,7 +917,7 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".External.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotExternalGraphics extends LookupAdapter {
 
-        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotExternalGraphics.class);
@@ -963,7 +971,7 @@ public class CallAndExternalFunctions {
     @RBuiltin(name = ".Call.graphics", kind = PRIMITIVE, parameterNames = {".NAME", "...", "PACKAGE"}, behavior = COMPLEX)
     public abstract static class DotCallGraphics extends LookupAdapter {
 
-        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode();
+        @Child CallRFFI.InvokeCallNode callRFFINode = RFFIFactory.getCallRFFI().createInvokeCallNode();
 
         static {
             Casts.noCasts(DotCallGraphics.class);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
index 93d2a214721c73a0d532933585bf56ebb6fed4ce..8a4d7c4ea7ef4c4c5e151f03cfa26cc40641b34e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java
@@ -11,9 +11,10 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.foreign;
 
-import com.oracle.truffle.api.dsl.Specialization;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -27,21 +28,21 @@ import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
 public abstract class Dqrcf extends RExternalBuiltinNode.Arg8 {
-    @Child private RApplRFFI.DqrcfNode dqcrfNode = RFFIFactory.getRFFI().getRApplRFFI().createDqrcfNode();
+    @Child private RApplRFFI.DqrcfNode dqcrfNode = RFFIFactory.getRApplRFFI().createDqrcfNode();
 
     private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE;
     private static final RStringVector DQRCF_NAMES = RDataFactory.createStringVector(new String[]{E, E, E, E, E, E, "coef", "info"}, RDataFactory.COMPLETE_VECTOR);
 
     static {
         Casts casts = new Casts(Dqrcf.class);
-        casts.arg(0).mustBe(doubleValue()).asDoubleVector();
-        casts.arg(1).mustBe(integerValue()).asIntegerVector().findFirst();
-        casts.arg(2).mustBe(integerValue()).asIntegerVector().findFirst();
-        casts.arg(3).mustBe(doubleValue()).asDoubleVector();
-        casts.arg(4).mustBe(doubleValue()).asDoubleVector();
-        casts.arg(5).mustBe(integerValue()).asIntegerVector().findFirst();
-        casts.arg(6).mustBe(doubleValue()).asDoubleVector();
-        casts.arg(7).mustBe(integerValue()).asIntegerVector();
+        casts.arg(0, "x").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(1, "nx").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(2, "k").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(3, "qraux").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(4, "y").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(5, "ny").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(6, "b").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(7, "info").mustBe(integerValue()).asIntegerVector();
     }
 
     @Specialization
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
index b546af27357097d5925f084a10af04b9f5b85cd4..357bf832692615454238f5ee94cc264b4a1cf6a0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java
@@ -26,7 +26,7 @@ import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 
 public abstract class Dqrdc2 extends RExternalBuiltinNode.Arg9 {
-    @Child private RApplRFFI.Dqrdc2Node dqrdc2Node = RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node();
+    @Child private RApplRFFI.Dqrdc2Node dqrdc2Node = RFFIFactory.getRApplRFFI().createDqrdc2Node();
 
     private static final String E = RRuntime.NAMES_ATTR_EMPTY_VALUE;
     private static final RStringVector DQRDC2_NAMES = RDataFactory.createStringVector(new String[]{"qr", E, E, E, E, "rank", "qraux", "pivot", E}, RDataFactory.COMPLETE_VECTOR);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrqty.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrqty.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a681d45226965b96f338db8851e8827676508a9
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrqty.java
@@ -0,0 +1,79 @@
+/*
+ * 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.nodes.builtin.base.foreign;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+
+public abstract class Dqrqty extends RExternalBuiltinNode.Arg7 {
+    @Child private RApplRFFI.DqrqtyNode dqrqtyNode = RFFIFactory.getRApplRFFI().createDqrqtyNode();
+
+    static {
+        Casts casts = new Casts(Dqrqty.class);
+        casts.arg(0, "x").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(1, "nx").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(2, "k").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(3, "qraux").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(4, "y").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(5, "ny").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(6, "b").mustBe(doubleValue()).asDoubleVector();
+    }
+
+    @Specialization
+    public RList dqrcf(RAbstractDoubleVector xVec, int nx, int k, RAbstractDoubleVector qrauxVec, RAbstractDoubleVector yVec, int ny, RAbstractDoubleVector bVec) {
+        try {
+            double[] x = xVec.materialize().getDataTemp();
+            double[] qraux = qrauxVec.materialize().getDataTemp();
+            double[] y = yVec.materialize().getDataTemp();
+            double[] b = bVec.materialize().getDataTemp();
+            dqrqtyNode.execute(x, nx, k, qraux, y, ny, b);
+            RDoubleVector coef = RDataFactory.createDoubleVector(b, RDataFactory.COMPLETE_VECTOR);
+            coef.copyAttributesFrom(bVec);
+            // @formatter:off
+            Object[] data = new Object[]{
+                        RDataFactory.createDoubleVector(x, RDataFactory.COMPLETE_VECTOR),
+                        nx,
+                        k,
+                        RDataFactory.createDoubleVector(qraux, RDataFactory.COMPLETE_VECTOR),
+                        RDataFactory.createDoubleVector(y, RDataFactory.COMPLETE_VECTOR),
+                        ny,
+                        coef,
+            };
+            // @formatter:on
+            return RDataFactory.createList(data);
+
+        } catch (ClassCastException | ArrayIndexOutOfBoundsException ex) {
+            throw error(RError.Message.INCORRECT_ARG, "dqrqty");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrqy.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrqy.java
new file mode 100644
index 0000000000000000000000000000000000000000..9ccdf43844cb8f5e3f46abe5716c1e5ad4b233a1
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrqy.java
@@ -0,0 +1,79 @@
+/*
+ * 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.nodes.builtin.base.foreign;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+
+public abstract class Dqrqy extends RExternalBuiltinNode.Arg7 {
+    @Child private RApplRFFI.DqrqyNode dqrqyNode = RFFIFactory.getRApplRFFI().createDqrqyNode();
+
+    static {
+        Casts casts = new Casts(Dqrqy.class);
+        casts.arg(0, "x").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(1, "nx").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(2, "k").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(3, "qraux").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(4, "y").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(5, "ny").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(6, "b").mustBe(doubleValue()).asDoubleVector();
+    }
+
+    @Specialization
+    public RList dqrcf(RAbstractDoubleVector xVec, int nx, int k, RAbstractDoubleVector qrauxVec, RAbstractDoubleVector yVec, int ny, RAbstractDoubleVector bVec) {
+        try {
+            double[] x = xVec.materialize().getDataTemp();
+            double[] qraux = qrauxVec.materialize().getDataTemp();
+            double[] y = yVec.materialize().getDataTemp();
+            double[] b = bVec.materialize().getDataTemp();
+            dqrqyNode.execute(x, nx, k, qraux, y, ny, b);
+            RDoubleVector coef = RDataFactory.createDoubleVector(b, RDataFactory.COMPLETE_VECTOR);
+            coef.copyAttributesFrom(bVec);
+            // @formatter:off
+            Object[] data = new Object[]{
+                        RDataFactory.createDoubleVector(x, RDataFactory.COMPLETE_VECTOR),
+                        nx,
+                        k,
+                        RDataFactory.createDoubleVector(qraux, RDataFactory.COMPLETE_VECTOR),
+                        RDataFactory.createDoubleVector(y, RDataFactory.COMPLETE_VECTOR),
+                        ny,
+                        coef,
+            };
+            // @formatter:on
+            return RDataFactory.createList(data);
+
+        } catch (ClassCastException | ArrayIndexOutOfBoundsException ex) {
+            throw error(RError.Message.INCORRECT_ARG, "dqrqy");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrrsd.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrrsd.java
new file mode 100644
index 0000000000000000000000000000000000000000..23b66ab9b34d888b240ed044d08ee340e3615599
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrrsd.java
@@ -0,0 +1,79 @@
+/*
+ * 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.nodes.builtin.base.foreign;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+
+public abstract class Dqrrsd extends RExternalBuiltinNode.Arg7 {
+    @Child private RApplRFFI.DqrrsdNode dqrrsdNode = RFFIFactory.getRApplRFFI().createDqrrsdNode();
+
+    static {
+        Casts casts = new Casts(Dqrrsd.class);
+        casts.arg(0, "x").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(1, "nx").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(2, "k").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(3, "qraux").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(4, "y").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(5, "ny").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(6, "rsd").mustBe(doubleValue()).asDoubleVector();
+    }
+
+    @Specialization
+    public RList dqrcf(RAbstractDoubleVector xVec, int nx, int k, RAbstractDoubleVector qrauxVec, RAbstractDoubleVector yVec, int ny, RAbstractDoubleVector rsdVec) {
+        try {
+            double[] x = xVec.materialize().getDataTemp();
+            double[] qraux = qrauxVec.materialize().getDataTemp();
+            double[] y = yVec.materialize().getDataTemp();
+            double[] rsd = rsdVec.materialize().getDataTemp();
+            dqrrsdNode.execute(x, nx, k, qraux, y, ny, rsd);
+            RDoubleVector coef = RDataFactory.createDoubleVector(rsd, RDataFactory.COMPLETE_VECTOR);
+            coef.copyAttributesFrom(rsdVec);
+            // @formatter:off
+            Object[] data = new Object[]{
+                        RDataFactory.createDoubleVector(x, RDataFactory.COMPLETE_VECTOR),
+                        nx,
+                        k,
+                        RDataFactory.createDoubleVector(qraux, RDataFactory.COMPLETE_VECTOR),
+                        RDataFactory.createDoubleVector(y, RDataFactory.COMPLETE_VECTOR),
+                        ny,
+                        coef,
+            };
+            // @formatter:on
+            return RDataFactory.createList(data);
+
+        } catch (ClassCastException | ArrayIndexOutOfBoundsException ex) {
+            throw error(RError.Message.INCORRECT_ARG, "dqrrsd");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrxb.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrxb.java
new file mode 100644
index 0000000000000000000000000000000000000000..6702b7633d6158245e202cb3dd79106e774b86a0
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrxb.java
@@ -0,0 +1,79 @@
+/*
+ * 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.nodes.builtin.base.foreign;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
+import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
+import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+
+public abstract class Dqrxb extends RExternalBuiltinNode.Arg7 {
+    @Child private RApplRFFI.DqrxbNode dqrrsdNode = RFFIFactory.getRApplRFFI().createDqrxbNode();
+
+    static {
+        Casts casts = new Casts(Dqrxb.class);
+        casts.arg(0, "x").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(1, "nx").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(2, "k").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(3, "qraux").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(4, "y").mustBe(doubleValue()).asDoubleVector();
+        casts.arg(5, "ny").mustBe(integerValue()).asIntegerVector().findFirst();
+        casts.arg(6, "xb").mustBe(doubleValue()).asDoubleVector();
+    }
+
+    @Specialization
+    public RList dqrcf(RAbstractDoubleVector xVec, int nx, int k, RAbstractDoubleVector qrauxVec, RAbstractDoubleVector yVec, int ny, RAbstractDoubleVector xbVec) {
+        try {
+            double[] x = xVec.materialize().getDataTemp();
+            double[] qraux = qrauxVec.materialize().getDataTemp();
+            double[] y = yVec.materialize().getDataTemp();
+            double[] xb = xbVec.materialize().getDataTemp();
+            dqrrsdNode.execute(x, nx, k, qraux, y, ny, xb);
+            RDoubleVector coef = RDataFactory.createDoubleVector(xb, RDataFactory.COMPLETE_VECTOR);
+            coef.copyAttributesFrom(xbVec);
+            // @formatter:off
+            Object[] data = new Object[]{
+                        RDataFactory.createDoubleVector(x, RDataFactory.COMPLETE_VECTOR),
+                        nx,
+                        k,
+                        RDataFactory.createDoubleVector(qraux, RDataFactory.COMPLETE_VECTOR),
+                        RDataFactory.createDoubleVector(y, RDataFactory.COMPLETE_VECTOR),
+                        ny,
+                        coef,
+            };
+            // @formatter:on
+            return RDataFactory.createList(data);
+
+        } catch (ClassCastException | ArrayIndexOutOfBoundsException ex) {
+            throw error(RError.Message.INCORRECT_ARG, "dqrxb");
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
index afdff5f5bcce8fd1e78e753c3aff002b74190c65..7fd4ccfd8cf47d00c8c5de672a6d7075b7954e36 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java
@@ -14,14 +14,20 @@ package com.oracle.truffle.r.nodes.builtin.base.foreign;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode;
+import com.oracle.truffle.r.nodes.builtin.base.foreign.FortranAndCFunctionsFactory.FortranResultNamesSetterNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapter.ExtractNativeCallInfoNode;
 import com.oracle.truffle.r.nodes.builtin.base.foreign.LookupAdapterFactory.ExtractNativeCallInfoNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -29,9 +35,11 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RAttributable;
 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.RString;
 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;
@@ -41,6 +49,7 @@ import com.oracle.truffle.r.runtime.ffi.CRFFI;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.NativeCallInfo;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * {@code .C} and {@code .Fortran} functions, which share a common signature.
@@ -56,14 +65,16 @@ public class FortranAndCFunctions {
         private static final int SCALAR_DOUBLE = 0;
         private static final int SCALAR_INT = 1;
         private static final int SCALAR_LOGICAL = 2;
-        @SuppressWarnings("unused") private static final int SCALAR_STRING = 3;
+        private static final int SCALAR_STRING = 3;
         private static final int VECTOR_DOUBLE = 10;
         private static final int VECTOR_INT = 11;
         private static final int VECTOR_LOGICAL = 12;
-        @SuppressWarnings("unused") private static final int VECTOR_STRING = 12;
+        private static final int VECTOR_STRING = 13;
+
+        private static final Charset charset = StandardCharsets.US_ASCII;
 
         @Child protected ExtractNativeCallInfoNode extractSymbolInfo = ExtractNativeCallInfoNodeGen.create();
-        @Child private CRFFI.InvokeCNode invokeCNode = RFFIFactory.getRFFI().getCRFFI().createInvokeCNode();
+        @Child private CRFFI.InvokeCNode invokeCNode = RFFIFactory.getCRFFI().createInvokeCNode();
 
         @Override
         public Object[] getDefaultParameterValues() {
@@ -80,6 +91,7 @@ public class FortranAndCFunctions {
             Object[] array = args.getArguments();
             int[] argTypes = new int[array.length];
             Object[] nativeArgs = new Object[array.length];
+            boolean hasStrings = false;
             for (int i = 0; i < array.length; i++) {
                 Object arg = array[i];
                 if (arg instanceof RAbstractDoubleVector) {
@@ -98,6 +110,16 @@ public class FortranAndCFunctions {
                         dataAsInt[j] = RRuntime.isNA(data[j]) ? RRuntime.INT_NA : data[j];
                     }
                     nativeArgs[i] = checkNAs(node, i + 1, dataAsInt);
+                } else if (arg instanceof RAbstractStringVector) {
+                    hasStrings = true;
+                    argTypes[i] = VECTOR_STRING;
+                    checkNAs(node, i + 1, (RAbstractStringVector) arg);
+                    nativeArgs[i] = encodeStrings((RAbstractStringVector) arg);
+                } else if (arg instanceof String) {
+                    hasStrings = true;
+                    argTypes[i] = SCALAR_STRING;
+                    checkNAs(node, i + 1, RString.valueOf((String) arg));
+                    nativeArgs[i] = new byte[][]{encodeString((String) arg)};
                 } else if (arg instanceof Double) {
                     argTypes[i] = SCALAR_DOUBLE;
                     nativeArgs[i] = checkNAs(node, i + 1, new double[]{(double) arg});
@@ -111,7 +133,7 @@ public class FortranAndCFunctions {
                     throw node.error(RError.Message.UNIMPLEMENTED_ARG_TYPE, i + 1);
                 }
             }
-            invokeCNode.execute(nativeCallInfo, nativeArgs);
+            invokeCNode.execute(nativeCallInfo, nativeArgs, hasStrings);
             // we have to assume that the native method updated everything
             RStringVector listNames = validateArgNames(array.length, args.getSignature());
             Object[] results = new Object[array.length];
@@ -133,6 +155,12 @@ public class FortranAndCFunctions {
                         }
                         results[i] = RDataFactory.createLogicalVector(nativeByteArgs, RDataFactory.COMPLETE_VECTOR);
                         break;
+                    case SCALAR_STRING:
+                        results[i] = RDataFactory.createStringVector(decodeStrings((byte[][]) nativeArgs[i]), RDataFactory.COMPLETE_VECTOR);
+                        break;
+                    case VECTOR_STRING:
+                        results[i] = ((RAbstractStringVector) array[i]).materialize().copyResetData(decodeStrings((byte[][]) nativeArgs[i]));
+                        break;
                     case VECTOR_DOUBLE:
                         results[i] = ((RAbstractDoubleVector) array[i]).materialize().copyResetData((double[]) nativeArgs[i]);
                         break;
@@ -163,6 +191,15 @@ public class FortranAndCFunctions {
             return data;
         }
 
+        private static void checkNAs(RBuiltinNode node, int argIndex, RAbstractStringVector data) {
+            CompilerAsserts.neverPartOfCompilation();
+            for (int i = 0; i < data.getLength(); i++) {
+                if (RRuntime.isNA(data.getDataAt(i))) {
+                    throw node.error(RError.Message.NA_IN_FOREIGN_FUNCTION_CALL, argIndex);
+                }
+            }
+        }
+
         private static double[] checkNAs(RBuiltinNode node, int argIndex, double[] data) {
             CompilerAsserts.neverPartOfCompilation();
             for (int i = 0; i < data.length; i++) {
@@ -184,6 +221,33 @@ public class FortranAndCFunctions {
             }
             return RDataFactory.createStringVector(listArgNames, RDataFactory.COMPLETE_VECTOR);
         }
+
+        private static Object encodeStrings(RAbstractStringVector vector) {
+            byte[][] result = new byte[vector.getLength()][];
+            for (int i = 0; i < vector.getLength(); i++) {
+                result[i] = encodeString(vector.getDataAt(i));
+            }
+            return result;
+        }
+
+        private static byte[] encodeString(String str) {
+            byte[] bytes = str.getBytes(charset);
+            byte[] result = new byte[bytes.length + 1];
+            System.arraycopy(bytes, 0, result, 0, bytes.length);
+            return result;
+        }
+
+        private static String[] decodeStrings(byte[][] bytes) {
+            String[] result = new String[bytes.length];
+            for (int i = 0; i < bytes.length; i++) {
+                int length = 0;
+                while (length < bytes[i].length && bytes[i][length] != 0) {
+                    length++;
+                }
+                result[i] = new String(bytes[i], 0, length, charset);
+            }
+            return result;
+        }
     }
 
     /**
@@ -197,6 +261,8 @@ public class FortranAndCFunctions {
             Casts.noCasts(Fortran.class);
         }
 
+        @Child private FortranResultNamesSetter resNamesSetter = FortranResultNamesSetterNodeGen.create();
+
         @Override
         @TruffleBoundary
         public RExternalBuiltinNode lookupBuiltin(RList symbol) {
@@ -205,6 +271,14 @@ public class FortranAndCFunctions {
                     return Dqrdc2.create();
                 case "dqrcf":
                     return DqrcfNodeGen.create();
+                case "dqrqty":
+                    return DqrqtyNodeGen.create();
+                case "dqrqy":
+                    return DqrqyNodeGen.create();
+                case "dqrrsd":
+                    return DqrrsdNodeGen.create();
+                case "dqrxb":
+                    return DqrxbNodeGen.create();
                 default:
                     return null;
             }
@@ -215,7 +289,7 @@ public class FortranAndCFunctions {
         protected Object doExternal(VirtualFrame frame, RList symbol, RArgsValuesAndNames args, byte naok, byte dup, Object rPackage, RMissing encoding,
                         @Cached("symbol") RList cached,
                         @Cached("lookupBuiltin(symbol)") RExternalBuiltinNode builtin) {
-            return builtin.call(frame, args);
+            return resNamesSetter.execute(builtin.call(frame, args), args);
         }
 
         @Specialization(guards = "lookupBuiltin(symbol) == null")
@@ -244,6 +318,40 @@ public class FortranAndCFunctions {
         }
     }
 
+    public abstract static class FortranResultNamesSetter extends RBaseNode {
+
+        public abstract Object execute(Object result, RArgsValuesAndNames argNames);
+
+        @Specialization
+        public Object handleArgNames(RAttributable result, RArgsValuesAndNames argValNames,
+                        @Cached("create()") SetNamesAttributeNode namesSetter,
+                        @Cached("create()") BranchProfile namesProfile) {
+            ArgumentsSignature sig = argValNames.getSignature();
+            if (sig.getNonNullCount() > 0) {
+                namesProfile.enter();
+                String[] argNames = sig.getNames();
+                String[] names = new String[sig.getLength()];
+                for (int i = 0; i < sig.getLength(); i++) {
+                    String argName = argNames[i];
+                    if (argName == null) {
+                        names[i] = "";
+                    } else {
+                        names[i] = argName;
+                    }
+                }
+                namesSetter.execute(result, RDataFactory.createStringVector(names, true));
+            }
+
+            return result;
+        }
+
+        @Fallback
+        public Object handleOthers(Object result, @SuppressWarnings("unused") RArgsValuesAndNames argNames) {
+            // do nothing
+            return result;
+        }
+    }
+
     @RBuiltin(name = ".C", kind = PRIMITIVE, parameterNames = {".NAME", "...", "NAOK", "DUP", "PACKAGE", "ENCODING"}, behavior = COMPLEX)
     public abstract static class DotC extends CRFFIAdapter {
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
index 49bcba78821d3eab1788b512a52a45eb64db657e..40e7c89190b120ecd29164dbe0d3adeb38019c92 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/LookupAdapter.java
@@ -149,7 +149,7 @@ abstract class LookupAdapter extends RBuiltinNode.Arg3 implements Lookup {
         protected abstract NativeCallInfo execute(VirtualFrame frame, RList symbol);
 
         @Specialization
-        protected NativeCallInfo extractNativeCallInfo(VirtualFrame frame, RList symbol) {
+        protected NativeCallInfo extractNativeCallInfo(RList symbol) {
             if (nameExtract == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 nameExtract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
@@ -162,11 +162,11 @@ abstract class LookupAdapter extends RBuiltinNode.Arg3 implements Lookup {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 packageExtract = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
             }
-            String name = RRuntime.asString(nameExtract.applyAccessField(frame, symbol, "name"));
-            SymbolHandle address = ((RExternalPtr) addressExtract.applyAccessField(frame, symbol, "address")).getAddr();
+            String name = RRuntime.asString(nameExtract.applyAccessField(symbol, "name"));
+            SymbolHandle address = ((RExternalPtr) addressExtract.applyAccessField(symbol, "address")).getAddr();
             // field name may be "package" or "dll", but always at (R) index 3
-            RList packageList = (RList) packageExtract.apply(frame, symbol, new Object[]{3}, RLogical.valueOf(false), RMissing.instance);
-            DLLInfo dllInfo = (DLLInfo) ((RExternalPtr) addressExtract.applyAccessField(frame, packageList, "info")).getExternalObject();
+            RList packageList = (RList) packageExtract.apply(symbol, new Object[]{3}, RLogical.valueOf(false), RMissing.instance);
+            DLLInfo dllInfo = (DLLInfo) ((RExternalPtr) addressExtract.applyAccessField(packageList, "info")).getExternalObject();
             return new NativeCallInfo(name, address, dllInfo);
 
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
index 6dc65c7395e95b45258a1fec91bc44cc1c1059e2..c40c9d62e8fd21afbe53ed68cf82510f9f19a082 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/AccessField.java
@@ -65,7 +65,7 @@ abstract class AccessFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
 
     @Child private ExtractListElement extractListElement = ExtractListElement.create();
 
-    @Specialization(limit = "2", guards = {"isSimpleList(list)", "list.getNames() == cachedNames", "field == cachedField"})
+    @Specialization(limit = "2", guards = {"getNamesNode.getNames(list) == cachedNames", "field == cachedField"})
     public Object doList(RList list, @SuppressWarnings("unused") String field,
                     @SuppressWarnings("unused") @Cached("list.getNames()") RStringVector cachedNames,
                     @SuppressWarnings("unused") @Cached("field") String cachedField,
@@ -76,7 +76,7 @@ abstract class AccessFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
         return extractListElement.execute(list, index);
     }
 
-    @Specialization(replaces = "doList", guards = {"isSimpleList(list)", "list.getNames() != null"})
+    @Specialization(replaces = "doList")
     public Object doListDynamic(RList list, String field) {
         int index = getIndex(getNamesNode.getNames(list), field);
         if (index == -1) {
@@ -110,7 +110,7 @@ public abstract class AccessField extends RBuiltinNode.Arg2 {
     }
 
     @Specialization
-    protected Object access(VirtualFrame frame, Object container, String field) {
+    protected Object access(Object container, String field) {
         if (!invalidAtomicVector.profile(container instanceof RAbstractListVector) && container instanceof RAbstractVector) {
             error.enter();
             throw error(RError.Message.DOLLAR_ATOMIC_VECTORS);
@@ -123,6 +123,6 @@ public abstract class AccessField extends RBuiltinNode.Arg2 {
                 return container;
             }
         }
-        return extract.applyAccessField(frame, container, field);
+        return extract.applyAccessField(container, field);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java
index 4d9d655c0723c28762833aa930d565f84a2d24f9..0c9110604ac573f5f02b25868342c9849c37ff25 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/ProfiledSpecialsUtils.java
@@ -126,7 +126,6 @@ public class ProfiledSpecialsUtils {
             }
             return defaultAccessNode.execute(frame, vector, index1, index2);
         }
-
     }
 
     public abstract static class ProfiledSubscriptSpecial2 extends ProfiledSubscriptSpecial2Base {
@@ -139,7 +138,6 @@ public class ProfiledSpecialsUtils {
         protected SubscriptSpecial2Base createAccessNode() {
             return SubscriptSpecial2NodeGen.create(inReplacement);
         }
-
     }
 
     public abstract static class ProfiledSubsetSpecial2 extends ProfiledSubscriptSpecial2Base {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
index 569af73be2fc13c8a9178766d0a4c773b7b30f4f..425bb7220c544608be9f77badb5a340fadadb823 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/SpecialsUtils.java
@@ -30,16 +30,15 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.r.nodes.attributes.HasAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertIndexNodeGen;
 import com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtilsFactory.ConvertValueNodeGen;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
-import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RIntVector;
-import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -68,16 +67,14 @@ class SpecialsUtils {
      */
     abstract static class SubscriptSpecialCommon extends Node {
 
-        @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false);
-
         protected final boolean inReplacement;
 
         protected SubscriptSpecialCommon(boolean inReplacement) {
             this.inReplacement = inReplacement;
         }
 
-        protected boolean simpleVector(RAbstractVector vector) {
-            return classHierarchy.execute(vector) == null;
+        protected boolean simpleVector(@SuppressWarnings("unused") RAbstractVector vector) {
+            return true;
         }
 
         /**
@@ -123,13 +120,8 @@ class SpecialsUtils {
      */
     abstract static class ListFieldSpecialBase extends RNode {
 
-        @Child private ClassHierarchyNode hierarchyNode = ClassHierarchyNode.create();
         @Child protected GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
-        protected final boolean isSimpleList(RList list) {
-            return hierarchyNode.execute(list) == null;
-        }
-
         protected static int getIndex(RStringVector names, String field) {
             if (names != null) {
                 int fieldHash = field.hashCode();
@@ -160,6 +152,8 @@ class SpecialsUtils {
 
         protected abstract RNode getDelegate();
 
+        public abstract Object execute(Object value);
+
         @Specialization
         protected static int convertInteger(int value) {
             return value;
@@ -168,7 +162,7 @@ class SpecialsUtils {
         @Specialization(rewriteOn = IllegalArgumentException.class)
         protected int convertDouble(double value) {
             int intValue = (int) value;
-            if (intValue == 0) {
+            if (intValue <= 0) {
                 /*
                  * Conversion from double to an index differs in subscript and subset for values in
                  * the ]0..1[ range (subscript interprets 0.1 as 1, whereas subset treats it as 0).
@@ -209,15 +203,17 @@ class SpecialsUtils {
             return value;
         }
 
-        @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null"})
+        @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null", "hasAttrsNode.execute(value)"})
         protected static int convertIntVector(RIntVector value,
-                        @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode) {
+                        @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode,
+                        @Cached("create()") @SuppressWarnings("unused") HasAttributesNode hasAttrsNode) {
             return value.getDataAt(0);
         }
 
-        @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null"})
+        @Specialization(guards = {"value.getLength() == 1", "hierarchyNode.execute(value) == null", "hasAttrsNode.execute(value)"})
         protected static double convertDoubleVector(RDoubleVector value,
-                        @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode) {
+                        @Cached("create()") @SuppressWarnings("unused") ClassHierarchyNode hierarchyNode,
+                        @Cached("create()") @SuppressWarnings("unused") HasAttributesNode hasAttrsNode) {
             return value.getDataAt(0);
         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
index 113fccddad113db8997093d4124656df4e8133d5..1cf72271811fdea2e4d1ce12505e81076984229d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subscript.java
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUBSCRIPT;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
@@ -68,7 +68,9 @@ abstract class SubscriptSpecialBase extends SubscriptSpecialCommon {
         super(inReplacement);
     }
 
-    protected abstract Object execute(VirtualFrame frame, Object vec, Object index);
+    public abstract Object execute(VirtualFrame frame, Object vec, Object index);
+
+    public abstract Object execute(VirtualFrame frame, Object vec, int index);
 
     @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index)"})
     protected int access(RAbstractIntVector vector, int index) {
@@ -103,6 +105,8 @@ abstract class SubscriptSpecial2Base extends SubscriptSpecial2Common {
 
     public abstract Object execute(VirtualFrame frame, Object vector, Object index1, Object index2);
 
+    public abstract Object execute(VirtualFrame frame, Object vec, int index1, int index2);
+
     @Specialization(guards = {"simpleVector(vector)", "isValidIndex(vector, index1, index2)"})
     protected int access(RAbstractIntVector vector, int index1, int index2) {
         return vector.getDataAt(matrixIndex(vector, index1, index2));
@@ -142,9 +146,9 @@ abstract class SubscriptSpecial extends SubscriptSpecialBase {
     }
 
     @Specialization(guards = {"simpleVector(vector)", "!inReplacement"})
-    protected static Object access(VirtualFrame frame, RAbstractVector vector, Object index,
+    protected static Object access(RAbstractVector vector, Object index,
                     @Cached("createAccess()") ExtractVectorNode extract) {
-        return extract.apply(frame, vector, new Object[]{index}, RRuntime.LOGICAL_TRUE, RLogical.TRUE);
+        return extract.apply(vector, new Object[]{index}, RRuntime.LOGICAL_TRUE, RLogical.TRUE);
     }
 
     public static RNode create(boolean inReplacement, RNode profiledVector, ConvertIndex index) {
@@ -169,11 +173,11 @@ abstract class SubscriptSpecial2 extends SubscriptSpecial2Base {
     }
 }
 
-@RBuiltin(name = "[[", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
+@RBuiltin(name = "[[", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE_SUBSCRIPT)
 @TypeSystemReference(RTypes.class)
 public abstract class Subscript extends RBuiltinNode.Arg4 {
 
-    @RBuiltin(name = ".subset2", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, behavior = PURE)
+    @RBuiltin(name = ".subset2", kind = PRIMITIVE, parameterNames = {"x", "...", "exact", "drop"}, behavior = PURE_SUBSCRIPT)
     public abstract class DefaultBuiltin {
         // same implementation as "[[", with different dispatch
     }
@@ -219,11 +223,11 @@ public abstract class Subscript extends RBuiltinNode.Arg4 {
     }
 
     @Specialization(guards = "!indexes.isEmpty()")
-    protected Object get(VirtualFrame frame, Object x, RArgsValuesAndNames indexes, RAbstractLogicalVector exact, @SuppressWarnings("unused") Object drop) {
+    protected Object get(Object x, RArgsValuesAndNames indexes, RAbstractLogicalVector exact, @SuppressWarnings("unused") Object drop) {
         /*
          * "drop" is not actually used by this builtin, but it needs to be in the argument list
          * (because the "drop" argument needs to be skipped).
          */
-        return extractNode.apply(frame, x, indexes.getArguments(), exact, RLogical.TRUE);
+        return extractNode.apply(x, indexes.getArguments(), exact, RLogical.TRUE);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
index 6d6a04e16b09ab36560a092af70c849b6dc5ba66..107b02ea74c06e5f4d067ab9738cbe24d8cf4225 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Subset.java
@@ -24,12 +24,11 @@ package com.oracle.truffle.r.nodes.builtin.base.infix;
 
 import static com.oracle.truffle.r.nodes.builtin.base.infix.SpecialsUtils.convertIndex;
 import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_SUBSET;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
@@ -78,9 +77,9 @@ abstract class SubsetSpecial extends SubscriptSpecialBase {
     }
 
     @Specialization(guards = {"simpleVector(vector)", "!inReplacement"})
-    protected Object access(VirtualFrame frame, RAbstractVector vector, Object index,
+    protected Object access(RAbstractVector vector, Object index,
                     @Cached("createAccess()") ExtractVectorNode extract) {
-        return extract.apply(frame, vector, new Object[]{index}, RRuntime.LOGICAL_TRUE, RLogical.TRUE);
+        return extract.apply(vector, new Object[]{index}, RRuntime.LOGICAL_TRUE, RLogical.TRUE);
     }
 
     public static RNode create(boolean inReplacement, RNode vectorNode, ConvertIndex index) {
@@ -116,10 +115,10 @@ abstract class SubsetSpecial2 extends SubscriptSpecial2Base {
     }
 }
 
-@RBuiltin(name = "[", kind = PRIMITIVE, parameterNames = {"x", "...", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE)
+@RBuiltin(name = "[", kind = PRIMITIVE, parameterNames = {"x", "...", "drop"}, dispatch = INTERNAL_GENERIC, behavior = PURE_SUBSET)
 public abstract class Subset extends RBuiltinNode.Arg3 {
 
-    @RBuiltin(name = ".subset", kind = PRIMITIVE, parameterNames = {"", "...", "drop"}, behavior = PURE)
+    @RBuiltin(name = ".subset", kind = PRIMITIVE, parameterNames = {"", "...", "drop"}, behavior = PURE_SUBSET)
     public abstract class DefaultBuiltin {
         // same implementation as "[", with different dispatch
     }
@@ -162,7 +161,7 @@ public abstract class Subset extends RBuiltinNode.Arg3 {
     }
 
     @Specialization(guards = "!indexes.isEmpty()")
-    protected Object get(VirtualFrame frame, Object x, RArgsValuesAndNames indexes, Object drop) {
-        return extractNode.apply(frame, x, indexes.getArguments(), RLogical.TRUE, drop);
+    protected Object get(Object x, RArgsValuesAndNames indexes, Object drop) {
+        return extractNode.apply(x, indexes.getArguments(), RLogical.TRUE, drop);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
index 3d1e5f25835fc4646394354aa6611cd29187b945..b73fcb9cc98050b48c2d5f5652c1c962323a10b9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateField.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
@@ -66,7 +65,7 @@ abstract class UpdateFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
         return value != RNull.instance && !(value instanceof RList);
     }
 
-    @Specialization(limit = "2", guards = {"isSimpleList(list)", "!list.isShared()", "list.getNames() == cachedNames", "field == cachedField", "isNotRNullRList(value)"})
+    @Specialization(limit = "2", guards = {"!list.isShared()", "getNamesNode.getNames(list) == cachedNames", "field == cachedField", "isNotRNullRList(value)"})
     public Object doList(RList list, @SuppressWarnings("unused") String field, Object value,
                     @SuppressWarnings("unused") @Cached("list.getNames()") RStringVector cachedNames,
                     @SuppressWarnings("unused") @Cached("field") String cachedField,
@@ -83,7 +82,7 @@ abstract class UpdateFieldSpecial extends SpecialsUtils.ListFieldSpecialBase {
         return list;
     }
 
-    @Specialization(replaces = "doList", guards = {"isSimpleList(list)", "!list.isShared()", "list.getNames() != null", "isNotRNullRList(value)"})
+    @Specialization(replaces = "doList", guards = {"!list.isShared()", "list.getNames() != null", "isNotRNullRList(value)"})
     public RList doListDynamic(RList list, String field, Object value) {
         int index = getIndex(getNamesNode.getNames(list), field);
         if (index == -1) {
@@ -131,9 +130,9 @@ public abstract class UpdateField extends RBuiltinNode.Arg3 {
     }
 
     @Specialization
-    protected Object update(VirtualFrame frame, Object container, String field, Object value) {
+    protected Object update(Object container, String field, Object value) {
         Object list = coerceList.profile(container instanceof RAbstractListVector) ? container : coerceList(container);
-        return update.apply(frame, list, new Object[]{field}, value);
+        return update.apply(list, new Object[]{field}, value);
     }
 
     private Object coerceList(Object vector) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
index 9bc4b7371cd0ea03c0fd97b882ca9b6dd3a0d928..36cf01ffbe3ead88ac0e13686cea150534705af0 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java
@@ -174,7 +174,7 @@ public abstract class UpdateSubscript extends RBuiltinNode.Arg2 {
     }
 
     @Specialization(guards = "!args.isEmpty()")
-    protected Object update(VirtualFrame frame, Object x, RArgsValuesAndNames args) {
+    protected Object update(Object x, RArgsValuesAndNames args) {
         Object value = args.getArgument(args.getLength() - 1);
         Object[] pos;
         if (argsLengthLargerThanOneProfile.profile(args.getLength() > 1)) {
@@ -182,7 +182,7 @@ public abstract class UpdateSubscript extends RBuiltinNode.Arg2 {
         } else {
             pos = new Object[]{RMissing.instance};
         }
-        return replaceNode.apply(frame, x, pos, value);
+        return replaceNode.apply(x, pos, value);
     }
 
     @Specialization(guards = "args.isEmpty()")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
index bb734f4ae2ccc9815be1e4df37bb5aa08aa46c8f..bf0e061a755ba8e6c8c49074541428b5cb4bf8c5 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubset.java
@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import java.util.Arrays;
 
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
@@ -67,7 +66,7 @@ public abstract class UpdateSubset extends RBuiltinNode.Arg1 {
     }
 
     @Specialization(guards = "args.getLength() >= 2")
-    protected Object update(VirtualFrame frame, RArgsValuesAndNames args) {
+    protected Object update(RArgsValuesAndNames args) {
         // first argument: object to assign to
         Object x = args.getArgument(0);
 
@@ -81,7 +80,7 @@ public abstract class UpdateSubset extends RBuiltinNode.Arg1 {
         } else {
             pos = new Object[]{RMissing.instance};
         }
-        return replaceNode.apply(frame, x, pos, value);
+        return replaceNode.apply(x, pos, value);
     }
 
     @Specialization(guards = "args.getLength() < 2")
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
index 635ec096266e654196e0ba316bf4b1b073197384..1416ca77c41feada5d35aee74e388cf51f641710 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java
@@ -427,27 +427,14 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
 
     @TruffleBoundary
     private static String encodeComplex(RComplex x, int wr, int dr, int er, int wi, int di, int ei, char cdec, int digits, String naString) {
-        String buff;
-        String im;
-        String re;
-        boolean flagNegIm = false;
-        RComplex y;
-
-        double xr = x.getRealPart();
-        double xi = x.getImaginaryPart();
-
         /* IEEE allows signed zeros; strip these here */
-        if (xr == 0.0) {
-            xr = 0.0;
-        }
-        if (xi == 0.0) {
-            xi = 0.0;
-        }
+        double xr = RRuntime.normalizeZero(x.getRealPart());
+        double xi = RRuntime.normalizeZero(x.getImaginaryPart());
 
         if (RRuntime.isNA(xr) || RRuntime.isNA(xi)) {
             int g = Math.min(wr + wi + 2, (NB - 1));
             String fmt = "%" + Utils.asBlankArg(g) + "s";
-            buff = Utils.snprintf(NB,
+            return Utils.snprintf(NB,
                             fmt, /* was "%*s%*s", R_print.gap, "", */
                             naString);
         } else {
@@ -456,24 +443,25 @@ public final class ComplexVectorPrinter extends VectorPrinter<RAbstractComplexVe
              * get strange trailing zeros. But we do want to avoid printing small exponentials that
              * are probably garbage.
              */
-            y = zprecr(x, digits);
+            RComplex y = zprecr(x, digits);
+            String re;
             if (y.getRealPart() == 0.) {
                 re = DoubleVectorPrinter.encodeReal(y.getRealPart(), wr, dr, er, cdec, naString);
             } else {
                 re = DoubleVectorPrinter.encodeReal(xr, wr, dr, er, cdec, naString);
             }
-            flagNegIm = xi < 0;
+            boolean flagNegIm = xi < 0;
             if (flagNegIm) {
                 xi = -xi;
             }
+            String im;
             if (y.getImaginaryPart() == 0.) {
                 im = DoubleVectorPrinter.encodeReal(y.getImaginaryPart(), wi, di, ei, cdec, naString);
             } else {
                 im = DoubleVectorPrinter.encodeReal(xi, wi, di, ei, cdec, naString);
             }
-            buff = snprintf(NB, "%s%s%si", re, flagNegIm ? "-" : "+", im);
+            return snprintf(NB, "%s%s%si", re, flagNegIm ? "-" : "+", im);
         }
-        return buff;
     }
 
     public static String[] format(RAbstractComplexVector value, boolean trim, int nsmall, int width, char decimalMark, PrintParameters pp) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
index 9ee413f6e6f9a50696f92847f6361c4628c1038d..1a1e8590b42cc2ed94454809333400f1ef893a0b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java
@@ -11,11 +11,7 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
-import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
-
 import java.io.IOException;
-import java.math.RoundingMode;
-import java.text.DecimalFormat;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -312,9 +308,9 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
                  * assumption that R_dec_min_exponent+303 is in range. Representation of 1e+303 has
                  * low error.
                  */
-                rPrec = (rPrec * 1e+303) / Math.pow(10, kp + 303);
+                rPrec = (rPrec * 1e+303) / DECIMAL_WEIGHTS[kp + 303 + DECIMAL_SHIFT];
             } else {
-                rPrec /= Math.pow(10, kp);
+                rPrec /= DECIMAL_WEIGHTS[kp + DECIMAL_SHIFT];
             }
             if (rPrec < tbl[digits]) {
                 rPrec *= 10.0;
@@ -354,7 +350,6 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
             double fuzz = 0.5 / tbl[1 + rgt];
             // kpower can be bigger than the table.
             roundingwidens = kpower > 0 && kpower <= KP_MAX && r < tbl[kpower + 1] - fuzz;
-
         }
 
         return new ScientificDouble(sgn, kpower, nsig, roundingwidens);
@@ -386,14 +381,32 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
         return encodeReal(x, dm.maxWidth, dm.d, dm.e, '.', pp);
     }
 
-    // caching some commonly used formats
-    private static final DecimalFormat[] CACHED_FORMATS = new DecimalFormat[32];
+    private static final int DECIMAL_SHIFT = 350;
+    private static final double[][] DECIMAL_VALUES = new double[700][10];
+    /**
+     * This array contains the halves minus the unit of least precision, e.g. 0.499999...
+     */
+    private static final double[] HALVES_MINUS_ULP = new double[700];
+    private static final double[] DECIMAL_WEIGHTS = new double[700];
+
+    static {
+        for (int i = 0; i < DECIMAL_WEIGHTS.length; i++) {
+            DECIMAL_WEIGHTS[i] = Math.pow(10, i - DECIMAL_SHIFT);
+        }
+        for (int i = 0; i < DECIMAL_VALUES.length; i++) {
+            for (int i2 = 0; i2 < 10; i2++) {
+                DECIMAL_VALUES[i][i2] = Math.pow(10, i - DECIMAL_SHIFT) * i2;
+            }
+            HALVES_MINUS_ULP[i] = Double.longBitsToDouble(Double.doubleToLongBits(DECIMAL_VALUES[i][5]) - 1);
+        }
+    }
 
     @TruffleBoundary
     static String encodeReal(double initialX, int w, int d, int e, char cdec, String naString) {
         /* IEEE allows signed zeros (yuck!) */
         double x = RRuntime.normalizeZero(initialX);
 
+        StringBuilder str = new StringBuilder(w);
         if (!RRuntime.isFinite(x)) {
             String id;
             if (RRuntime.isNA(x)) {
@@ -403,49 +416,137 @@ public final class DoubleVectorPrinter extends VectorPrinter<RAbstractDoubleVect
             } else {
                 id = x > 0 ? "Inf" : "-Inf";
             }
-            return prependBlanks(w, id);
-        } else if (e != 0) {
-            String fmt = String.format((d != 0) ? "%%#%d.%de" : "%%%d.%de", Math.min(w, (NB - 1)), d);
-            String result;
-            if (Math.abs(x) < 1e-300 && Math.abs(x) >= Double.MIN_VALUE) {
-                // work around java formatting bug for small numbers like 1.53160350210786e-322
-                result = snprintf(NB, fmt, x * 1e100);
-                StringBuilder str = new StringBuilder(result);
-                assert str.charAt(str.length() - 3) == '2';
-                str.setCharAt(str.length() - 3, '3');
-                result = str.toString();
-            } else {
-                result = snprintf(NB, fmt, x);
+            int blanks = w - id.length();
+            for (int i = 0; i < blanks; i++) {
+                str.append(' ');
             }
-            return result.replace('.', cdec);
-        } else { /* e = 0 */
-            DecimalFormat df = null;
-            if (d < CACHED_FORMATS.length) {
-                df = CACHED_FORMATS[d];
+            str.append(id);
+        } else {
+            boolean negated = x < 0;
+            if (negated) {
+                x = -x;
             }
-            if (df == null) {
-                df = new DecimalFormat("#.#");
-                df.setRoundingMode(RoundingMode.HALF_EVEN);
-                df.setDecimalSeparatorAlwaysShown(false);
-                df.setMinimumFractionDigits(d);
-                df.setMaximumFractionDigits(d);
-                if (d < CACHED_FORMATS.length) {
-                    CACHED_FORMATS[d] = df;
+            if (e != 0) {
+
+                boolean shifted = false;
+                int log10;
+                int adjustedE = e;
+                if (x == 0) {
+                    log10 = 0;
+                } else {
+                    if (x < 1e-300) {
+                        shifted = true;
+                        x *= 1e100;
+                    }
+                    log10 = (int) Math.log10(x);
+                    if (DECIMAL_WEIGHTS[log10 + DECIMAL_SHIFT] > x) {
+                        // log10 behaves differently for < 1.0
+                        log10--;
+                    }
+                    if (log10 <= -100 || log10 >= 100) {
+                        adjustedE = 3;
+                    }
+                }
+                int blanks = w // target width
+                                - (negated ? 1 : 0) // "-"
+                                - 1 // digits before "."
+                                - (d > 0 ? 1 : 0)  // "."
+                                - d // digits after "."
+                                - 1 // "e"
+                                - 1 // "+/-" for exponent
+                                - Math.max(2, adjustedE); // digits for exponent
+                for (int i = 0; i < blanks; i++) {
+                    str.append(' ');
+                }
+
+                double pow10 = DECIMAL_WEIGHTS[-log10 + d + DECIMAL_SHIFT];
+                long mantissa = (long) (x * pow10);
+                // round towards next digit instead of truncating
+                double rounded;
+                if ((mantissa & 1L) == 0) {
+                    // even
+                    rounded = x + HALVES_MINUS_ULP[log10 - d - 1 + DECIMAL_SHIFT];
+                } else {
+                    rounded = x + DECIMAL_VALUES[log10 - d - 1 + DECIMAL_SHIFT][5];
+                }
+
+                if (Double.isFinite(rounded)) {
+                    x = rounded;
+                    // the rounding might have modified the exponent
+                    if (DECIMAL_WEIGHTS[log10 + 1 + DECIMAL_SHIFT] <= x) {
+                        log10++;
+                    }
+                }
+                if (negated) {
+                    str.append('-');
+                }
+                x = appendDigit(x, log10, str);
+                if (d > 0) {
+                    str.append(cdec);
+                    for (int i = 1; i <= d; i++) {
+                        x = appendDigit(x, log10 - i, str);
+                    }
+                }
+                str.append('e');
+                if (log10 < 0) {
+                    str.append('-');
+                    log10 = -log10;
+                } else {
+                    str.append('+');
+                }
+                if (shifted) {
+                    log10 += 100;
+                }
+                if (adjustedE >= 3) {
+                    str.append((char) ('0' + (log10 / 100)));
+                    log10 = log10 % 100;
+                }
+                str.append((char) ('0' + (log10 / 10)));
+                str.append((char) ('0' + (log10 % 10)));
+            } else { /* e == 0 */
+                double pow10 = DECIMAL_WEIGHTS[d + DECIMAL_SHIFT];
+                long mantissa = (long) (x * pow10);
+                // round towards next digit instead of truncating
+                if ((mantissa & 1L) == 0) {
+                    // even
+                    x += HALVES_MINUS_ULP[-d - 1 + DECIMAL_SHIFT];
+                } else {
+                    x += DECIMAL_VALUES[-d - 1 + DECIMAL_SHIFT][5];
+                }
+
+                int log10 = x == 0 ? 0 : Math.max((int) Math.log10(x), 0);
+                int blanks = w // target width
+                                - (negated ? 1 : 0) // "-"
+                                - (log10 + 1) // digits before "."
+                                - (d > 0 ? 1 : 0) // "."
+                                - d; // digits after "."
+
+                for (int i = 0; i < blanks; i++) {
+                    str.append(' ');
+                }
+                if (negated) {
+                    str.append('-');
+                }
+                for (int i = log10; i >= 0; i--) {
+                    x = appendDigit(x, i, str);
+                }
+                if (d > 0) {
+                    str.append(cdec);
+                    for (int i = 1; i <= d; i++) {
+                        x = appendDigit(x, -i, str);
+                    }
                 }
             }
-            return prependBlanks(w, df.format(x)).replace('.', cdec);
         }
+        assert str.length() >= w;
+        return str.toString();
     }
 
-    private static String prependBlanks(int width, String id) {
-        if (id.length() >= width) {
-            return id;
-        }
-        StringBuilder str = new StringBuilder(width);
-        for (int i = 0; i < width - id.length(); i++) {
-            str.append(' ');
-        }
-        return str.append(id).toString();
+    private static double appendDigit(double x, int digit, StringBuilder str) {
+        int c = (int) (x / DECIMAL_WEIGHTS[digit + DECIMAL_SHIFT]);
+        assert c >= 0 && c <= 9;
+        str.append((char) ('0' + c));
+        return x - DECIMAL_VALUES[digit + DECIMAL_SHIFT][c];
     }
 
     public static String[] format(RAbstractDoubleVector value, boolean trim, int nsmall, int width, char decimalMark, PrintParameters pp) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FormatMetrics.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FormatMetrics.java
index 052d4675874c6853669d8229963763e069e200ca..c0f020d91e9eaba2f3b4519c7d60493d2ef0c40b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FormatMetrics.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FormatMetrics.java
@@ -25,7 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base.printer;
 /**
  * The generic formatting metrics. N.B. This class is public since it is used in the PrettyWriter
  * public API.
- * 
+ *
  * @see PrettyWriter
  */
 public class FormatMetrics {
@@ -34,7 +34,6 @@ public class FormatMetrics {
     int maxWidth;
 
     FormatMetrics(int maxWidth) {
-        super();
         this.originalMaxWidth = maxWidth;
         this.maxWidth = maxWidth;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
index 5453a2fa40ab27cf826ab8da4ca2a6f58cda10b8..f9d0ea7c4f89cb0cf9b1470a644d0615fee0eed6 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java
@@ -46,7 +46,7 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
 
         @Override
         protected FormatMetrics formatVector(int offs, int len) {
-            return formatIntVector(vector, offs, len, printCtx.parameters().getNaWidth());
+            return new FormatMetrics(formatIntVectorInternal(vector, offs, len, printCtx.parameters().getNaWidth()));
         }
 
         @Override
@@ -66,7 +66,7 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
         }
     }
 
-    public static FormatMetrics formatIntVector(RAbstractIntVector x, int offs, int n, int naWidth) {
+    static int formatIntVectorInternal(RAbstractIntVector x, int offs, int n, int naWidth) {
         int xmin = RRuntime.INT_MAX_VALUE;
         int xmax = RRuntime.INT_MIN_VALUE;
         boolean naflag = false;
@@ -105,21 +105,62 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
                 fieldwidth = l;
             }
         }
+        return fieldwidth;
+    }
+
+    private static final int[][] DECIMAL_VALUES = new int[10][10];
+    private static final int[] DECIMAL_WEIGHTS = new int[10];
 
-        return new FormatMetrics(fieldwidth);
+    static {
+        for (int i = 0; i < DECIMAL_WEIGHTS.length; i++) {
+            DECIMAL_WEIGHTS[i] = (int) Math.pow(10, i);
+        }
+        for (int i = 0; i < DECIMAL_VALUES.length; i++) {
+            for (int i2 = 0; i2 < 10; i2++) {
+                DECIMAL_VALUES[i][i2] = (int) (Math.pow(10, i) * i2);
+            }
+        }
     }
 
-    /*
-     * There is no documented (or enforced) limit on 'w' here, so use snprintf
-     */
-    static int NB = 1000;
+    public static String encodeInteger(int initialX, int w, PrintParameters pp) {
+        StringBuilder str = new StringBuilder(w);
 
-    public static String encodeInteger(int x, int w, PrintParameters pp) {
-        if (x == RRuntime.INT_NA) {
-            return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "s", pp.getNaString());
+        int x = initialX;
+        if (RRuntime.isNA(x)) {
+            String id = pp.getNaString();
+            for (int i = w - id.length(); i > 0; i--) {
+                str.append(' ');
+            }
+            str.append(id);
         } else {
-            return Utils.snprintf(NB, "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "d", x);
+            boolean negated = false;
+            if (x < 0) {
+                negated = true;
+                x = -x;
+            }
+            int log10 = x == 0 ? 0 : (int) Math.log10(x);
+            int blanks = w // target width
+                            - (negated ? 1 : 0) // "-"
+                            - (log10 + 1); // digits
+
+            for (int i = 0; i < blanks; i++) {
+                str.append(' ');
+            }
+            if (negated) {
+                str.append('-');
+            }
+            for (int i = log10; i >= 0; i--) {
+                x = appendDigit(x, i, str);
+            }
         }
+        return str.toString();
+    }
+
+    private static int appendDigit(int x, int digit, StringBuilder str) {
+        int c = x / DECIMAL_WEIGHTS[digit];
+        assert c >= 0 && c <= 9;
+        str.append((char) ('0' + c));
+        return x - DECIMAL_VALUES[digit][c];
     }
 
     public static String[] format(RAbstractIntVector value, boolean trim, int width, PrintParameters pp) {
@@ -127,8 +168,7 @@ public final class IntegerVectorPrinter extends VectorPrinter<RAbstractIntVector
         if (trim) {
             w = 1;
         } else {
-            FormatMetrics metrics = formatIntVector(value, 0, value.getLength(), pp.getNaWidth());
-            w = metrics.maxWidth;
+            w = formatIntVectorInternal(value, 0, value.getLength(), pp.getNaWidth());
         }
         w = Math.max(w, width);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
index 3cde3e059f0377c95c9090efa054f8b38b05f3e0..d1f913348016edbc453d52d9128a5c5d107670bd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
@@ -71,15 +71,15 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
         int ns = s.getLength();
         String[] t = new String[ns];
         for (int i = 0; i < ns; i++) {
-            Object tmp = RRuntime.asAbstractVector(s.getDataAtAsObject(i));
+            Object tmp = RRuntime.convertScalarVectors(s.getDataAtAsObject(i));
             final String pbuf;
             if (tmp == null || tmp == RNull.instance) {
                 pbuf = RRuntime.NULL;
             } else if (tmp instanceof RAbstractLogicalVector) {
                 RAbstractLogicalVector lv = (RAbstractLogicalVector) tmp;
                 if (lv.getLength() == 1) {
-                    FormatMetrics fm = LogicalVectorPrinter.formatLogicalVector(lv, 0, 1, pp.getNaWidth());
-                    pbuf = LogicalVectorPrinter.encodeLogical(lv.getDataAt(0), fm.maxWidth, pp);
+                    int width = LogicalVectorPrinter.formatLogicalVectorInternal(lv, 0, 1, pp.getNaWidth());
+                    pbuf = LogicalVectorPrinter.encodeLogical(lv.getDataAt(0), width, pp);
                 } else {
                     pbuf = "Logical," + lv.getLength();
                 }
@@ -90,8 +90,8 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
                     pbuf = "factor," + iv.getLength();
                 } else {
                     if (iv.getLength() == 1) {
-                        FormatMetrics fm = IntegerVectorPrinter.formatIntVector(iv, 0, 1, pp.getNaWidth());
-                        pbuf = IntegerVectorPrinter.encodeInteger(iv.getDataAt(0), fm.maxWidth, pp);
+                        int width = IntegerVectorPrinter.formatIntVectorInternal(iv, 0, 1, pp.getNaWidth());
+                        pbuf = IntegerVectorPrinter.encodeInteger(iv.getDataAt(0), width, pp);
                     } else {
                         pbuf = "Integer," + iv.getLength();
                     }
@@ -165,7 +165,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
         int ns = s.getLength();
 
         RAbstractStringVector names;
-        names = Utils.castTo(RRuntime.asAbstractVector(s.getNames()));
+        names = Utils.castTo(RRuntime.convertScalarVectors(s.getNames()));
 
         if (ns > 0) {
             int npr = (ns <= pp.getMax() + 1) ? ns : pp.getMax();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
index 29231624992cce41ae975e5c03bbc1b88038f6fa..3421a15d5b01f989d577a8e5b274bea67a117002 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java
@@ -11,9 +11,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
-import static com.oracle.truffle.r.nodes.builtin.base.printer.IntegerVectorPrinter.NB;
-import static com.oracle.truffle.r.nodes.builtin.base.printer.Utils.snprintf;
-
 import java.io.IOException;
 
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -47,13 +44,12 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
 
         @Override
         protected FormatMetrics formatVector(int offs, int len) {
-            return formatLogicalVector(vector, offs, len, printCtx.parameters().getNaWidth());
+            return new FormatMetrics(formatLogicalVectorInternal(vector, offs, len, printCtx.parameters().getNaWidth()));
         }
 
         @Override
         protected void printElement(int i, FormatMetrics fm) throws IOException {
-            String v = encodeLogical(vector.getDataAt(i), fm.maxWidth, printCtx.parameters());
-            out.print(v);
+            out.print(encodeLogical(vector.getDataAt(i), fm.maxWidth, printCtx.parameters()));
         }
 
         @Override
@@ -67,7 +63,7 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
         }
     }
 
-    static FormatMetrics formatLogicalVector(RAbstractLogicalVector x, int offs, int n, int naWidth) {
+    static int formatLogicalVectorInternal(RAbstractLogicalVector x, int offs, int n, int naWidth) {
         int fieldwidth = 1;
         for (int i = 0; i < n; i++) {
             byte xi = x.getDataAt(offs + i);
@@ -83,18 +79,29 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
                 /* this is the widest it can be, so stop */
             }
         }
-        return new FormatMetrics(fieldwidth);
+        return fieldwidth;
     }
 
     static String encodeLogical(byte x, int w, PrintParameters pp) {
-        final String fmt = "%" + Utils.asBlankArg(Math.min(w, (NB - 1))) + "s";
+        String id;
         if (x == RRuntime.LOGICAL_NA) {
-            return snprintf(NB, fmt, pp.getNaString());
-        } else if (x != 0) {
-            return snprintf(NB, fmt, "TRUE");
+            id = pp.getNaString();
+        } else if (x != RRuntime.LOGICAL_FALSE) {
+            id = "TRUE";
         } else {
-            return snprintf(NB, fmt, "FALSE");
+            id = "FALSE";
+        }
+        if (id.length() == w) {
+            return id;
+        }
+        int blanks = w // target width
+                        - id.length(); // text
+        StringBuilder str = new StringBuilder();
+        for (int i = 0; i < blanks; i++) {
+            str.append(' ');
         }
+        str.append(id);
+        return str.toString();
     }
 
     public static String[] format(RAbstractLogicalVector value, boolean trim, int width, PrintParameters pp) {
@@ -102,8 +109,7 @@ public final class LogicalVectorPrinter extends VectorPrinter<RAbstractLogicalVe
         if (trim) {
             w = 1;
         } else {
-            FormatMetrics metrics = formatLogicalVector(value, 0, value.getLength(), pp.getNaWidth());
-            w = metrics.maxWidth;
+            w = formatLogicalVectorInternal(value, 0, value.getLength(), pp.getNaWidth());
         }
         w = Math.max(w, width);
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
index 8d357469522dcb9584c6a379ea3c8517efa14423..c73fabdda712ae98656ae584182d7289738e7341 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java
@@ -50,7 +50,7 @@ final class PairListPrinter extends AbstractValuePrinter<RPairList> {
         if (dims != null && dims.getLength() > 1) {
             String[] t = new String[ns];
             for (int i = 0; i < ns; i++) {
-                Object tmp = RRuntime.asAbstractVector(s.getDataAtAsObject(i));
+                Object tmp = RRuntime.convertScalarVectors(s.getDataAtAsObject(i));
                 final String pbuf;
                 if (tmp == null || tmp == RNull.instance) {
                     pbuf = RRuntime.NULL;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
index 45a9a4724b7fe11f0944cb97c36d72174976e2a8..728f9e8e90004906b1b31a1852b1732e8efe3190 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java
@@ -11,8 +11,6 @@
  */
 package com.oracle.truffle.r.nodes.builtin.base.printer;
 
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 
 //Transcribed from GnuR, src/include/Print.h
@@ -23,8 +21,6 @@ import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 public final class PrintParameters {
-    @CompilationFinal private static int DefaultDigits = -1;
-
     private int width;
     private int naWidth;
     private int naWidthNoquote;
@@ -45,11 +41,7 @@ public final class PrintParameters {
     private boolean suppressIndexLabels;
 
     public static int getDefaultDigits() {
-        if (DefaultDigits == -1) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            DefaultDigits = RRuntime.asInteger(RContext.getInstance().stateROptions.getValue("digits"));
-        }
-        return DefaultDigits;
+        return RRuntime.asInteger(RContext.getInstance().stateROptions.getValue("digits"));
     }
 
     public PrintParameters() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RArgsValuesAndNamesPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RArgsValuesAndNamesPrinter.java
new file mode 100644
index 0000000000000000000000000000000000000000..7b46744d7cf8e1e14aece5cf379ee90c2e460254
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/RArgsValuesAndNamesPrinter.java
@@ -0,0 +1,41 @@
+/*
+ * 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.nodes.builtin.base.printer;
+
+import java.io.IOException;
+
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+
+public final class RArgsValuesAndNamesPrinter extends AbstractValuePrinter<RArgsValuesAndNames> {
+
+    public static final RArgsValuesAndNamesPrinter INSTANCE = new RArgsValuesAndNamesPrinter();
+
+    private RArgsValuesAndNamesPrinter() {
+    }
+
+    @Override
+    protected void printValue(RArgsValuesAndNames value, PrintContext printCtx) throws IOException {
+        StringVectorPrinter.INSTANCE.print(RDataFactory.createStringVector("<...>"), printCtx);
+    }
+}
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 662a227111f22dc328e300f21616f61edfd10dae..ca3ba2e74e589591a357d2425a26f2377b40e656 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
@@ -26,16 +26,12 @@ import java.io.IOException;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.TruffleLanguage;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 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.nodes.Node;
-import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
@@ -560,17 +556,4 @@ public final class ValuePrinterNode extends RBaseNode {
             PrintContext.leave();
         }
     }
-
-    @SuppressWarnings("deprecation")
-    public static String prettyPrint(final Object value) {
-        return (String) Truffle.getRuntime().createCallTarget(new RootNode(TruffleLanguage.class, null, null) {
-
-            @Child ValuePrinterNode valuePrinterNode = new ValuePrinterNode();
-
-            @Override
-            public Object execute(VirtualFrame frame) {
-                return valuePrinterNode.prettyPrint(value, AnyVectorToStringVectorWriter::new);
-            }
-        }).call(value);
-    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
index 0bd88751d6643cdb10f595f18ad40e3a5b98507f..e3c2e29a373bec5ea0d6026dc2f2b3b6c09eb518 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.r.nodes.function.ClassHierarchyNode;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
@@ -107,6 +108,8 @@ final class ValuePrinters implements ValuePrinter<Object> {
                     printer = RawVectorPrinter.INSTANCE;
                 } else if (x instanceof RAbstractListVector) {
                     printer = ListPrinter.INSTANCE;
+                } else if (x instanceof RArgsValuesAndNames) {
+                    printer = RArgsValuesAndNamesPrinter.INSTANCE;
                 } else if (x instanceof REnvironment) {
                     printer = EnvironmentPrinter.INSTANCE;
                 } else if (x instanceof TruffleObject) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
index 611ee0d6eae2e000a2f3ef45a855f3e740a1f942..e2a12e3ae18c0977f6db8c47300dac10950c6080 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
@@ -81,7 +81,7 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
                 if (dims.getLength() == 1) {
                     RList t = Utils.<RList> castTo(getDimNames(vector));
                     if (t != null && t.getDataAt(0) != null) {
-                        RAbstractStringVector nn = Utils.castTo(RRuntime.asAbstractVector(t.getNames()));
+                        RAbstractStringVector nn = Utils.castTo(RRuntime.convertScalarVectors(t.getNames()));
 
                         if (nn != null) {
                             title = nn.getDataAt(0);
@@ -90,7 +90,7 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
                         }
 
                         jobMode = vector.getLength() == 0 ? JobMode.namedEmpty : JobMode.named;
-                        names = Utils.castTo(RRuntime.asAbstractVector(t.getDataAt(0)));
+                        names = Utils.castTo(RRuntime.convertScalarVectors(t.getDataAt(0)));
                     } else {
                         title = null;
                         names = null;
@@ -112,7 +112,7 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
                 Object namesAttr = Utils.castTo(getNames(vector));
                 if (namesAttr != null) {
                     if (vector.getLength() > 0) {
-                        names = Utils.castTo(RRuntime.asAbstractVector(namesAttr));
+                        names = Utils.castTo(RRuntime.convertScalarVectors(namesAttr));
                         jobMode = JobMode.named;
                     } else {
                         names = null;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/compiler/R/compiler_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/compiler/R/compiler_overrides.R
new file mode 100644
index 0000000000000000000000000000000000000000..f7bfb97550110fae9ecf410b22f25fcd7aaaaa62
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/compiler/R/compiler_overrides.R
@@ -0,0 +1,24 @@
+# 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.
+
+eval(expression({
+compile <- function(f, ...) f
+}), asNamespace("compiler"))
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 3594b6ceaaeb548248103ca47531d29805e995b6..1fec8cd3b23c6b2290daafc56f8784015f74b0b5 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
@@ -34,24 +34,26 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.TruffleContext;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RChannel;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.ChildContextInfo;
+import com.oracle.truffle.r.runtime.context.EvalThread;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
-import com.oracle.truffle.r.runtime.context.RContext.EvalThread;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -96,10 +98,10 @@ public class FastRContext {
     }
 
     private static void handleSharedContexts(ContextKind contextKind) {
-        if (contextKind == ContextKind.SHARE_ALL) {
+        if (contextKind == ContextKind.SHARE_ALL && EvalThread.threadCnt.get() == 0) {
             RContext current = RContext.getInstance();
             if (EvalThread.threadCnt.get() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) {
-                ContextInfo.resetMultiSlotIndexGenerator();
+                ChildContextInfo.resetMultiSlotIndexGenerator();
             } else {
                 throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Shared contexts can be created only if no other child contexts exist");
             }
@@ -135,15 +137,18 @@ public class FastRContext {
             handleSharedContexts(contextKind);
 
             int length = exprs.getLength();
-            RContext.EvalThread[] threads = new RContext.EvalThread[length];
+            EvalThread[] threads = new EvalThread[length];
             int[] data = new int[length];
+            int[] multiSlotIndices = new int[length];
             for (int i = 0; i < length; i++) {
-                ContextInfo info = createContextInfo(contextKind);
-                threads[i] = new RContext.EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL));
+                ChildContextInfo info = createContextInfo(contextKind);
+                threads[i] = new EvalThread(RContext.getInstance().threads, info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL),
+                                FastROptions.SpawnUsesPolyglot.getBooleanValue());
                 data[i] = info.getId();
+                multiSlotIndices[i] = info.getMultiSlotInd();
             }
             if (contextKind == ContextKind.SHARE_ALL) {
-                REnvironment.convertSearchpathToMultiSlot();
+                REnvironment.convertSearchpathToMultiSlot(multiSlotIndices);
             }
             for (int i = 0; i < length; i++) {
                 threads[i].start();
@@ -167,8 +172,13 @@ public class FastRContext {
         @TruffleBoundary
         protected RNull eval(RAbstractIntVector handle) {
             try {
+                int[] multiSlotIndices = new int[handle.getLength()];
                 for (int i = 0; i < handle.getLength(); i++) {
-                    Thread thread = RContext.EvalThread.threads.get(handle.getDataAt(i));
+                    int id = handle.getDataAt(i);
+                    Thread thread = RContext.getInstance().threads.get(id);
+                    if (EvalThread.idToMultiSlotTable.containsKey(id)) {
+                        multiSlotIndices[i] = EvalThread.idToMultiSlotTable.remove(id);
+                    }
                     if (thread == null) {
                         // already done
                         continue;
@@ -176,6 +186,12 @@ public class FastRContext {
                         thread.join();
                     }
                 }
+                // If all eval threads died, completely remove multi slot data.
+                if (EvalThread.threadCnt.get() == 0) {
+                    REnvironment.cleanupSearchpathFromMultiSlot();
+                } else {
+                    REnvironment.cleanupSearchpathFromMultiSlot(multiSlotIndices);
+                }
             } catch (InterruptedException ex) {
                 throw error(RError.Message.GENERIC, "error finishing eval thread");
 
@@ -220,22 +236,20 @@ public class FastRContext {
             int length = exprs.getLength();
             Object[] results = new Object[length];
             if (length == 1) {
-                ContextInfo info = createContextInfo(contextKind);
-                PolyglotEngine vm = info.createVM();
-                try {
-                    results[0] = RContext.EvalThread.run(vm, info, RSource.fromTextInternalInvisible(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL));
-                } finally {
-                    vm.dispose();
-                }
+                ChildContextInfo info = createContextInfo(contextKind);
+                TruffleContext truffleContext = info.createTruffleContext();
+                results[0] = EvalThread.run(truffleContext, info, RSource.fromTextInternalInvisible(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL));
             } else {
                 // separate threads that run in parallel; invoking thread waits for completion
-                RContext.EvalThread[] threads = new RContext.EvalThread[length];
+                EvalThread[] threads = new EvalThread[length];
+                int[] multiSlotIndices = new int[length];
                 for (int i = 0; i < length; i++) {
-                    ContextInfo info = createContextInfo(contextKind);
-                    threads[i] = new RContext.EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL));
+                    ChildContextInfo info = createContextInfo(contextKind);
+                    threads[i] = new EvalThread(RContext.getInstance().threads, info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL), false);
+                    multiSlotIndices[i] = info.getMultiSlotInd();
                 }
                 if (contextKind == ContextKind.SHARE_ALL) {
-                    REnvironment.convertSearchpathToMultiSlot();
+                    REnvironment.convertSearchpathToMultiSlot(multiSlotIndices);
                 }
                 for (int i = 0; i < length; i++) {
                     threads[i].start();
@@ -275,7 +289,7 @@ public class FastRContext {
         @Specialization
         @TruffleBoundary
         protected Object r(RAbstractStringVector args, RAbstractStringVector env, boolean intern) {
-            Object rc = RContext.getRRuntimeASTAccess().rcommandMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern);
+            Object rc = RContext.getRRuntimeASTAccess().rcommandMain(prependCommand(args, "R"), env.materialize().getDataCopy(), intern);
             return rc;
         }
 
@@ -311,7 +325,7 @@ public class FastRContext {
         @Specialization
         @TruffleBoundary
         protected Object rscript(RAbstractStringVector args, RAbstractStringVector env, boolean intern) {
-            return RContext.getRRuntimeASTAccess().rscriptMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern);
+            return RContext.getRRuntimeASTAccess().rscriptMain(prependCommand(args, "Rscript"), env.materialize().getDataCopy(), intern);
         }
 
         @Specialization
@@ -321,8 +335,18 @@ public class FastRContext {
         }
     }
 
-    private static ContextInfo createContextInfo(RContext.ContextKind contextKind) {
-        return ContextInfo.createNoRestore(Client.RSCRIPT, null, contextKind, RContext.getInstance(), RContext.getInstance().getConsoleHandler());
+    private static String[] prependCommand(RAbstractStringVector argsVec, String command) {
+        String[] argsVecArgs = argsVec.materialize().getDataCopy();
+        String[] result = new String[argsVecArgs.length + 1];
+        result[0] = command;
+        System.arraycopy(argsVecArgs, 0, result, 1, argsVecArgs.length);
+        return result;
+    }
+
+    private static ChildContextInfo createContextInfo(RContext.ContextKind contextKind) {
+        RContext context = RContext.getInstance();
+        ConsoleIO console = context.getConsole();
+        return ChildContextInfo.createNoRestore(Client.RSCRIPT, null, contextKind, context, console.getStdin(), console.getStdout(), console.getStderr());
     }
 
     @RBuiltin(name = ".fastr.channel.create", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX)
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRHelp.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRHelp.java
new file mode 100644
index 0000000000000000000000000000000000000000..f41e6f961cbf059792a7cd275b090bc3799e7c43
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRHelp.java
@@ -0,0 +1,68 @@
+/*
+ * 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 com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.dsl.Specialization;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import static com.oracle.truffle.r.runtime.RVisibility.ON;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RNull;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+@RBuiltin(name = ".fastr.interop.getHelpRd", visibility = ON, kind = PRIMITIVE, parameterNames = {"builtinName"}, behavior = COMPLEX)
+public abstract class FastRHelp extends RBuiltinNode.Arg1 {
+
+    static {
+        Casts casts = new Casts(FastRHelp.class);
+        casts.arg("builtinName").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+    }
+
+    @Specialization()
+    @TruffleBoundary
+    public Object isExternal(String builtinName) {
+        InputStream in = getClass().getResourceAsStream("/com/oracle/truffle/r/nodes/builtin/fastr/Rd/" + builtinName + ".Rd");
+        if (in != null) {
+            try (BufferedReader r = new BufferedReader(new InputStreamReader(in))) {
+                StringBuilder sb = new StringBuilder();
+                String line;
+                while ((line = r.readLine()) != null) {
+                    sb.append(line).append("\n");
+                }
+                return sb.toString();
+            } catch (IOException ex) {
+                RError.warning(this, RError.Message.GENERIC, "problems while reading " + builtinName + ".Rd", ex.getMessage());
+            }
+        }
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
index 4c2f44c65435784378c9ac91b3fb8e3f55df718b..11cbc9ac724d29fb42f9bf2cc27bff32a31d5ed2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRInterop.java
@@ -22,10 +22,15 @@
  */
 package com.oracle.truffle.r.nodes.builtin.fastr;
 
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notLogicalNA;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
 import static com.oracle.truffle.r.runtime.RVisibility.OFF;
 import static com.oracle.truffle.r.runtime.RVisibility.ON;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
@@ -33,6 +38,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Array;
+import java.net.MalformedURLException;
 
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerAsserts;
@@ -53,15 +60,9 @@ import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.Source.Builder;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.integerValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.typeName;
 import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -81,15 +82,18 @@ 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.RRaw;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
 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.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import java.lang.reflect.Array;
-import java.util.logging.Level;
-import java.util.logging.Logger;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.Foreign2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 
 public class FastRInterop {
 
@@ -99,24 +103,14 @@ public class FastRInterop {
         isTesting = true;
     }
 
-    @RBuiltin(name = ".fastr.interop.eval", visibility = OFF, kind = PRIMITIVE, parameterNames = {"mimeType", "source"}, behavior = COMPLEX)
-    public abstract static class Eval extends RBuiltinNode.Arg2 {
+    @RBuiltin(name = "eval.external", visibility = OFF, kind = PRIMITIVE, parameterNames = {"mimeType", "source", "path"}, behavior = COMPLEX)
+    public abstract static class Eval extends RBuiltinNode.Arg3 {
 
         static {
             Casts casts = new Casts(Eval.class);
-            casts.arg("mimeType").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
-            casts.arg("source").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
-        }
-
-        protected CallTarget parse(String mimeType, String source) {
-            CompilerAsserts.neverPartOfCompilation();
-
-            Source sourceObject = RSource.fromTextInternal(source, RSource.Internal.EVAL_WRAPPER, mimeType);
-            try {
-                return RContext.getInstance().getEnv().parse(sourceObject);
-            } catch (Throwable t) {
-                throw error(RError.Message.GENERIC, "Error while parsing: " + t.getMessage());
-            }
+            casts.arg("mimeType").allowMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+            casts.arg("source").allowMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+            casts.arg("path").allowMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
         }
 
         protected DirectCallNode createCall(String mimeType, String source) {
@@ -125,7 +119,7 @@ public class FastRInterop {
 
         @SuppressWarnings("unused")
         @Specialization(guards = {"cachedMimeType != null", "cachedMimeType.equals(mimeType)", "cachedSource != null", "cachedSource.equals(source)"})
-        protected Object evalCached(String mimeType, String source,
+        protected Object evalCached(String mimeType, String source, RMissing path,
                         @Cached("mimeType") String cachedMimeType,
                         @Cached("source") String cachedSource,
                         @Cached("createCall(mimeType, source)") DirectCallNode call) {
@@ -134,21 +128,46 @@ public class FastRInterop {
 
         @Specialization(replaces = "evalCached")
         @TruffleBoundary
-        protected Object eval(String mimeType, String source) {
+        protected Object eval(String mimeType, String source, @SuppressWarnings("unused") RMissing path) {
             return parse(mimeType, source).call();
         }
-    }
 
-    @RBuiltin(name = ".fastr.interop.evalFile", visibility = OFF, kind = PRIMITIVE, parameterNames = {"path", "mimeType"}, behavior = COMPLEX)
-    public abstract static class EvalFile extends RBuiltinNode.Arg2 {
+        @Specialization()
+        @TruffleBoundary
+        protected Object eval(@SuppressWarnings("unused") RMissing mimeType, @SuppressWarnings("unused") String source, @SuppressWarnings("unused") RMissing path) {
+            throw RError.error(this, RError.Message.INVALID_ARG, "mimeType");
+        }
 
-        static {
-            Casts casts = new Casts(EvalFile.class);
-            casts.arg("path").mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
-            casts.arg("mimeType").allowMissing().mustBe(stringValue()).asStringVector().mustBe(singleElement()).findFirst();
+        protected CallTarget parse(String mimeType, String source) {
+            CompilerAsserts.neverPartOfCompilation();
+
+            Source sourceObject = RSource.fromTextInternal(source, RSource.Internal.EVAL_WRAPPER, mimeType);
+            try {
+                return RContext.getInstance().getEnv().parse(sourceObject);
+            } catch (Throwable t) {
+                throw error(RError.Message.GENERIC, "Error while parsing: " + t.getMessage());
+            }
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object eval(String mimeType, @SuppressWarnings("unused") String source, String path) {
+            return parseFile(path, mimeType).call();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object eval(String mimeType, @SuppressWarnings("unused") RMissing source, String path) {
+            return parseFile(path, mimeType).call();
+        }
+
+        @Specialization
+        @TruffleBoundary
+        protected Object eval(@SuppressWarnings("unused") RMissing mimeType, @SuppressWarnings("unused") RMissing source, String path) {
+            return parseFile(path, null).call();
         }
 
-        protected CallTarget parse(String path, String mimeType) {
+        protected CallTarget parseFile(String path, String mimeType) {
             CompilerAsserts.neverPartOfCompilation();
 
             File file = new File(path);
@@ -168,18 +187,12 @@ public class FastRInterop {
 
         @Specialization
         @TruffleBoundary
-        protected Object eval(String path, @SuppressWarnings("unused") RMissing missing) {
-            return parse(path, null).call();
-        }
-
-        @Specialization
-        @TruffleBoundary
-        protected Object eval(String path, String mimeType) {
-            return parse(path, mimeType).call();
+        protected Object eval(@SuppressWarnings("unused") RMissing source, @SuppressWarnings("unused") RMissing mimeType, @SuppressWarnings("unused") RMissing path) {
+            throw RError.error(this, RError.Message.INVALID_ARG, "'source' or 'path'");
         }
     }
 
-    @RBuiltin(name = ".fastr.interop.export", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "value"}, behavior = COMPLEX)
+    @RBuiltin(name = "export", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "value"}, behavior = COMPLEX)
     public abstract static class Export extends RBuiltinNode.Arg2 {
 
         static {
@@ -190,28 +203,26 @@ public class FastRInterop {
 
         @Specialization(guards = "!isRMissing(value)")
         @TruffleBoundary
-        protected Object exportSymbol(String name, RTypedValue value) {
+        protected Object exportSymbol(String name, TruffleObject value) {
             if (name == null) {
                 throw error(RError.Message.INVALID_ARGUMENT, "name");
             }
-            RContext.getInstance().getExportedSymbols().put(name, value);
+            RContext.getInstance().getEnv().exportSymbol(name, value);
             return RNull.instance;
         }
 
         @Specialization
-        @TruffleBoundary
         protected Object exportSymbol(@SuppressWarnings("unused") String name, @SuppressWarnings("unused") RMissing value) {
             throw error(RError.Message.ARGUMENT_MISSING, "value");
         }
 
         @Fallback
-        @TruffleBoundary
         protected Object exportSymbol(@SuppressWarnings("unused") Object name, @SuppressWarnings("unused") Object value) {
             throw error(RError.Message.GENERIC, "only R language objects can be exported");
         }
     }
 
-    @RBuiltin(name = ".fastr.interop.import", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX)
+    @RBuiltin(name = "import", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name"}, behavior = COMPLEX)
     public abstract static class Import extends RBuiltinNode.Arg1 {
 
         static {
@@ -230,22 +241,7 @@ public class FastRInterop {
         }
     }
 
-    @RBuiltin(name = ".fastr.interop.hasSize", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
-    public abstract static class HasSize extends RBuiltinNode.Arg1 {
-
-        @Child private Node node = Message.HAS_SIZE.createNode();
-
-        static {
-            Casts.noCasts(HasSize.class);
-        }
-
-        @Specialization
-        public byte hasSize(TruffleObject obj) {
-            return RRuntime.asLogical(ForeignAccess.sendHasSize(node, obj));
-        }
-    }
-
-    @RBuiltin(name = ".fastr.interop.isNull", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    @RBuiltin(name = "is.external.null", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class IsNull extends RBuiltinNode.Arg1 {
 
         @Child private Node node = Message.IS_NULL.createNode();
@@ -258,9 +254,14 @@ public class FastRInterop {
         public byte isNull(TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendIsNull(node, obj));
         }
+
+        @Fallback
+        public byte isNull(@SuppressWarnings("unused") Object obj) {
+            return RRuntime.asLogical(false);
+        }
     }
 
-    @RBuiltin(name = ".fastr.interop.isExecutable", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    @RBuiltin(name = "is.external.executable", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class IsExecutable extends RBuiltinNode.Arg1 {
 
         @Child private Node node = Message.IS_EXECUTABLE.createNode();
@@ -273,13 +274,18 @@ public class FastRInterop {
         public byte isExecutable(TruffleObject obj) {
             return RRuntime.asLogical(ForeignAccess.sendIsExecutable(node, obj));
         }
+
+        @Fallback
+        public byte isExecutable(@SuppressWarnings("unused") Object obj) {
+            return RRuntime.asLogical(false);
+        }
     }
 
-    @RBuiltin(name = ".fastr.interop.toByte", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    @RBuiltin(name = "as.external.byte", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class ToByte extends RBuiltinNode.Arg1 {
 
         static {
-            castToJavaNumberType(new Casts(ToByte.class));
+            castToInteroptNumberType(new Casts(ToByte.class));
         }
 
         @Specialization
@@ -298,7 +304,7 @@ public class FastRInterop {
         }
     }
 
-    @RBuiltin(name = ".fastr.interop.toChar", visibility = ON, kind = PRIMITIVE, parameterNames = {"value", "pos"}, behavior = COMPLEX)
+    @RBuiltin(name = "as.external.char", visibility = ON, kind = PRIMITIVE, parameterNames = {"value", "pos"}, behavior = COMPLEX)
     public abstract static class ToChar extends RBuiltinNode.Arg2 {
 
         static {
@@ -323,11 +329,13 @@ public class FastRInterop {
             return toChar(value, 0);
         }
 
+        @SuppressWarnings("unused")
         @Specialization
         public RInteropChar toChar(int value, int pos) {
             throw RError.error(this, RError.Message.POS_NOT_ALLOWED_WITH_NUMERIC);
         }
 
+        @SuppressWarnings("unused")
         @Specialization
         public RInteropChar toChar(double value, int pos) {
             throw RError.error(this, RError.Message.POS_NOT_ALLOWED_WITH_NUMERIC);
@@ -339,16 +347,16 @@ public class FastRInterop {
         }
     }
 
-    @RBuiltin(name = ".fastr.interop.toFloat", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    @RBuiltin(name = "as.external.float", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class ToFloat extends RBuiltinNode.Arg1 {
 
         static {
-            castToJavaNumberType(new Casts(ToFloat.class));
+            castToInteroptNumberType(new Casts(ToFloat.class));
         }
 
         @Specialization
         public RInteropFloat toFloat(int value) {
-            return RInteropFloat.valueOf((float) value);
+            return RInteropFloat.valueOf(value);
         }
 
         @Specialization
@@ -362,16 +370,16 @@ public class FastRInterop {
         }
     }
 
-    @RBuiltin(name = ".fastr.interop.toLong", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    @RBuiltin(name = "as.external.long", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class ToLong extends RBuiltinNode.Arg1 {
 
         static {
-            castToJavaNumberType(new Casts(ToLong.class));
+            castToInteroptNumberType(new Casts(ToLong.class));
         }
 
         @Specialization
         public RInteropLong toLong(int value) {
-            return RInteropLong.valueOf((long) value);
+            return RInteropLong.valueOf(value);
         }
 
         @Specialization
@@ -385,11 +393,11 @@ public class FastRInterop {
         }
     }
 
-    @RBuiltin(name = ".fastr.interop.toShort", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
+    @RBuiltin(name = "as.external.short", visibility = ON, kind = PRIMITIVE, parameterNames = {"value"}, behavior = COMPLEX)
     public abstract static class ToShort extends RBuiltinNode.Arg1 {
 
         static {
-            castToJavaNumberType(new Casts(ToShort.class));
+            castToInteroptNumberType(new Casts(ToShort.class));
         }
 
         @Specialization
@@ -406,10 +414,9 @@ public class FastRInterop {
         public RInteropShort toShort(RRaw value) {
             return RInteropShort.valueOf(value.getValue());
         }
-
     }
 
-    private static void castToJavaNumberType(Casts casts) {
+    private static void castToInteroptNumberType(Casts casts) {
         casts.arg("value").mustBe(integerValue().or(doubleValue().or(rawValue())), RError.Message.INVALID_ARGUMENT_OF_TYPE, "value", Predef.typeName()).asVector().mustBe(singleElement()).findFirst();
     }
 
@@ -427,7 +434,7 @@ public class FastRInterop {
         }
     }
 
-    @RBuiltin(name = ".fastr.java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "silent"}, behavior = COMPLEX)
+    @RBuiltin(name = "new.java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "silent"}, behavior = COMPLEX)
     public abstract static class JavaClass extends RBuiltinNode.Arg2 {
 
         static {
@@ -441,7 +448,7 @@ public class FastRInterop {
         @TruffleBoundary
         public TruffleObject javaClass(String clazz, boolean silent) {
             try {
-                return JavaInterop.asTruffleObject(Class.forName(clazz.replaceAll("/", ".")));
+                return JavaInterop.asTruffleObject(RContext.getInstance().loadClass(clazz.replaceAll("/", ".")));
             } catch (ClassNotFoundException | SecurityException | IllegalArgumentException e) {
                 if (silent) {
                     return RNull.instance;
@@ -451,59 +458,113 @@ public class FastRInterop {
         }
     }
 
+    @RBuiltin(name = "java.addToClasspath", visibility = OFF, kind = PRIMITIVE, parameterNames = {"value", "silent"}, behavior = COMPLEX)
+    public abstract static class JavaAddToClasspath extends RBuiltinNode.Arg2 {
+
+        static {
+            Casts casts = new Casts(JavaAddToClasspath.class);
+            casts.arg("value").mustBe(stringValue()).asStringVector();
+            casts.arg("silent").mapMissing(Predef.constant(RRuntime.LOGICAL_FALSE)).mustBe(logicalValue().or(Predef.nullValue())).asLogicalVector().mustBe(singleElement()).findFirst().mustBe(
+                            notLogicalNA()).map(Predef.toBoolean());
+        }
+
+        @Specialization
+        @TruffleBoundary
+        public TruffleObject addEntries(RAbstractStringVector value, boolean silent) {
+            try {
+                RContext ctx = RContext.getInstance();
+                String[] entriesArr = new String[value.getLength()];
+                for (int i = 0; i < value.getLength(); i++) {
+                    entriesArr[i] = value.getDataAt(i);
+                }
+                ctx.addInteropClasspathEntries(entriesArr);
+                return value;
+            } catch (MalformedURLException e) {
+                if (silent) {
+                    return RNull.instance;
+                }
+                throw error(RError.Message.GENERIC, "error while adding classpath entry: " + e.getMessage());
+            }
+        }
+    }
+
     @ImportStatic({RRuntime.class})
-    @RBuiltin(name = ".fastr.java.isArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
-    public abstract static class IsJavaArray extends RBuiltinNode.Arg1 {
+    @RBuiltin(name = "java.class", visibility = ON, kind = PRIMITIVE, parameterNames = {"class"}, behavior = COMPLEX)
+    public abstract static class JavaClassName extends RBuiltinNode.Arg1 {
 
         static {
-            Casts.noCasts(IsJavaArray.class);
+            Casts.noCasts(JavaClassName.class);
         }
 
-        private final ConditionProfile isJavaProfile = ConditionProfile.createBinaryProfile();
-        private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile();
+        @Specialization(guards = {"isJavaObject(obj)"})
+        @TruffleBoundary
+        public Object javaClassName(TruffleObject obj) {
+            Object o = JavaInterop.asJavaObject(Object.class, obj);
+            if (o == null) {
+                return RNull.instance;
+            }
+            return o.getClass().getName();
+        }
+
+        protected boolean isJavaObject(TruffleObject obj) {
+            return JavaInterop.isJavaObject(obj);
+        }
+
+        @Fallback
+        public String javaClassName(@SuppressWarnings("unused") Object obj) {
+            throw error(RError.Message.GENERIC, "unsupported type");
+        }
+    }
+
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = "is.external.array", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
+    public abstract static class IsForeignArray extends RBuiltinNode.Arg1 {
+
+        static {
+            Casts.noCasts(IsForeignArray.class);
+        }
 
         @Specialization(guards = {"isForeignObject(obj)"})
         @TruffleBoundary
-        public Object isArray(TruffleObject obj) {
-            // TODO does this return true only for java arrays, or also
-            // js arrays?
-            boolean result = isJavaProfile.profile(JavaInterop.isJavaObject(Object.class, obj)) && isArrayProfile.profile(JavaInterop.isArray(obj));
-            return RRuntime.java2R(result);
+        public byte isArray(TruffleObject obj,
+                        @Cached("HAS_SIZE.createNode()") Node hasSize) {
+            return RRuntime.asLogical(ForeignAccess.sendHasSize(hasSize, obj));
         }
 
         @Fallback
-        public Object isArray(Object obj) {
-            return RRuntime.java2R(false);
+        public byte isArray(@SuppressWarnings("unused") Object obj) {
+            return RRuntime.LOGICAL_FALSE;
         }
     }
 
-    @RBuiltin(name = ".fastr.java.newArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "dim"}, behavior = COMPLEX)
+    @RBuiltin(name = "new.java.array", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "dim"}, behavior = COMPLEX)
     public abstract static class NewJavaArray extends RBuiltinNode.Arg2 {
 
         static {
             Casts casts = new Casts(NewJavaArray.class);
             casts.arg("class").mustBe(stringValue()).asStringVector().mustBe(Predef.singleElement()).findFirst();
-            casts.arg("dim").mustBe(integerValue(), RError.Message.INVALID_ARGUMENT_OF_TYPE, "dim", typeName()).asIntegerVector();
+            casts.arg("dim").mustBe(integerValue().or(doubleValue()), RError.Message.INVALID_ARGUMENT_OF_TYPE, "dim", typeName()).asIntegerVector();
         }
 
         @Specialization
         @TruffleBoundary
         public Object newArray(String clazz, int length) {
-            try {
-                // TODO new via ForeignAccess
-                return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), length));
-            } catch (ClassNotFoundException e) {
-                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
-            }
+            return JavaInterop.asTruffleObject(Array.newInstance(getClazz(clazz), length));
         }
 
         @Specialization
         @TruffleBoundary
         public Object newArray(String clazz, RAbstractIntVector dim) {
+            int[] dima = new int[dim.getLength()];
+            for (int i = 0; i < dima.length; i++) {
+                dima[i] = dim.getDataAt(i);
+            }
+            return JavaInterop.asTruffleObject(Array.newInstance(getClazz(clazz), dima));
+        }
+
+        private Class<?> getClazz(String className) throws RError {
             try {
-                int[] dima = new int[dim.getLength()];
-                // TODO new via ForeignAccess
-                return JavaInterop.asTruffleObject(Array.newInstance(Class.forName(clazz), dima));
+                return classForName(className);
             } catch (ClassNotFoundException e) {
                 throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
             }
@@ -511,7 +572,7 @@ public class FastRInterop {
     }
 
     @ImportStatic({Message.class, RRuntime.class})
-    @RBuiltin(name = ".fastr.java.toArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"x", "className", "flat"}, behavior = COMPLEX)
+    @RBuiltin(name = "as.java.array", visibility = ON, kind = PRIMITIVE, parameterNames = {"x", "className", "flat"}, behavior = COMPLEX)
     public abstract static class ToJavaArray extends RBuiltinNode.Arg3 {
 
         static {
@@ -524,20 +585,23 @@ public class FastRInterop {
 
         @Specialization
         @TruffleBoundary
-        public Object toArray(RAbstractLogicalVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
-            return toArray(vec, flat, boolean.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        public Object toArray(RAbstractLogicalVector vec, @SuppressWarnings("unused") RMissing className, boolean flat,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign) {
+            return toArray(vec, flat, boolean.class, (array, i) -> Array.set(array, i, r2Foreign.execute(vec.getDataAt(i))));
         }
 
         @Specialization
         @TruffleBoundary
-        public Object toArray(RAbstractLogicalVector vec, String className, boolean flat) {
-            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        public Object toArray(RAbstractLogicalVector vec, String className, boolean flat,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, r2Foreign.execute(vec.getDataAt(i))));
         }
 
         @Specialization
         @TruffleBoundary
-        public Object toArray(RAbstractIntVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
-            return toArray(vec, flat, int.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAt(i))));
+        public Object toArray(RAbstractIntVector vec, @SuppressWarnings("unused") RMissing className, boolean flat,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign) {
+            return toArray(vec, flat, int.class, (array, i) -> Array.set(array, i, r2Foreign.execute(vec.getDataAt(i))));
         }
 
         @Specialization
@@ -572,63 +636,51 @@ public class FastRInterop {
 
         @Specialization
         @TruffleBoundary
-        public Object toArray(RAbstractVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
-            return toArray(vec, flat, Object.class, (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAtAsObject(i))));
+        public Object toArray(RAbstractRawVector vec, @SuppressWarnings("unused") RMissing className, boolean flat) {
+            return toArray(vec, flat, byte.class, (array, i) -> Array.set(array, i, vec.getDataAt(i).getValue()));
         }
 
         @Specialization
         @TruffleBoundary
-        public Object toArray(RAbstractVector vec, String className, boolean flat) {
-            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(vec.getDataAtAsObject(i))));
+        public Object toArray(RAbstractRawVector vec, String className, boolean flat) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, vec.getDataAt(i).getValue()));
+        }
+
+        @Specialization(guards = "!isJavaLikeVector(vec)")
+        @TruffleBoundary
+        public Object toArray(RAbstractVector vec, @SuppressWarnings("unused") RMissing className, boolean flat,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign) {
+            return toArray(vec, flat, Object.class, (array, i) -> Array.set(array, i, r2Foreign.execute(vec.getDataAtAsObject(i))));
+        }
+
+        @Specialization(guards = "!isJavaLikeVector(vec)")
+        @TruffleBoundary
+        public Object toArray(RAbstractVector vec, String className, boolean flat,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign) {
+            return toArray(vec, flat, getClazz(className), (array, i) -> Array.set(array, i, r2Foreign.execute(vec.getDataAtAsObject(i))));
         }
 
         @Specialization
         @TruffleBoundary
-        public Object toArray(RInteropScalar ri, String className, boolean flat) {
+        public Object toArray(RInteropScalar ri, String className, boolean flat,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign) {
             RList list = RDataFactory.createList(new Object[]{ri});
-            return toArray(list, flat, getClazz(className), (array, i) -> Array.set(array, i, RRuntime.r2Java(list.getDataAt(i))));
+            return toArray(list, flat, getClazz(className), (array, i) -> Array.set(array, i, r2Foreign.execute(list.getDataAt(i))));
         }
 
         @Specialization
         @TruffleBoundary
-        public Object toArray(RInteropScalar ri, RMissing className, boolean flat) {
+        public Object toArray(RInteropScalar ri, @SuppressWarnings("unused") RMissing className, boolean flat,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign) {
             RList list = RDataFactory.createList(new Object[]{ri});
-            return toArray(list, flat, ri.getJavaType(), (array, i) -> Array.set(array, i, RRuntime.r2Java(list.getDataAt(i))));
+            return toArray(list, flat, ri.getJavaType(), (array, i) -> Array.set(array, i, r2Foreign.execute(list.getDataAt(i))));
         }
 
-        private Class<?> getClazz(String className) throws RError {
-            if (className.equals(Byte.TYPE.getName())) {
-                return Byte.TYPE;
-            }
-            if (className.equals(Boolean.TYPE.getName())) {
-                return Boolean.TYPE;
-            }
-            if (className.equals(Character.TYPE.getName())) {
-                return Character.TYPE;
-            }
-            if (className.equals(Double.TYPE.getName())) {
-                return Double.TYPE;
-            }
-            if (className.equals(Float.TYPE.getName())) {
-                return Float.TYPE;
-            }
-            if (className.equals(Integer.TYPE.getName())) {
-                return Integer.TYPE;
-            }
-            if (className.equals(Long.TYPE.getName())) {
-                return Long.TYPE;
-            }
-            if (className.equals(Short.TYPE.getName())) {
-                return Short.TYPE;
-            }
-            try {
-                return Class.forName(className);
-            } catch (ClassNotFoundException e) {
-                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
-            }
+        protected R2Foreign createR2Foreign() {
+            return R2ForeignNodeGen.create();
         }
 
-        private int[] getDim(boolean flat, RAbstractVector vec) {
+        private static int[] getDim(boolean flat, RAbstractVector vec) {
             int[] dims;
             if (flat) {
                 dims = new int[]{vec.getLength()};
@@ -641,7 +693,7 @@ public class FastRInterop {
             return dims;
         }
 
-        private Object toArray(RAbstractVector vec, boolean flat, Class<?> clazz, VecElementToArray vecToArray) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
+        private static Object toArray(RAbstractVector vec, boolean flat, Class<?> clazz, VecElementToArray vecToArray) throws IllegalArgumentException, ArrayIndexOutOfBoundsException {
             int[] dims = getDim(flat, vec);
             final Object array = Array.newInstance(clazz, dims);
             for (int d = 0; d < dims.length; d++) {
@@ -658,138 +710,90 @@ public class FastRInterop {
             void toArray(Object array, Integer i);
         }
 
-        @Specialization
+        @Specialization(guards = "isJavaObject(obj)")
         @TruffleBoundary
         public Object toArray(TruffleObject obj, @SuppressWarnings("unused") RMissing missing, @SuppressWarnings("unused") boolean flat,
                         @Cached("WRITE.createNode()") Node write) {
-            if (JavaInterop.isJavaObject(Object.class, obj)) {
-                if (JavaInterop.isArray(obj)) {
-                    // TODO should return copy?
+
+            if (JavaInterop.isArray(obj)) {
+                // TODO should return copy?
+                return obj;
+            }
+            try {
+                Object o = JavaInterop.asJavaObject(Object.class, obj);
+                if (o == null) {
                     return obj;
                 }
-                try {
-                    // TODO should create array with the same component type as the JavaObject
-                    TruffleObject array = JavaInterop.asTruffleObject(Array.newInstance(Object.class, 1));
-                    ForeignAccess.sendWrite(write, array, 0, obj);
-                    return array;
-                } catch (UnsupportedMessageException | UnknownIdentifierException e) {
-                    throw error(RError.Message.GENERIC, "error while creating array: " + e.getMessage());
-                } catch (UnsupportedTypeException ex) {
-                    Logger.getLogger(FastRInterop.class.getName()).log(Level.SEVERE, null, ex);
-                }
+                TruffleObject array = JavaInterop.asTruffleObject(Array.newInstance(o.getClass(), 1));
+                ForeignAccess.sendWrite(write, array, 0, obj);
+                return array;
+            } catch (UnsupportedTypeException | UnsupportedMessageException | UnknownIdentifierException e) {
+                throw error(RError.Message.GENERIC, "error while creating array: " + e.getMessage());
             }
-            throw error(RError.Message.GENERIC, "can't create array from " + obj);
         }
 
+        @SuppressWarnings("unused")
         @Fallback
-        public Object toArray(Object o, @SuppressWarnings("unused") Object className, @SuppressWarnings("unused") Object flat) {
+        public Object toArray(Object o, Object className, Object flat) {
             throw error(RError.Message.GENERIC, "unsupported type");
         }
 
+        private Class<?> getClazz(String className) throws RError {
+            try {
+                return classForName(className);
+            } catch (ClassNotFoundException e) {
+                throw error(RError.Message.GENERIC, "error while accessing Java class: " + e.getMessage());
+            }
+        }
+
+        protected boolean isJavaObject(TruffleObject obj) {
+            return JavaInterop.isJavaObject(obj);
+        }
+
+        protected boolean isJavaLikeVector(RAbstractVector vec) {
+            return vec instanceof RAbstractLogicalVector ||
+                            vec instanceof RAbstractIntVector ||
+                            vec instanceof RAbstractDoubleVector ||
+                            vec instanceof RAbstractStringVector ||
+                            vec instanceof RAbstractRawVector;
+        }
     }
 
-    @RBuiltin(name = ".fastr.java.fromArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"array"}, behavior = COMPLEX)
-    public abstract static class FromJavaArray extends RBuiltinNode.Arg1 {
-        @Child Node getSize = Message.GET_SIZE.createNode();
-        @Child Node read;
-        @Child Node isNull;
-        @Child Node isBoxed;
-        @Child Node unbox;
+    @ImportStatic({Message.class, RRuntime.class})
+    @RBuiltin(name = ".fastr.interop.fromArray", visibility = ON, kind = PRIMITIVE, parameterNames = {"array"}, behavior = COMPLEX)
+    public abstract static class FromForeignArray extends RBuiltinNode.Arg1 {
+
         static {
-            Casts casts = new Casts(FromJavaArray.class);
-            casts.arg("array").mustNotBeMissing();
+            Casts casts = new Casts(FromForeignArray.class);
+            casts.arg("array").castForeignObjects(false).mustNotBeMissing();
         }
 
-        protected boolean isJavaArray(TruffleObject obj) {
-            return JavaInterop.isJavaObject(Object.class, obj) && JavaInterop.isArray(obj);
+        private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile();
+
+        protected ForeignArray2R createForeignArray2R() {
+            return ForeignArray2RNodeGen.create();
         }
 
-        @Specialization(guards = {"isJavaArray(obj)"})
+        @Specialization(guards = {"isForeignObject(obj)"})
         @TruffleBoundary
-        public Object fromArray(TruffleObject obj) {
-            int size;
-            try {
-                size = (int) ForeignAccess.sendGetSize(getSize, obj);
-                if (size == 0) {
-                    return RDataFactory.createList();
-                }
-                Object[] elements = new Object[size];
-                boolean allBoolean = true;
-                boolean allInteger = true;
-                boolean allDouble = true;
-                boolean allString = true;
-                for (int i = 0; i < size; i++) {
-                    if (read == null) {
-                        read = insert(Message.READ.createNode());
-                    }
-                    Object element = ForeignAccess.sendRead(read, obj, i);
-                    if (element instanceof TruffleObject) {
-                        if (isNull == null) {
-                            isNull = insert(Message.IS_NULL.createNode());
-                        }
-                        if (ForeignAccess.sendIsNull(isNull, (TruffleObject) element)) {
-                            element = null;
-                        } else {
-                            if (isBoxed == null) {
-                                isBoxed = insert(Message.IS_BOXED.createNode());
-                            }
-                            if (ForeignAccess.sendIsBoxed(isBoxed, (TruffleObject) element)) {
-                                if (unbox == null) {
-                                    unbox = insert(Message.UNBOX.createNode());
-                                }
-                                element = ForeignAccess.sendIsBoxed(unbox, (TruffleObject) element);
-                            }
-                        }
-                    }
-                    allBoolean &= element instanceof Boolean;
-                    allInteger &= element instanceof Byte || element instanceof Integer || element instanceof Short;
-                    allDouble &= element instanceof Double || element instanceof Float || element instanceof Long;
-                    allString &= element instanceof Character || element instanceof String;
-
-                    elements[i] = RRuntime.java2R(element);
-                }
-                if (allBoolean) {
-                    byte[] ret = new byte[size];
-                    for (int i = 0; i < size; i++) {
-                        ret[i] = ((Number) elements[i]).byteValue();
-                    }
-                    return RDataFactory.createLogicalVector(ret, true);
-                }
-                if (allInteger) {
-                    int[] ret = new int[size];
-                    for (int i = 0; i < size; i++) {
-                        ret[i] = ((Number) elements[i]).intValue();
-                    }
-                    return RDataFactory.createIntVector(ret, true);
-                }
-                if (allDouble) {
-                    double[] ret = new double[size];
-                    for (int i = 0; i < size; i++) {
-                        ret[i] = ((Number) elements[i]).doubleValue();
-                    }
-                    return RDataFactory.createDoubleVector(ret, true);
-                }
-                if (allString) {
-                    String[] ret = new String[size];
-                    for (int i = 0; i < size; i++) {
-                        ret[i] = String.valueOf(elements[i]);
-                    }
-                    return RDataFactory.createStringVector(ret, true);
-                }
-                return RDataFactory.createList(elements);
-            } catch (UnsupportedMessageException | UnknownIdentifierException e) {
-                throw error(RError.Message.GENERIC, "error while converting array: " + e.getMessage());
+        public Object fromArray(TruffleObject obj,
+                        @Cached("HAS_SIZE.createNode()") Node hasSize,
+                        @Cached("createForeignArray2R()") ForeignArray2R array2R) {
+            if (isArrayProfile.profile(ForeignAccess.sendHasSize(hasSize, obj))) {
+                return array2R.execute(obj, true);
+            } else {
+                throw error(RError.Message.GENERIC, "not a java array");
             }
         }
 
         @Fallback
-        public Object fromArray(@SuppressWarnings("unused") Object obj) {
+        public Object fromObject(@SuppressWarnings("unused") Object obj) {
             throw error(RError.Message.GENERIC, "not a java array");
         }
     }
 
     @ImportStatic({Message.class, RRuntime.class})
-    @RBuiltin(name = ".fastr.interop.new", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
+    @RBuiltin(name = "new.external", visibility = ON, kind = PRIMITIVE, parameterNames = {"class", "..."}, behavior = COMPLEX)
     public abstract static class InteropNew extends RBuiltinNode.Arg2 {
 
         static {
@@ -800,14 +804,16 @@ public class FastRInterop {
         @TruffleBoundary
         public Object interopNew(TruffleObject clazz, RArgsValuesAndNames args,
                         @SuppressWarnings("unused") @Cached("args.getLength()") int length,
-                        @Cached("createNew(length).createNode()") Node sendNew) {
+                        @Cached("createNew(length).createNode()") Node sendNew,
+                        @Cached("createR2Foreign()") R2Foreign r2Foreign,
+                        @Cached("createForeign2R()") Foreign2R foreign2R) {
             try {
                 Object[] argValues = new Object[args.getLength()];
                 for (int i = 0; i < argValues.length; i++) {
-                    argValues[i] = RRuntime.r2Java(args.getArgument(i));
+                    argValues[i] = r2Foreign.execute(args.getArgument(i));
                 }
                 Object result = ForeignAccess.sendNew(sendNew, clazz, argValues);
-                return RRuntime.java2R(result);
+                return foreign2R.execute(result);
             } catch (IllegalStateException | SecurityException | IllegalArgumentException | UnsupportedTypeException | ArityException | UnsupportedMessageException e) {
                 String msg = isTesting ? "error during Java object instantiation" : "error during Java object instantiation: " + e.getMessage();
                 throw error(RError.Message.GENERIC, msg);
@@ -818,10 +824,18 @@ public class FastRInterop {
         public Object interopNew(@SuppressWarnings("unused") Object clazz, @SuppressWarnings("unused") Object args) {
             throw error(RError.Message.GENERIC, "interop object needed as receiver of NEW message");
         }
+
+        protected R2Foreign createR2Foreign() {
+            return R2ForeignNodeGen.create();
+        }
+
+        protected Foreign2R createForeign2R() {
+            return Foreign2RNodeGen.create();
+        }
     }
 
     @ImportStatic(RRuntime.class)
-    @RBuiltin(name = ".fastr.interop.isExternal", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
+    @RBuiltin(name = "is.external", visibility = ON, kind = PRIMITIVE, parameterNames = {"obj"}, behavior = COMPLEX)
     public abstract static class IsExternal extends RBuiltinNode.Arg1 {
 
         static {
@@ -829,13 +843,41 @@ public class FastRInterop {
         }
 
         @Specialization(guards = {"isForeignObject(obj)"})
-        public byte isExternal(TruffleObject obj) {
+        public byte isExternal(@SuppressWarnings("unused") TruffleObject obj) {
             return RRuntime.LOGICAL_TRUE;
         }
 
         @Fallback
-        public byte isExternal(Object obj) {
+        public byte isExternal(@SuppressWarnings("unused") Object obj) {
             return RRuntime.LOGICAL_FALSE;
         }
     }
+
+    private static Class<?> classForName(String className) throws ClassNotFoundException {
+        if (className.equals(Byte.TYPE.getName())) {
+            return Byte.TYPE;
+        }
+        if (className.equals(Boolean.TYPE.getName())) {
+            return Boolean.TYPE;
+        }
+        if (className.equals(Character.TYPE.getName())) {
+            return Character.TYPE;
+        }
+        if (className.equals(Double.TYPE.getName())) {
+            return Double.TYPE;
+        }
+        if (className.equals(Float.TYPE.getName())) {
+            return Float.TYPE;
+        }
+        if (className.equals(Integer.TYPE.getName())) {
+            return Integer.TYPE;
+        }
+        if (className.equals(Long.TYPE.getName())) {
+            return Long.TYPE;
+        }
+        if (className.equals(Short.TYPE.getName())) {
+            return Short.TYPE;
+        }
+        return Class.forName(className);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRLibPaths.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRLibPaths.java
new file mode 100644
index 0000000000000000000000000000000000000000..cd75720992f31dd99db977b18ae9fc97205dd401
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRLibPaths.java
@@ -0,0 +1,63 @@
+/*
+ * 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.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.r.nodes.builtin.CastBuilder.Predef;
+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.context.RContext;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RMissing;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+
+/**
+ * Allows to show the actual location of the source section of a provided function.
+ */
+@RBuiltin(name = ".fastr.libPaths", visibility = ON, kind = PRIMITIVE, parameterNames = "new", behavior = RBehavior.MODIFIES_STATE)
+public abstract class FastRLibPaths extends RBuiltinNode.Arg1 {
+
+    static {
+        Casts casts = new Casts(FastRLibPaths.class);
+        casts.arg("new").allowMissing().mustBe(Predef.stringValue()).asStringVector();
+    }
+
+    @Specialization
+    public Object setLibPaths(RAbstractStringVector paths) {
+        RContext.getInstance().libraryPaths.clear();
+        for (int i = 0; i < paths.getLength(); i++) {
+            RContext.getInstance().libraryPaths.add(paths.getDataAt(i));
+        }
+        return paths;
+    }
+
+    @Specialization
+    public Object srcInfo(@SuppressWarnings("unused") RMissing path) {
+        String[] libPaths = RContext.getInstance().libraryPaths.toArray(new String[0]);
+        return RDataFactory.createStringVector(libPaths, true);
+    }
+}
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
index 5f9863bb15b9b99732b13ce28e22876aaab8e349..fd2d891411ccaa621e96578318781d76e32cebbb 100644
--- 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
@@ -26,6 +26,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.runtime.RVisibility.ON;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.Node;
@@ -59,7 +60,8 @@ public abstract class FastRSourceInfo extends RBuiltinNode.Arg1 {
         return srcInfo(fun.getRep());
     }
 
-    private Object srcInfo(Node fun) {
+    @TruffleBoundary
+    private static Object srcInfo(Node fun) {
         SourceSection ss = fun.getSourceSection();
         if (ss != null) {
             String path = ss.getSource().getPath();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
index b7179ade00d55bd5bad8fd8e03c96728bb9837a9..eb1009cec1c6f30031f743a6aa8049a0346a5668 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStackTrace.java
@@ -52,7 +52,7 @@ public abstract class FastRStackTrace extends RBuiltinNode.Arg1 {
     @TruffleBoundary
     @Specialization
     protected RNull printStackTrace(boolean printFrameContents) {
-        RContext.getInstance().getConsoleHandler().print(Utils.createStackTrace(printFrameContents));
+        RContext.getInstance().getConsole().print(Utils.createStackTrace(printFrameContents));
         return RNull.instance;
     }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
index 458fa6ebeff90250e215b59b64ec750d1755edde..e09fae33d35e17af9fa7cddbd887b530101b596e 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRStats.java
@@ -158,7 +158,7 @@ public class FastRStats {
     }
 
     @RBuiltin(name = ".fastr.stats.typecounts", visibility = OFF, kind = PRIMITIVE, parameterNames = {"filename", "append"}, behavior = COMPLEX)
-    public abstract static class FastRProfTypecounts extends RBuiltinNode.Arg2 implements RDataFactory.Listener {
+    public abstract static class FastRProfTypecounts extends RBuiltinNode.Arg2 {
         @Override
         public Object[] getDefaultParameterValues() {
             return new Object[]{"Rproftypecounts.out", RRuntime.LOGICAL_FALSE};
@@ -190,8 +190,7 @@ public class FastRStats {
                 try {
                     PrintStream out = new PrintStream(new FileOutputStream(filenameVec.getDataAt(0), append));
                     state.setOut(out);
-                    RDataFactory.addListener(this);
-                    RDataFactory.setTracingState(true);
+                    RDataFactory.addListener(LISTENER);
                 } catch (IOException ex) {
                     throw error(RError.Message.GENERIC, String.format("Rprofmem: cannot open profile file '%s'", filenameVec.getDataAt(0)));
                 }
@@ -202,36 +201,38 @@ public class FastRStats {
         protected void endProfiling() {
             State state = State.get();
             if (state.out() != null) {
-                RDataFactory.setTracingState(false);
+                RDataFactory.removeListener(LISTENER);
                 state.cleanup(0);
             }
         }
 
-        @Override
-        public void reportAllocation(RTypedValue data) {
-            Class<? extends RTypedValue> klass = data.getClass();
-            boolean isVector = (data instanceof RAbstractVector);
-            State state = State.get();
-            Map<Class<? extends RTypedValue>, SortedMap<Integer, State.Counter>> typecountsMap = state.getTypecountsMap();
-            SortedMap<Integer, State.Counter> countsMap = typecountsMap.get(klass);
-            if (countsMap == null) {
-                countsMap = new TreeMap<>();
-                typecountsMap.put(klass, countsMap);
-            }
-            int length;
-            if (isVector) {
-                RAbstractVector vector = (RAbstractVector) data;
-                length = vector.getLength();
-            } else {
-                length = 1;
-            }
-            State.Counter count = countsMap.get(length);
-            if (count == null) {
-                count = new State.Counter();
-                countsMap.put(length, count);
+        private static final RDataFactory.Listener LISTENER = new RDataFactory.Listener() {
+            @Override
+            public void reportAllocation(RTypedValue data) {
+                Class<? extends RTypedValue> klass = data.getClass();
+                boolean isVector = (data instanceof RAbstractVector);
+                State state = State.get();
+                Map<Class<? extends RTypedValue>, SortedMap<Integer, State.Counter>> typecountsMap = state.getTypecountsMap();
+                SortedMap<Integer, State.Counter> countsMap = typecountsMap.get(klass);
+                if (countsMap == null) {
+                    countsMap = new TreeMap<>();
+                    typecountsMap.put(klass, countsMap);
+                }
+                int length;
+                if (isVector) {
+                    RAbstractVector vector = (RAbstractVector) data;
+                    length = vector.getLength();
+                } else {
+                    length = 1;
+                }
+                State.Counter count = countsMap.get(length);
+                if (count == null) {
+                    count = new State.Counter();
+                    countsMap.put(length, count);
+                }
+                count.incCount();
             }
-            count.incCount();
-        }
+        };
 
         private static class State extends RprofState {
             public static class Counter {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
index 47f7e66ea42b3325d297d573edf5171ddbeff747..c5f6be6387c73d8e5482e3939a400905e4d9743f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
  */
 @RBuiltin(name = ".fastr.dqrls", visibility = OFF, kind = PRIMITIVE, parameterNames = {"x", "n", "p", "y", "ny", "tol", "coeff"}, behavior = PURE)
 public abstract class FastrDqrls extends RBuiltinNode.Arg7 {
-    @Child private RApplRFFI.DqrlsNode dqrlsNode = RFFIFactory.getRFFI().getRApplRFFI().createDqrlsNode();
+    @Child private RApplRFFI.DqrlsNode dqrlsNode = RFFIFactory.getRApplRFFI().createDqrlsNode();
 
     private static final String[] NAMES = new String[]{"qr", "coefficients", "residuals", "effects", "rank", "pivot", "qraux", "tol", "pivoted"};
     private static RStringVector namesVector = null;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.byte.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.byte.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..5411a6b93d1f9809becca8d3a5ce784bbd4a894f
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.byte.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{as.external.byte}
+\alias{as.external.byte}
+\title{Marks a R value to be converted to byte when passed over to a foreign language.}
+\usage{
+as.external.byte(value)
+}
+\arguments{
+\item{value}{a R value which can be converted to byte}
+}
+\value{
+An interop byte value. Error in case the given value can't be converted to a byte.
+}
+\description{
+Marks a R value to be converted to byte when passed over to a foreign language.
+}
+\examples{
+as.external.byte(123)
+}
+\seealso{
+\code{\link{as.external.char}}, \code{\link{as.external.float}}, \code{\link{as.external.long}}, \code{\link{as.external.short}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.char.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.char.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..589ff22fb5756d1ad62cfe9a13598e9868f54587
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.char.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{as.external.char}
+\alias{as.external.char}
+\title{Marks a R value to be converted to char when passed over to a foreign language.}
+\usage{
+as.external.char(value)
+}
+\arguments{
+\item{value}{a R value which can be converted to char}
+}
+\value{
+An interop char value. Error in case the given value can't be converted to a char.
+}
+\description{
+Marks a R value to be converted to char when passed over to a foreign language.
+}
+\examples{
+as.external.char('a')
+}
+\seealso{
+\code{\link{as.external.byte}}, \code{\link{as.external.float}}, \code{\link{as.external.long}}, \code{\link{as.external.short}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.float.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.float.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..10d7248d16a2713f82150b99c9ed45c5800ea8a8
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.float.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{as.external.float}
+\alias{as.external.float}
+\title{Marks a R value to be converted to float when passed over to a foreign language.}
+\usage{
+as.external.float(value)
+}
+\arguments{
+\item{value}{a R value which can be converted to float}
+}
+\value{
+An interop float value. Error in case the given value can't be converted to a float.
+}
+\description{
+Marks a R value to be converted to float when passed over to a foreign language.
+}
+\examples{
+as.external.float(1.1)
+}
+\seealso{
+\code{\link{as.external.byte}}, \code{\link{as.external.char}}, \code{\link{as.external.long}}, \code{\link{as.external.short}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.long.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.long.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..600f2746f3a7d84908cec829fe6b566e92362707
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.long.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{as.external.long}
+\alias{as.external.long}
+\title{Marks a R value to be converted to long when passed over to a foreign language.}
+\usage{
+as.external.long(value)
+}
+\arguments{
+\item{value}{a R value which can be converted to long}
+}
+\value{
+An interop long value. Error in case the given value can't be converted to a long.
+}
+\description{
+Marks a R value to be converted to long when passed over to a foreign language.
+}
+\examples{
+as.external.long(123)
+}
+\seealso{
+\code{\link{as.external.byte}}, \code{\link{as.external.char}}, \code{\link{as.external.float}}, \code{\link{as.external.short}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.short.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.short.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..fd96b53ac77c43169ae7ef39d5a41412aa511353
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.external.short.Rd
@@ -0,0 +1,23 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{as.external.short}
+\alias{as.external.short}
+\title{Marks a R value to be converted to short when passed over to a foreign language.}
+\usage{
+as.external.short(value)
+}
+\arguments{
+\item{value}{a R value which can be converted to short}
+}
+\value{
+An interop short value. Error in case the given value can't be converted to a short.
+}
+\description{
+Marks a R value to be converted to short when passed over to a foreign language.
+}
+\examples{
+as.external.short(123)
+}
+\seealso{
+\code{\link{as.external.byte}}, \code{\link{as.external.char}}, \code{\link{as.external.short}}, \code{\link{as.external.long}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.java.array.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.java.array.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..0b6f195c8d6ed2e08070697d570c9e1a2d8744e2
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/as.java.array.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{as.java.array}
+\alias{as.java.array}
+\title{Converts a R vector or list to a java array.}
+\usage{
+as.java.array(x, className)
+}
+\arguments{
+\item{x}{a vector or list}
+
+\item{className}{Optional. Determines the java array component type.}
+}
+\value{
+An external object representing a java array. Error in case the array could not be created.
+}
+\description{
+Converts a R vector or list to a java array.
+}
+\examples{
+as.java.array(c(1, 2, 3), 'java.lang.Double')
+}
+\seealso{
+\code{\link{new.java.array}}, \code{\link{is.external.array}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..3912ef157cb6b5af02d16b2d52eae2b667e2fc20
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{is.external}
+\alias{is.external}
+\title{Determines whether the given object is an external object or not.}
+\usage{
+is.external(obj)
+}
+\arguments{
+\item{obj}{an external object}
+}
+\value{
+TRUE in case the given value is executable, otherwise FALSE.
+}
+\description{
+Determines whether the given object is an external object or not.
+}
+\examples{
+javaClass <- new.java.class('java.util.ArrayList')
+is.external(javaClass)
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.array.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.array.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..ddd27ee8ec3bdd962b9f77e10d9d08d3d9974618
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.array.Rd
@@ -0,0 +1,26 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{is.external.array}
+\alias{is.external.array}
+\title{Determines whether the given external object has a size. If an external object has a size, it is expected it represents an array-like structure.
+Note that even if an e.g. java ArrayList has a "size", the returned value still would be false, because it will be recognised as an array-like structure.}
+\usage{
+is.external.array(obj)
+}
+\arguments{
+\item{obj}{an external object}
+}
+\value{
+TRUE in case the given value is an array-like structure, otherwise FALSE.
+}
+\description{
+Determines whether the given external object has a size. If an external object has a size, it is expected it represents an array-like structure.
+Note that even if an e.g. java ArrayList has a "size", the returned value still would be false, because it will be recognised as an array-like structure.
+}
+\examples{
+javaClass <- new.java.class('java.util.ArrayList')
+is.external.array(javaClass)
+}
+\seealso{
+\code{\link{new.java.array}}, \code{\link{as.java.array}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.executable.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.executable.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..f1a066cd72df154e880c236ecb38ced1245f08c6
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.executable.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{is.external.executable}
+\alias{is.external.executable}
+\title{Determines whether the passed external object can be executed.}
+\usage{
+is.external.executable(value)
+}
+\arguments{
+\item{value}{an external object}
+}
+\value{
+TRUE in case the given value is executable, otherwise FALSE.
+}
+\description{
+Determines whether the passed external object can be executed.
+}
+\examples{
+javaClass <- new.java.class('java.util.Collections')
+is.external.executable(javaClass$addAll())
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.null.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.null.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..7bfbf3054ca46617b52166108346538ca907b7d6
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/is.external.null.Rd
@@ -0,0 +1,21 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{is.external.null}
+\alias{is.external.null}
+\title{Determines whether the given object (external object, or not) represents a Null value.}
+\usage{
+is.external.null(value)
+}
+\arguments{
+\item{value}{an external object}
+}
+\value{
+TRUE in case the given value is Null, otherwise FALSE.
+}
+\description{
+Determines whether the given object (external object, or not) represents a Null value.
+}
+\examples{
+javaClass <- new.java.class('java.util.Collections')
+is.external.null(javaClass)
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/java.addToClasspath.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/java.addToClasspath.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..71bbd9225971a399b6d82e9b14a40aa7292dac24
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/java.addToClasspath.Rd
@@ -0,0 +1,22 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{java.addToClasspath}
+\alias{java.addToClasspath}
+\title{Adds a class path entry to the class path.}
+\usage{
+java.addToClasspath(value, silent = FALSE)
+}
+\arguments{
+\item{value}{character vector. The class path entry or entries to be added to the FastR interop class path.}
+
+\item{silent}{logical, default FALSE. Determines whether errors should be reported or not.}
+}
+\description{
+Adds a class path entry to the class path.
+}
+\examples{
+java.addClasspathEntry('/foo/bar.jar')
+}
+\seealso{
+\code{\link{new.java.class}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/java.class.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/java.class.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..cc69669f516f6e00d66ab3d82006141d39a9387a
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/java.class.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{java.class}
+\alias{java.class}
+\title{Returns the fully qualified class name for the given external object representing a java class.}
+\usage{
+java.class(class)
+}
+\arguments{
+\item{class}{an external object representing a java class.}
+}
+\value{
+fully qualified class name if the given value is an external object representing a java class.
+}
+\description{
+Returns the fully qualified class name for the given external object representing a java class.
+}
+\examples{
+javaClass <- new.java.class('java.util.ArrayList')
+javaObject <- new.external(javaClass)
+java.class(javaObject)
+}
+\seealso{
+\code{\link{new.external}}, \code{\link{new.java.class}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.external.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.external.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..e1f12eec9348c0007c0f047db87c4c8db7c62bda
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.external.Rd
@@ -0,0 +1,24 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{new.external}
+\alias{new.external}
+\title{Creates a new external object from the given class.}
+\usage{
+new.external(class)
+}
+\arguments{
+\item{class}{an external object representing a class}
+}
+\value{
+An external object created from the given class. Error in case the object could not be created.
+}
+\description{
+Creates a new external object from the given class.
+}
+\examples{
+javaClass <- new.java.class('java.util.ArrayList')
+new.external(javaClass)
+}
+\seealso{
+\code{\link{java.class}}, \code{\link{new.java.class}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.java.array.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.java.array.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..36a31df71e804dae545d1791048c6f8576263930
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.java.array.Rd
@@ -0,0 +1,26 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{new.java.array}
+\alias{new.java.array}
+\title{Creates a new java array given by the class name and length or dimensions.}
+\usage{
+new.java.array(class, dim)
+}
+\arguments{
+\item{class}{a fully qualified class name}
+
+\item{dim}{the array length or dimensions}
+}
+\value{
+An external object representing a java array. Error in case the array could not be created.
+}
+\description{
+Creates a new java array given by the class name and length or dimensions.
+}
+\examples{
+new.java.array('java.lang.Double', 10)
+new.java.array('java.lang.Double', c(2, 3))
+}
+\seealso{
+\code{\link{as.java.array}}, \code{\link{is.external.array}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.java.class.Rd b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.java.class.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..afc718272f49952b390b27cdaabb8326060bf8af
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/Rd/new.java.class.Rd
@@ -0,0 +1,25 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/fastrInteropt.R
+\name{new.java.class}
+\alias{new.java.class}
+\title{Creates a java class given by the fully qualified java class name. The class must be available on FastR`s interop classpath.}
+\usage{
+new.java.class(class, silent = FALSE)
+}
+\arguments{
+\item{class}{a fully qualified java class name}
+
+\item{silent}{logical, default FALSE. Determines whether errors should be reported or not.}
+}
+\value{
+An external object representing a java class. Otherwise either NULL if silent is set to TRUE, or error in case the class name could not be determined.
+}
+\description{
+Creates a java class given by the fully qualified java class name. The class must be available on FastR`s interop classpath.
+}
+\examples{
+new.java.class('java.util.ArrayList')
+}
+\seealso{
+\code{\link{java.addClasspathEntry}}, \code{\link{new.external}}, \code{\link{java.class}}
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmem.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmem.java
new file mode 100644
index 0000000000000000000000000000000000000000..4023e75743f2f89ed59332251971523e2c43434d
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmem.java
@@ -0,0 +1,94 @@
+/*
+ * 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.nodes.builtin.fastr.memprof;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.runtime.RVisibility.OFF;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerInstrument;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.api.vm.PolyglotRuntime.Instrument;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+@RBuiltin(name = ".fastr.profmem", visibility = OFF, kind = PRIMITIVE, parameterNames = {"on"}, behavior = IO)
+public abstract class FastRprofmem extends RBuiltinNode.Arg1 {
+
+    public static final String STACKS_VIEW = "stacks";
+    public static final String HOTSPOTS_VIEW = "hotspots";
+
+    static {
+        Casts casts = new Casts(FastRprofmem.class);
+        casts.arg("on").asLogicalVector().mustBe(singleElement()).findFirst().map(toBoolean());
+    }
+
+    static void castViewArg(Casts casts) {
+        casts.arg("view").asStringVector().mustBe(singleElement()).findFirst().mustBe(eq("stacks").or(eq("hotspots")));
+    }
+
+    static void castSnapshotArg(Casts casts) {
+        casts.arg("snapshot").mustBe(TruffleObject.class);
+    }
+
+    @Specialization
+    @TruffleBoundary
+    public Object doProfMem(boolean on) {
+        PolyglotEngine vm = RContext.getInstance().getVM();
+        if (vm != null) {
+            Instrument profilerInstr = vm.getRuntime().getInstruments().get(MemAllocProfilerInstrument.ID);
+            if (profilerInstr != null && profilerInstr.isEnabled() != on) {
+                profilerInstr.setEnabled(on);
+            }
+        } else {
+            throw error(RError.Message.GENERIC, "No context VM found");
+        }
+        return RNull.instance;
+    }
+
+    static MemAllocProfilerPrinter getProfilerPrinter() {
+        PolyglotEngine vm = RContext.getInstance().getVM();
+        MemAllocProfilerPrinter profPrinter = null;
+        if (vm != null) {
+            Instrument profilerInstr = vm.getRuntime().getInstruments().get(MemAllocProfilerInstrument.ID);
+            if (profilerInstr != null && profilerInstr.isEnabled()) {
+                profPrinter = profilerInstr.lookup(MemAllocProfilerPrinter.class);
+            }
+        }
+
+        if (profPrinter == null) {
+            profPrinter = new MemAllocProfilerPrinter(System.out);
+        }
+
+        return profPrinter;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemShow.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemShow.java
new file mode 100644
index 0000000000000000000000000000000000000000..b85dfe90a71c3f4139f114e8e635e2e814b22cbf
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemShow.java
@@ -0,0 +1,85 @@
+/*
+ * 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.nodes.builtin.fastr.memprof;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
+import static com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmem.castSnapshotArg;
+import static com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmem.castViewArg;
+import static com.oracle.truffle.r.runtime.RVisibility.OFF;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerPaths;
+
+@RBuiltin(name = ".fastr.profmem.show", visibility = OFF, kind = PRIMITIVE, parameterNames = {"levels", "desc", "id", "printParents", "view", "snapshot"}, behavior = IO)
+public abstract class FastRprofmemShow extends RBuiltinNode.Arg6 {
+
+    static {
+        Casts casts = new Casts(FastRprofmemShow.class);
+        casts.arg("levels").asIntegerVector().mustBe(singleElement()).findFirst().replaceNA(Integer.MAX_VALUE);
+        casts.arg("desc").asLogicalVector().mustBe(singleElement()).findFirst().map(toBoolean());
+        casts.arg("id").returnIf(nullValue()).asIntegerVector().mustBe(singleElement()).findFirst().replaceNA(Integer.MAX_VALUE);
+        casts.arg("printParents").asLogicalVector().mustBe(singleElement()).findFirst().map(toBoolean());
+        castViewArg(casts);
+        castSnapshotArg(casts);
+    }
+
+    @Override
+    public Object[] getDefaultParameterValues() {
+        return new Object[]{RRuntime.INT_NA, RRuntime.LOGICAL_TRUE, RNull.instance, RRuntime.LOGICAL_FALSE, FastRprofmem.STACKS_VIEW, RNull.instance};
+    }
+
+    @Specialization
+    public Object doProfMem(int levels, boolean desc, @SuppressWarnings("unused") RNull n, boolean printParents, String view, TruffleObject snapshot) {
+        return show(levels, desc, null, printParents, view, snapshot);
+    }
+
+    @Specialization
+    public Object doProfMem(int levels, boolean desc, int entryId, boolean printParents, String view, TruffleObject snapshot) {
+        return show(levels, desc, entryId, printParents, view, snapshot);
+    }
+
+    @TruffleBoundary
+    private static Object show(int levels, boolean desc, Integer entryId, boolean printParents, String view, TruffleObject snapshotTO) {
+        MemAllocProfilerPaths snapshot = MemAllocProfilerPaths.fromTruffleObject(snapshotTO);
+        return show(levels, desc, entryId, printParents, view, snapshot);
+    }
+
+    private static Object show(int levels, boolean desc, Integer entryId, boolean printParents, String view, MemAllocProfilerPaths snapshot) {
+        MemAllocProfilerPaths usedSnapshot = snapshot;
+        if (FastRprofmem.HOTSPOTS_VIEW.equals(view)) {
+            usedSnapshot = usedSnapshot.toHS();
+        }
+        FastRprofmem.getProfilerPrinter().show(usedSnapshot, entryId, levels, desc, printParents);
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemSnapshot.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemSnapshot.java
new file mode 100644
index 0000000000000000000000000000000000000000..e003c4e52bbf41a33b118d938d9734b749dd71e1
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemSnapshot.java
@@ -0,0 +1,65 @@
+/*
+ * 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.nodes.builtin.fastr.memprof;
+
+import static com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmem.castViewArg;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.runtime.RVisibility.OFF;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerPaths;
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerStacks;
+
+@RBuiltin(name = ".fastr.profmem.snapshot", visibility = OFF, kind = PRIMITIVE, parameterNames = {"name", "view"}, behavior = IO)
+public abstract class FastRprofmemSnapshot extends RBuiltinNode.Arg2 {
+
+    static {
+        Casts casts = new Casts(FastRprofmemSnapshot.class);
+        casts.arg("name").asStringVector().mustBe(singleElement()).findFirst();
+        castViewArg(casts);
+    }
+
+    @Override
+    public Object[] getDefaultParameterValues() {
+        return new Object[]{RNull.instance, FastRprofmem.STACKS_VIEW};
+    }
+
+    @Specialization
+    @TruffleBoundary
+    public TruffleObject makeSnapshot(String name, String view) {
+        MemAllocProfilerPaths snapshot = MemAllocProfilerStacks.getInstance().getStackPaths().getOrMakeSnapshot(name);
+
+        if (FastRprofmem.HOTSPOTS_VIEW.equals(view)) {
+            snapshot = snapshot.toHS();
+        }
+
+        return snapshot.toTruffleObject();
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemSource.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemSource.java
new file mode 100644
index 0000000000000000000000000000000000000000..3c008c7eec1fbbdd89b1461b122cc9b5779c4654
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/FastRprofmemSource.java
@@ -0,0 +1,73 @@
+/*
+ * 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.nodes.builtin.fastr.memprof;
+
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
+import static com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmem.castSnapshotArg;
+import static com.oracle.truffle.r.nodes.builtin.fastr.memprof.FastRprofmem.castViewArg;
+import static com.oracle.truffle.r.runtime.RVisibility.OFF;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.IO;
+import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.builtins.RBuiltin;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerPaths;
+
+@RBuiltin(name = ".fastr.profmem.source", visibility = OFF, kind = PRIMITIVE, parameterNames = {"id", "view", "snapshot"}, behavior = IO)
+public abstract class FastRprofmemSource extends RBuiltinNode.Arg3 {
+
+    static {
+        Casts casts = new Casts(FastRprofmemSource.class);
+        casts.arg("id").asIntegerVector().mustBe(singleElement()).findFirst().replaceNA(Integer.MAX_VALUE);
+        castViewArg(casts);
+        castSnapshotArg(casts);
+    }
+
+    @Override
+    public Object[] getDefaultParameterValues() {
+        return new Object[]{RRuntime.INT_NA, FastRprofmem.STACKS_VIEW, RNull.instance};
+    }
+
+    @Specialization
+    @TruffleBoundary
+    public Object showSource(int entryId, String view, TruffleObject snapshotTO) {
+        MemAllocProfilerPaths paths = MemAllocProfilerPaths.fromTruffleObject(snapshotTO);
+        return showSource(entryId, view, paths);
+    }
+
+    private static Object showSource(int entryId, String view, MemAllocProfilerPaths snap) {
+        MemAllocProfilerPaths snapshot = snap;
+        if (FastRprofmem.HOTSPOTS_VIEW.equals(view)) {
+            snapshot = snapshot.toHS();
+        }
+
+        FastRprofmem.getProfilerPrinter().source(snapshot, entryId);
+
+        return RNull.instance;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/MemAllocProfilerPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/MemAllocProfilerPrinter.java
new file mode 100644
index 0000000000000000000000000000000000000000..c3cda91fda8596729ce54f97f3c9b1ab2cf4a595
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/memprof/MemAllocProfilerPrinter.java
@@ -0,0 +1,118 @@
+/*
+ * 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.nodes.builtin.fastr.memprof;
+
+import java.io.PrintStream;
+import java.util.Iterator;
+
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerPaths;
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerStacks;
+
+/**
+ * A utility class that can be used for developing simple command line profiling tools. It works on
+ * top of the {@link MemAllocProfilerStacks memory allocations model}.
+ *
+ * <pre>
+ * MemAllocProfilerPrinter memAllocPrinter = new MemAllocProfilerPrinter(System.out);
+ * // Print the whole hierarchy of allocations
+ * memAllocPrinter.show(null, entryId.MAX_VALUE, true, true);
+ * // Print the source section associated with the allocation entry 103
+ * memAllocPrinter.source(103);
+ * </pre>
+ */
+public final class MemAllocProfilerPrinter {
+
+    private final PrintStream out;
+
+    /**
+     * @param out the output stream used to print the output
+     */
+    public MemAllocProfilerPrinter(PrintStream out) {
+        this.out = out;
+    }
+
+    /**
+     * Show the allocations hierarchy.
+     *
+     * @param paths the allocation paths
+     * @param entryId the id of the top allocation entry. If <code>null</code> the absolute root
+     *            entry is used.
+     * @param levels the maximum number of levels of the hierarchy to print
+     * @param desc if true allocation entries will be sorted in the descending order below their
+     *            parent entries
+     * @param printParents instructs to print the parent entries of the top entry. It makes sense
+     *            only if a sub-hierarchy is printed.
+     */
+    public void show(MemAllocProfilerPaths paths, Integer entryId, int levels, boolean desc, boolean printParents) {
+        MemAllocProfilerPaths.Entry rootEntry = null;
+        if (entryId != null) {
+            rootEntry = paths.getEntry(entryId);
+        }
+
+        paths.traverse(rootEntry, stack -> {
+            if (stack.peek().getStats().getCount() == 0 && stack.size() != levels) {
+                return;
+            }
+
+            StringBuilder sb = new StringBuilder();
+            Iterator<MemAllocProfilerPaths.Entry> iter = stack.descendingIterator();
+            while (iter.hasNext()) {
+                MemAllocProfilerPaths.Entry entry = iter.next();
+                if (entry.getId() == 0) {
+                    continue;
+                }
+                sb.append('/').append(entry.getName()).append("[id=").append(entry.getId()).append(']');
+            }
+            MemAllocProfilerPaths.Entry entry = stack.peek();
+            sb.append(" { size: ").append(entry.getAllocatedAggr()).append(", count: ").append(entry.getCountAggr()).append(" }");
+            out.println(sb.toString());
+        }, new MemAllocProfilerStacks.AlocatedAggrComparator(desc), levels, printParents);
+    }
+
+    /**
+     * Print the source section associated with the given allocation entry id.
+     *
+     * @param entryId the entry id
+     */
+    public void source(MemAllocProfilerPaths paths, int entryId) {
+        MemAllocProfilerPaths.Entry entry = paths.getEntry(entryId);
+        if (entry == null) {
+            out.format("No entry found for id %s\n", entryId);
+        } else {
+            SourceSection sel = entry.getSourceSection();
+            StringBuilder sb = new StringBuilder();
+            sb.append("{ size: ").append(entry.getAllocatedAggr()).append(", localSize: ").append(entry.getStats().getAllocated()).append(", count: ").append(entry.getCountAggr()).append(
+                            ", localCount: ").append(entry.getStats().getCount()).append(" }");
+            out.println(sb);
+
+            if (sel == null) {
+                out.println("No source available");
+            } else {
+                out.format("<<< %s at %s:%s\n", entry.getName(), sel.getStartLine(), sel.getStartColumn());
+                out.println(sel.getCode());
+                out.format(">>> %s at %s:%s\n", entry.getName(), sel.getEndLine(), sel.getEndColumn());
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
index c37597d0690a1c8ccae5322cb8a7ae91e4b3e26f..c5507805b9b2e72728bcb283e51625a1aae0a0d3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java
@@ -23,10 +23,10 @@
 package com.oracle.truffle.r.nodes.builtin.helpers;
 
 import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
 import com.oracle.truffle.r.runtime.JumpToTopLevelException;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -37,10 +37,10 @@ import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RSrcref;
 import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 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.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -49,7 +49,6 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState.BrowserState;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
-import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
@@ -63,7 +62,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * </ol>
  *
  */
-public abstract class BrowserInteractNode extends RNode {
+public abstract class BrowserInteractNode extends Node {
 
     public static final int STEP = 0;
     public static final int NEXT = 1;
@@ -73,26 +72,29 @@ public abstract class BrowserInteractNode extends RNode {
     @Child private GetFixedAttributeNode getSrcRefAttrNode;
     @Child private GetFixedAttributeNode getSrcFileAttrNode;
 
+    public abstract int execute(VirtualFrame frame, RCaller caller);
+
     @Specialization
-    protected int interact(VirtualFrame frame) {
+    protected int interact(VirtualFrame frame, RCaller caller) {
         CompilerDirectives.transferToInterpreter();
         MaterializedFrame mFrame = frame.materialize();
-        ConsoleHandler ch = RContext.getInstance().getConsoleHandler();
+        ConsoleIO ch = RContext.getInstance().getConsole();
         BrowserState browserState = RContext.getInstance().stateInstrumentation.getBrowserState();
         String savedPrompt = ch.getPrompt();
         RFunction callerFunction = RArguments.getFunction(frame);
         // we may be at top level where there is not caller
-        boolean callerIsDebugged = callerFunction == null ? false : DebugHandling.isDebugged(callerFunction);
+        boolean callerIsDebugged = callerFunction == null || DebugHandling.isDebugged(callerFunction);
         int exitMode = NEXT;
-        RCaller currentCaller = RArguments.getCall(mFrame);
+        RCaller currentCaller = caller;
         if (currentCaller == null) {
             currentCaller = RCaller.topLevel;
         }
-        RCaller browserCaller = createCaller(currentCaller);
+        RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder();
+        RCaller browserCaller = RCaller.create(null, currentCaller, builder.call(RSyntaxNode.INTERNAL, builder.lookup(RSyntaxNode.INTERNAL, "browser", true)));
         try {
             browserState.setInBrowser(browserCaller);
             LW: while (true) {
-                ch.setPrompt(browserPrompt(RArguments.getDepth(frame)));
+                ch.setPrompt(browserPrompt(currentCaller.getDepth()));
                 String input = ch.readLine();
                 if (input != null) {
                     input = input.trim();
@@ -130,7 +132,7 @@ public abstract class BrowserInteractNode extends RNode {
                     case "Q":
                         throw new JumpToTopLevelException();
                     case "where": {
-                        if (RArguments.getDepth(mFrame) > 1) {
+                        if (currentCaller.getDepth() > 1) {
                             Object stack = Utils.createTraceback(0);
                             // browser inverts frame depth
                             int idepth = 1;
@@ -178,12 +180,6 @@ public abstract class BrowserInteractNode extends RNode {
         return exitMode;
     }
 
-    @TruffleBoundary
-    private static RCaller createCaller(RCaller currentCaller) {
-        RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder();
-        return RCaller.create(null, currentCaller, builder.call(RSyntaxNode.INTERNAL, builder.lookup(RSyntaxNode.INTERNAL, "browser", true)));
-    }
-
     private String getSrcinfo(RStringVector element) {
         if (getSrcRefAttrNode == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
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 b50be670aff64e6194a116cffdf175381e241629..be71516f860f6787c10996a09aee8ef3cf117999 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
@@ -39,6 +39,7 @@ import com.oracle.truffle.api.instrumentation.StandardTags;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.Node.Child;
 import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.api.utilities.CyclicAssumption;
 import com.oracle.truffle.r.nodes.control.AbstractLoopNode;
@@ -51,8 +52,8 @@ import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
@@ -66,9 +67,9 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor;
 /**
  * The implementation of the R debug functions.
  *
- * When a function is enabled for debugging a set of {@link DebugEventListener}s are created and
- * attached to key nodes in the AST body associated with the {@link FunctionDefinitionNode}
- * corresponding to the {@link RFunction} instance.
+ * When a function is enabled for debugging a set of {@link InteractingDebugEventListener}s are
+ * created and attached to key nodes in the AST body associated with the
+ * {@link FunctionDefinitionNode} corresponding to the {@link RFunction} instance.
  *
  * Three different listener classes are defined:
  * <ul>
@@ -108,8 +109,6 @@ public class DebugHandling {
 
     /**
      * Attach the DebugHandling instrument to the FunctionStatementsNode and all syntactic nodes.
-     *
-     * @param implicit TODO
      */
     public static boolean enableDebug(RFunction func, Object text, Object condition, boolean once, boolean implicit) {
         FunctionStatementsEventListener fbr = getFunctionStatementsEventListener(func);
@@ -117,23 +116,38 @@ public class DebugHandling {
             attachDebugHandler(func, text, condition, once, implicit);
         } else {
             fbr.enable();
+            fbr.setParentListener(null);
+
+            if (!fbr.isAttached()) {
+                fbr.attach();
+            }
         }
         return true;
     }
 
     public static boolean undebug(RFunction func) {
-        FunctionStatementsEventListener fbr = getFunctionStatementsEventListener(func);
-        if (fbr == null) {
-            return false;
-        } else {
-            fbr.disable();
+        FunctionStatementsEventListener fsel = getFunctionStatementsEventListener(func);
+        if (fsel != null && !fsel.disabled()) {
+            fsel.dispose();
             return true;
         }
+        return false;
     }
 
     public static boolean isDebugged(RFunction func) {
         FunctionStatementsEventListener fser = getFunctionStatementsEventListener(func);
-        return fser != null && !fser.disabled();
+        return fser != null && (!fser.disabled() || fser.parentListener != null && !fser.parentListener.disabled());
+    }
+
+    /**
+     *
+     */
+    public static void dispose() {
+        for (ExecutionEventListener l : RContext.getInstance().stateInstrumentation.getDebugListeners()) {
+            if (l instanceof DebugEventListener) {
+                ((DebugEventListener) l).dispose();
+            }
+        }
     }
 
     private static FunctionStatementsEventListener getFunctionStatementsEventListener(RFunction func) {
@@ -151,50 +165,37 @@ public class DebugHandling {
     @TruffleBoundary
     private static FunctionStatementsEventListener attachDebugHandler(FunctionDefinitionNode fdn, Object text, Object condition, boolean once, boolean implicit) {
         FunctionStatementsEventListener fser = new FunctionStatementsEventListener(fdn, text, condition, once, implicit);
+
         // First attach the main listener on the START_FUNCTION
-        Instrumenter instrumenter = RInstrumentation.getInstrumenter();
-        SourceSectionFilter.Builder functionBuilder = RInstrumentation.createFunctionFilter(fdn, StandardTags.RootTag.class);
-        instrumenter.attachListener(functionBuilder.build(), fser);
-        // Next attach statement handler to all STATEMENTs except LOOPs
-        SourceSectionFilter.Builder statementBuilder = RInstrumentation.createFunctionStatementFilter(fdn);
-        statementBuilder.tagIsNot(RSyntaxTags.LoopTag.class);
-        instrumenter.attachListener(statementBuilder.build(), fser.getStatementListener());
-        // Finally attach loop listeners to all loop nodes
-        SourceSectionFilter.Builder loopBuilder = RInstrumentation.createFunctionFilter(fdn, RSyntaxTags.LoopTag.class);
-        new RSyntaxVisitor<Void>() {
-
-            @Override
-            protected Void visit(RSyntaxCall element) {
-                if (element instanceof AbstractLoopNode) {
-                    instrumenter.attachListener(loopBuilder.build(), fser.getLoopStatementReceiver((AbstractLoopNode) element));
-                }
-                accept(element.getSyntaxLHS());
-                for (RSyntaxElement arg : element.getSyntaxArguments()) {
-                    accept(arg);
-                }
-                return null;
-            }
+        fser.attach();
 
-            @Override
-            protected Void visit(RSyntaxConstant element) {
-                return null;
-            }
+        return fser;
+    }
 
-            @Override
-            protected Void visit(RSyntaxLookup element) {
-                return null;
-            }
+    @TruffleBoundary
+    public static void enableLineDebug(Source fdn, int line) {
+        Instrumenter instrumenter = RInstrumentation.getInstrumenter();
+        SourceSection lineSourceSection = fdn.createSection(line);
+        SourceSectionFilter.Builder functionBuilder = RInstrumentation.createLineFilter(fdn, line, StandardTags.StatementTag.class);
+        LineBreakpointEventListener listener = new LineBreakpointEventListener(lineSourceSection);
+        listener.setBinding(instrumenter.attachListener(functionBuilder.build(), listener));
+        RContext.getInstance().stateInstrumentation.putDebugListener(lineSourceSection, listener);
+    }
 
-            @Override
-            protected Void visit(RSyntaxFunction element) {
-                accept(element.getSyntaxBody());
-                return null;
+    @TruffleBoundary
+    public static void disableLineDebug(Source fdn, int line) {
+        LineBreakpointEventListener l = (LineBreakpointEventListener) RContext.getInstance().stateInstrumentation.getDebugListener(fdn.createSection(line));
+        if (l != null) {
+            l.dispose();
+
+            if (l.fser != null) {
+                l.fser.setParentListener(null);
+                l.fser.disable();
             }
-        }.accept(fdn);
-        return fser;
+        }
     }
 
-    private static FunctionStatementsEventListener ensureSingleStep(FunctionDefinitionNode fdn) {
+    private static FunctionStatementsEventListener ensureSingleStep(FunctionDefinitionNode fdn, LineBreakpointEventListener parentListener) {
         FunctionStatementsEventListener fser = getFunctionStatementsEventListener(fdn);
         if (fser == null) {
             // attach a "once" listener
@@ -205,30 +206,29 @@ public class DebugHandling {
                 // record initial state was disabled for undo
                 fser.enabledForStepInto = true;
             }
+            if (!fser.isAttached()) {
+                fser.attach();
+            }
         }
+        fser.setParentListener(parentListener);
         return fser;
     }
 
     private abstract static class DebugEventListener implements ExecutionEventListener {
 
-        protected final Object text;
-        protected final Object condition;
-        protected final FunctionDefinitionNode functionDefinitionNode;
-        protected EventBinding<StepIntoInstrumentListener> stepIntoInstrument;
-        @CompilationFinal private boolean disabled;
-        CyclicAssumption disabledUnchangedAssumption = new CyclicAssumption("debug event disabled state unchanged");
-
-        @Child private BrowserInteractNode browserInteractNode = BrowserInteractNodeGen.create();
+        private EventBinding<? extends DebugEventListener> binding;
 
-        protected DebugEventListener(FunctionDefinitionNode functionDefinitionNode, Object text, Object condition) {
-            this.text = text;
-            this.condition = condition;
-            this.functionDefinitionNode = functionDefinitionNode;
+        @TruffleBoundary
+        protected static void print(String msg, boolean nl) {
+            try {
+                StdConnections.getStdout().writeString(msg, nl);
+            } catch (IOException ex) {
+                throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage());
+            }
         }
 
-        @Override
-        public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) {
-        }
+        @CompilationFinal private boolean disabled;
+        CyclicAssumption disabledUnchangedAssumption = new CyclicAssumption("debug event disabled state unchanged");
 
         boolean disabled() {
             return disabled || RContext.getInstance().stateInstrumentation.debugGloballyDisabled();
@@ -249,17 +249,45 @@ public class DebugHandling {
             }
         }
 
-        @TruffleBoundary
-        protected static void print(String msg, boolean nl) {
-            try {
-                StdConnections.getStdout().writeString(msg, nl);
-            } catch (IOException ex) {
-                throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, ex.getMessage());
+        public EventBinding<? extends DebugEventListener> getBinding() {
+            return binding;
+        }
+
+        public void setBinding(EventBinding<? extends DebugEventListener> binding) {
+            assert binding != null;
+            assert this.binding == null;
+            this.binding = binding;
+        }
+
+        public void dispose() {
+            if (binding != null && !binding.isDisposed()) {
+                binding.dispose();
+                binding = null;
             }
         }
+    }
+
+    private abstract static class InteractingDebugEventListener extends DebugEventListener {
+
+        protected final Object text;
+        protected final Object condition;
+        protected final FunctionDefinitionNode functionDefinitionNode;
+        protected EventBinding<StepIntoInstrumentListener> stepIntoInstrument;
+
+        @Child private BrowserInteractNode browserInteractNode = BrowserInteractNodeGen.create();
+
+        protected InteractingDebugEventListener(FunctionDefinitionNode functionDefinitionNode, Object text, Object condition) {
+            this.text = text;
+            this.condition = condition;
+            this.functionDefinitionNode = functionDefinitionNode;
+        }
+
+        @Override
+        public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) {
+        }
 
         protected void browserInteract(Node node, VirtualFrame frame) {
-            int exitMode = (int) browserInteractNode.execute(frame);
+            int exitMode = browserInteractNode.execute(frame, RArguments.getCall(frame));
             switch (exitMode) {
                 case BrowserInteractNode.NEXT:
                     break;
@@ -314,6 +342,12 @@ public class DebugHandling {
                 stepIntoInstrument = null;
             }
         }
+
+        @Override
+        public void dispose() {
+            super.dispose();
+            clearStepInstrument();
+        }
     }
 
     /**
@@ -323,28 +357,35 @@ public class DebugHandling {
      * "steps over" the <@code {</code> to the first statement, otherwise it just stops at the first
      * statement.
      */
-    private static class FunctionStatementsEventListener extends DebugEventListener {
+    private static class FunctionStatementsEventListener extends InteractingDebugEventListener {
 
         private final StatementEventListener statementListener;
-        ArrayList<LoopStatementEventListener> loopStatementListeners = new ArrayList<>();
+        private final ArrayList<LoopStatementEventListener> loopStatementListeners = new ArrayList<>();
 
         /**
          * Denotes the {@code debugOnce} function, debugging disabled after one execution, or a
          * handler established temporarily for step-into.
          */
         private final boolean once;
+
         /**
          * Denotes that this was installed by an explicit call to {@code browser()} on an otherwise
          * undebugged function. {@code assert once == true}.
          */
         private final boolean implicit;
+
         /**
          * Records whether a permanent handler was (temporarily) enabled for a step-into.
-         *
          */
         private boolean enabledForStepInto;
         private boolean continuing;
 
+        /**
+         * The parent listener (a line breakpoint listener) if this function statement listener has
+         * been created due to a line breakpoint.
+         */
+        private LineBreakpointEventListener parentListener;
+
         FunctionStatementsEventListener(FunctionDefinitionNode functionDefinitionNode, Object text, Object condition, boolean once, boolean implicit) {
             super(functionDefinitionNode, text, condition);
             RContext.getInstance().stateInstrumentation.putDebugListener(functionDefinitionNode.getSourceSection(), this);
@@ -353,23 +394,97 @@ public class DebugHandling {
             this.implicit = implicit;
         }
 
-        StatementEventListener getStatementListener() {
-            return statementListener;
+        void setParentListener(LineBreakpointEventListener l) {
+            if (l != null) {
+                super.disable();
+            } else {
+                super.enable();
+            }
+            parentListener = l;
+        }
+
+        void attachStatementListener() {
+            if (statementListener.getBinding() == null) {
+                SourceSectionFilter.Builder statementBuilder = RInstrumentation.createFunctionStatementFilter(functionDefinitionNode);
+                statementBuilder.tagIsNot(RSyntaxTags.LoopTag.class);
+                Instrumenter instrumenter = RInstrumentation.getInstrumenter();
+                statementListener.setBinding(instrumenter.attachListener(statementBuilder.build(), statementListener));
+            }
         }
 
-        LoopStatementEventListener getLoopStatementReceiver(RSyntaxNode loopNode) {
+        LoopStatementEventListener getLoopStatementReceiver(SourceSectionFilter ssf, RSyntaxNode loopNode) {
             LoopStatementEventListener lser = new LoopStatementEventListener(functionDefinitionNode, text, condition, loopNode, this);
             loopStatementListeners.add(lser);
+            Instrumenter instrumenter = RInstrumentation.getInstrumenter();
+            lser.setBinding(instrumenter.attachListener(ssf, lser));
             return lser;
         }
 
         @Override
-        void disable() {
-            super.disable();
-            statementListener.disable();
+        public void dispose() {
+            disable();
+            super.dispose();
+            statementListener.dispose();
+
             for (LoopStatementEventListener lser : loopStatementListeners) {
-                lser.disable();
+                lser.dispose();
             }
+            loopStatementListeners.clear();
+        }
+
+        public boolean isAttached() {
+            return getBinding() != null && !getBinding().isDisposed();
+        }
+
+        public void attach() {
+
+            Instrumenter instrumenter = RInstrumentation.getInstrumenter();
+            SourceSectionFilter.Builder functionBuilder = RInstrumentation.createFunctionFilter(functionDefinitionNode, StandardTags.RootTag.class);
+            setBinding(instrumenter.attachListener(functionBuilder.build(), this));
+
+            // Next attach statement handler to all STATEMENTs except LOOPs
+            attachStatementListener();
+
+            // Finally attach loop listeners to all loop nodes
+            SourceSectionFilter.Builder loopBuilder = RInstrumentation.createFunctionFilter(functionDefinitionNode, RSyntaxTags.LoopTag.class);
+            new RSyntaxVisitor<Void>() {
+
+                @Override
+                protected Void visit(RSyntaxCall element) {
+                    if (element instanceof AbstractLoopNode) {
+                        getLoopStatementReceiver(loopBuilder.build(), (AbstractLoopNode) element);
+                    }
+                    accept(element.getSyntaxLHS());
+                    for (RSyntaxElement arg : element.getSyntaxArguments()) {
+                        if (arg != null) {
+                            accept(arg);
+                        }
+                    }
+                    return null;
+                }
+
+                @Override
+                protected Void visit(RSyntaxConstant element) {
+                    return null;
+                }
+
+                @Override
+                protected Void visit(RSyntaxLookup element) {
+                    return null;
+                }
+
+                @Override
+                protected Void visit(RSyntaxFunction element) {
+                    accept(element.getSyntaxBody());
+                    return null;
+                }
+            }.accept(functionDefinitionNode);
+        }
+
+        @Override
+        void disable() {
+            super.disable();
+            disableChildren();
         }
 
         @Override
@@ -385,14 +500,18 @@ public class DebugHandling {
             }
         }
 
-        void setContinuing() {
-            continuing = true;
+        void disableChildren() {
             statementListener.disable();
             for (LoopStatementEventListener lser : loopStatementListeners) {
                 lser.disable();
             }
         }
 
+        void setContinuing() {
+            continuing = true;
+            disableChildren();
+        }
+
         void setFinishing(AbstractLoopNode loopNode) {
             // Disable every statement listener except that for loopNode
             for (LoopStatementEventListener lser : loopStatementListeners) {
@@ -409,20 +528,29 @@ public class DebugHandling {
             enableChildren();
         }
 
+        private void onEnterInternal(EventContext context, VirtualFrame frame) {
+            CompilerDirectives.transferToInterpreter();
+            print("debugging in: ", false);
+            printCall(frame);
+            printNode(context.getInstrumentedNode(), true);
+            browserInteract(context.getInstrumentedNode(), frame);
+        }
+
         @Override
         public void onEnter(EventContext context, VirtualFrame frame) {
             if (!disabled()) {
-                CompilerDirectives.transferToInterpreter();
-                print("debugging in: ", false);
-                printCall(frame);
                 /*
                  * If this is a recursive call, then returnCleanup will not have happened, so we
                  * enable our child listeners unconditionally. TODO It is possible that the enabled
                  * state should be stacked to match the call stack in the recursive case.
                  */
                 enableChildren();
-                printNode(context.getInstrumentedNode(), true);
-                browserInteract(context.getInstrumentedNode(), frame);
+                onEnterInternal(context, frame);
+            } else {
+                // This is necessary if a line breakpoint has been set. We disable the children
+                // listeners such that it does not stop until line breakpoint listener has been
+                // invoked.
+                disableChildren();
             }
         }
 
@@ -466,7 +594,7 @@ public class DebugHandling {
 
     @TruffleBoundary
     private static void printNode(Node node, boolean startFunction) {
-        ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
+        ConsoleIO console = RContext.getInstance().getConsole();
         /*
          * N.B. It would seem that GnuR does a deparse that because, e.g., a function that ends with
          * } without a preceding newline prints with one and indentation is standardized.
@@ -475,20 +603,20 @@ public class DebugHandling {
         boolean curly = RSyntaxCall.isCallTo((RSyntaxElement) node, "{");
 
         if (startFunction && !curly) {
-            consoleHandler.print("debug: ");
+            console.print("debug: ");
         } else {
             SourceSection source = ((RBaseNode) node).asRSyntaxNode().getSourceSection();
             String path = RSource.getPath(source.getSource());
             if (path == null) {
                 path = "";
             }
-            consoleHandler.print("debug at " + path + "#" + source.getStartLine() + ": ");
+            console.print("debug at " + path + "#" + source.getStartLine() + ": ");
         }
-        consoleHandler.print(RDeparse.deparseSyntaxElement(rNode.asRSyntaxNode()));
-        consoleHandler.print("\n");
+        console.print(RDeparse.deparseSyntaxElement(rNode.asRSyntaxNode()));
+        console.print("\n");
     }
 
-    private static class StatementEventListener extends DebugEventListener {
+    private static class StatementEventListener extends InteractingDebugEventListener {
 
         StatementEventListener(FunctionDefinitionNode functionDefinitionNode, Object text, Object condition) {
             super(functionDefinitionNode, text, condition);
@@ -515,6 +643,61 @@ public class DebugHandling {
         }
     }
 
+    /**
+     * A catch-listener that will be invoked if a line breakpoint is hit. It then enables the whole
+     * function for debugging.
+     */
+    private static class LineBreakpointEventListener extends DebugEventListener {
+
+        private final SourceSection ss;
+        private FunctionStatementsEventListener fser;
+
+        LineBreakpointEventListener(SourceSection ss) {
+            this.ss = ss;
+        }
+
+        @Override
+        public void onEnter(EventContext context, VirtualFrame frame) {
+            if (!disabled()) {
+                CompilerDirectives.transferToInterpreter();
+                installFunctionListener(frame);
+                assert fser != null;
+                print(ss.getSource().getName() + "#" + ss.getStartLine(), true);
+                fser.onEnterInternal(context, frame);
+            }
+        }
+
+        private void installFunctionListener(VirtualFrame frame) {
+            if (fser == null) {
+                RFunction function = RArguments.getFunction(frame);
+                fser = ensureSingleStep(RInstrumentation.getFunctionDefinitionNode(function), this);
+            }
+        }
+
+        @Override
+        public void onReturnValue(EventContext context, VirtualFrame frame, Object result) {
+            if (fser != null) {
+                fser.enableChildren();
+            }
+        }
+
+        @Override
+        public void onReturnExceptional(EventContext context, VirtualFrame frame, Throwable exception) {
+            if (fser != null) {
+                fser.enableChildren();
+            }
+        }
+
+        @Override
+        public void dispose() {
+            super.dispose();
+            disable();
+            if (fser != null) {
+                fser.dispose();
+            }
+        }
+    }
+
     /**
      * Handles the loop header and there is one instance registered for each loop.
      */
@@ -601,7 +784,7 @@ public class DebugHandling {
                 RootNode rootNode = context.getInstrumentedNode().getRootNode();
                 if (rootNode instanceof FunctionDefinitionNode) {
                     FunctionDefinitionNode fdn = (FunctionDefinitionNode) rootNode;
-                    FunctionStatementsEventListener ensureSingleStep = ensureSingleStep(fdn);
+                    FunctionStatementsEventListener ensureSingleStep = ensureSingleStep(fdn, null);
 
                     functionStatementsEventListener.clearStepInstrument();
                     ensureSingleStep.onEnter(context, frame);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R
index 698ae85bc701c39fe45b7d6ae8f35fcd75ae7345..83b0473a58d44dcfa8d72db4ca09781807a45c9b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/methods/R/methods_overrides.R
@@ -26,13 +26,13 @@ eval(expression({
 
 new <- function (Class, ...) {
     if(is.character(Class)) {
-        javaClass <- .fastr.java.class(Class, silent=TRUE)
+        javaClass <- new.java.class(Class, silent=TRUE)
         if(!is.null(javaClass)) {
             Class <- javaClass
         }
     }
-    if(.fastr.interop.isExternal(Class)) {
-        .fastr.interop.new(Class, ...)
+    if(is.external(Class)) {
+        new.external(Class, ...)
     } else {
         ClassDef <- getClass(Class, where = topenv(parent.frame()))
         value <- .Call(C_new_object, ClassDef)
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 02940b6a2aa6d27bf3fc7b34d79558e58f26a8c3..ef6706e12aabf46ad4405a29bbee45cc2b61f442 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
@@ -55,9 +55,23 @@ newSHAREDnodes <- function(nnodes, debug, options = defaultClusterOptions) {
 	contexts <- vector("integer", nnodes)
 	channels <- vector("integer", nnodes)
 	outfile <- getClusterOption("outfile", options)
+	
+	# get initial port number
+	port <- as.integer(parallel:::getClusterOption("port", options))
+	
+	# find first unused port number
+	continue <- TRUE
+	firstUnused <- 0
+	while(continue) {
+		tryCatch({
+			.fastr.channel.get(port + (firstUnused + 1) * 1000)
+			firstUnused <- firstUnused + 1 
+		}, error = function(e) { continue <<- FALSE })
+	}
+
 	for (i in 1:nnodes) {
 		# generate unique values for channel keys (addition factor is chosen based on how snow generates port numbers)
-		port <- as.integer(parallel:::getClusterOption("port", options) + i * 1000)
+		port <- as.integer(parallel:::getClusterOption("port", options) + (i + firstUnused) * 1000)
 		
 		startup <- substitute(local({
             makeSHAREDmaster <- function(key) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/snow/R/snow_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/snow/R/snow_overrides.R
new file mode 100644
index 0000000000000000000000000000000000000000..127fd3195449cee82afb1ca48db71b4ba78a8982
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/snow/R/snow_overrides.R
@@ -0,0 +1,131 @@
+#
+# This material is distributed under the GNU General Public License
+# Version 2. You may review the terms of this license at
+# http://www.gnu.org/licenses/gpl-2.0.html
+#
+# Copyright (c) 1995-2014, The R Core Team
+# Copyright (c) 2016, Oracle and/or its affiliates
+#
+# All rights reserved.
+#
+
+## Derived from snow and parallel packages
+
+eval(expression({
+
+# overwritten functions:
+
+makeCluster <- function (spec, type = getClusterOption("type"), ...) {
+    switch(type,
+        SOCK = snow::makeSOCKcluster(spec, ...),
+        MPI = snow::makeMPIcluster(spec, ...),
+        NWS = snow::makeNWScluster(spec, ...),
+        SHARED = makeSHAREDcluster(spec, ...), # this line was added
+        stop("unknown cluster type"))
+}
+
+# added functions:
+
+closeNode.SHAREDnode <- function(node) {
+    .fastr.channel.close(node$channel)
+}
+
+sendData.SHAREDnode <- function(node, data) {
+    .fastr.channel.send(node$channel, data)
+}
+
+recvData.SHAREDnode <- function(node) {
+    .fastr.channel.receive(node$channel)
+}
+
+recvOneData.SHAREDcluster <- function(cl) {
+	channel_ids = lapply(cl, function(l) l[["channel"]])
+    res <- .fastr.channel.select(channel_ids)
+	selected_id = res[[1]]
+	# TODO: I am sure there is a better way...
+	indexes = lapply(cl, function(l, id) if (identical(l[["channel"]], id)) id else as.integer(NA), id=selected_id)
+	node_ind = which(as.double(indexes)==as.double(selected_id))
+	list(node = node_ind, value = res[[2]])
+}
+
+newSHAREDnodes <- function(nnodes, debug, options = defaultClusterOptions) {
+	context_code <- vector("character", nnodes)
+	contexts <- vector("integer", nnodes)
+	channels <- vector("integer", nnodes)
+	outfile <- getClusterOption("outfile", options)
+	
+	# get initial port number
+	port <- as.integer(snow:::getClusterOption("port", options))
+	
+	# find first unused port number
+	continue <- TRUE
+	firstUnused <- 0
+	while(continue) {
+		tryCatch({
+			.fastr.channel.get(port + (firstUnused + 1) * 1000)
+			firstUnused <- firstUnused + 1 
+		}, error = function(e) { continue <<- FALSE })
+	}
+
+	for (i in 1:nnodes) {
+		# generate unique values for channel keys (addition factor is chosen based on how snow generates port numbers)
+		port <- as.integer(snow:::getClusterOption("port", options) + (i + firstUnused) * 1000)
+		
+		startup <- substitute(local({
+            makeSHAREDmaster <- function(key) {
+                channel <- .fastr.channel.get(as.integer(key))
+                structure(list(channel=channel), class = "SHAREDnode")
+            }
+            snow:::sinkWorkerOutput(OUTFILE)
+            snow:::slaveLoop(makeSHAREDmaster(PORT))
+        }), list(OUTFILE=outfile, PORT=port))
+		
+        context_code[[i]] <- paste0(deparse(startup), collapse="\n")
+        if (isTRUE(debug)) cat(sprintf("Starting context: %d with code %s\n", i, context_code[[i]]))
+
+		## Need to return a list here, in the same form as the
+		## "cluster" data structure.
+    	channels[[i]] <- .fastr.channel.create(port)
+		if (isTRUE(debug)) cat(sprintf("Context %d started!\n", i))
+	}
+    contexts <- .fastr.context.spawn(context_code)
+    cl <- vector("list", nnodes)
+	for (i in 1:nnodes) {
+		cl[[i]] <- structure(list(channel = channels[[i]], context=contexts[[i]], rank = i), class = "SHAREDnode")
+	}
+	cl
+}
+
+makeSHAREDcluster <- function(nnodes = getOption("mc.cores", 2L), options = defaultClusterOptions, ...) {
+    nnodes <- as.integer(nnodes)
+    if(is.na(nnodes) || nnodes < 1L) stop("'nnodes' must be >= 1")
+	options <- addClusterOptions(options, list(...))
+
+	# Add the "debug" option defaulted to FALSE, if the user didn't specify
+	# If the user gives TRUE, print extra stuff during cluster setup
+	debug <- FALSE
+	if (exists("debug", envir=options, inherits=FALSE)) {
+		debug <- snow:::getClusterOption("debug", options)
+	} else {
+		options <- snow:::addClusterOptions(options, list(debug = debug))
+	}
+	
+    cl <- newSHAREDnodes(nnodes, debug = debug, options=options)
+	class(cl) <- c("SHAREDcluster", "cluster")
+	cl
+}
+
+stopCluster.SHAREDcluster <- function(cl) {
+    for (n in cl) {
+        snow:::postNode(n, "DONE")
+        .fastr.context.join(n$context)
+    }
+}
+
+## 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("snow"))
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/tools/R/tools_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/tools/R/tools_overrides.R
index 0899b8303b49a63a02bb3669bf319aa373637eab..800d9e30812cd59297e887bdd5699992e6af480d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/tools/R/tools_overrides.R
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/tools/R/tools_overrides.R
@@ -161,5 +161,4 @@ function(dir, outDir)
     parse(outFile)
     invisible()
 }
-
 }), asNamespace("tools"))
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/R/utils_overrides.R b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/R/utils_overrides.R
new file mode 100644
index 0000000000000000000000000000000000000000..038bccdf91fc35c7702aec16a21fc26c53ef4fc8
--- /dev/null
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/utils/R/utils_overrides.R
@@ -0,0 +1,104 @@
+# 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.
+
+eval(expression({
+setBreakpoint <- function (srcfile, line, nameonly = TRUE, envir = parent.frame(), 
+    lastenv, verbose = TRUE, tracer, print = FALSE, clear = FALSE, 
+    ...) 
+{
+    res <- .fastr.setBreakpoint(srcfile, line, clear)
+    if(is.null(res))
+    	res <- structure(list(), class="findLineNumResult")
+    if (verbose) 
+        print(res, steps = !clear)
+}
+}), asNamespace("utils"))
+
+eval(expression({
+help <- function (topic, package = NULL, lib.loc = NULL, verbose = getOption("verbose"), try.all.packages = getOption("help.try.all.packages"), help_type = getOption("help_type")) {
+    types <- c("text", "html", "pdf")
+    if (!missing(package))
+        if (is.name(y <- substitute(package)))
+            package <- as.character(y)
+    if (missing(topic)) {
+        if (!is.null(package)) {
+            help_type <- if (!length(help_type))
+                "text"
+                else match.arg(tolower(help_type), types)
+            if (interactive() && help_type == "html") {
+                port <- tools::startDynamicHelp(NA)
+                if (port <= 0L)
+                  return(library(help = package, lib.loc = lib.loc, character.only = TRUE))
+                browser <- if (.Platform$GUI == "AQUA") {
+                  get("aqua.browser", envir = as.environment("tools:RGUI"))
+                }
+                else getOption("browser")
+                browseURL(paste0("http://127.0.0.1:", port, "/library/", package, "/html/00Index.html"), browser)
+                return(invisible())
+            }
+            else return(library(help = package, lib.loc = lib.loc, character.only = TRUE))
+        }
+        if (!is.null(lib.loc))
+            return(library(lib.loc = lib.loc))
+        topic <- "help"
+        package <- "utils"
+        lib.loc <- .Library
+    }
+    ischar <- tryCatch(is.character(topic) && length(topic) == 1L, error = identity)
+    if (inherits(ischar, "error"))
+        ischar <- FALSE
+    if (!ischar) {
+        reserved <- c("TRUE", "FALSE", "NULL", "Inf", "NaN", "NA", "NA_integer_", "NA_real_", "NA_complex_", "NA_character_")
+        stopic <- deparse(substitute(topic))
+        if (!is.name(substitute(topic)) && !stopic %in% reserved)
+            stop("'topic' should be a name, length-one character vector or reserved word")
+        topic <- stopic
+    }
+    # Fastr >>>>
+    fastrHelpRd <- .fastr.interop.getHelpRd(topic)
+    if (!is.null(fastrHelpRd)) {
+        fastrHelpRd <- tools::parse_Rd(textConnection(fastrHelpRd))
+        cat("==== R Help on ‘", topic, "’ ====\n", sep = "")
+        return(tools::Rd2txt(fastrHelpRd))
+    }
+    # Fastr <<<<
+    help_type <- if (!length(help_type))
+        "text"
+        else match.arg(tolower(help_type), types)
+    paths <- index.search(topic, find.package(if (is.null(package))
+        loadedNamespaces()
+        else package, lib.loc, verbose = verbose))
+    tried_all_packages <- FALSE
+    if (!length(paths) && is.logical(try.all.packages) && !is.na(try.all.packages) && try.all.packages && is.null(package) && is.null(lib.loc)) {
+        for (lib in .libPaths()) {
+            packages <- .packages(TRUE, lib)
+            packages <- packages[is.na(match(packages, .packages()))]
+            paths <- c(paths, index.search(topic, file.path(lib, packages)))
+        }
+        paths <- paths[nzchar(paths)]
+        tried_all_packages <- TRUE
+    }
+    paths <- unique(paths)
+    attributes(paths) <- list(call = match.call(), topic = topic, tried_all_packages = tried_all_packages, type = help_type)
+    class(paths) <- "help_files_with_topic"
+    paths
+}
+}), asNamespace("utils"))
\ No newline at end of file
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNodeTest.java
index ab6890dc71921b4181e468da93ee62f673b80d98..7461c2db64119fac2900b7d4a75528f9bd83a4af 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNodeTest.java
@@ -302,6 +302,6 @@ public class ExtractVectorNodeTest extends TestBase {
 
     private static NodeHandle<ExtractVectorNode> create(ElementAccessMode mode, boolean exact, boolean dropDimension) {
         return createHandle(ExtractVectorNode.create(mode, false),
-                        (node, args) -> node.apply(null, args[0], (Object[]) args[1], RLogical.valueOf(exact), RLogical.valueOf(dropDimension)));
+                        (node, args) -> node.apply(args[0], (Object[]) args[1], RLogical.valueOf(exact), RLogical.valueOf(dropDimension)));
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNodeTest.java
index 063a5f35abfd48880789808d97992b806383e6c8..c24a265ce6875dbf8b7ae9b5be152e2526f4b60c 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNodeTest.java
@@ -298,6 +298,6 @@ public class ReplaceVectorNodeTest extends TestBase {
 
     private static NodeHandle<ReplaceVectorNode> create(ElementAccessMode mode) {
         return createHandle(ReplaceVectorNode.create(mode, false),
-                        (node, args) -> node.apply(null, args[0], (Object[]) args[1], args[2]));
+                        (node, args) -> node.apply(args[0], (Object[]) args[1], args[2]));
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
index 0b68e310c4c02f17aa36a82d62c5418da65a652f..fda59988b92dd86d2a049a7d8f417642bbde717b 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/CastUtils.java
@@ -36,6 +36,7 @@ import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
@@ -324,9 +325,14 @@ public class CastUtils {
             } else {
                 Casts positiveCasts = new Casts(cs.stream().filter(c -> existsConvertibleActualType(actualInputTypes, c.inputType(), true)).collect(Collectors.toList()));
                 TypeExpr positive = positiveCasts.casts().stream().map(c -> TypeExpr.atom(c.resultType())).reduce((res, te) -> res.or(te)).orElse(TypeExpr.NOTHING);
-
-                Casts negativeCasts = new Casts(cs.stream().filter(c -> !positiveCasts.resultTypes().contains(c.resultType()) &&
-                                !existsConvertibleActualType(actualInputTypes, c.inputType(), true)).collect(Collectors.toList()));
+                Casts negativeCasts = new Casts(
+                                cs.stream().filter(c -> !existsConvertibleActualType(actualInputTypes, c.inputType(), true) &&
+                                                // Make sure that the negativeCasts set contains no
+                                                // cast whose return type is
+                                                // convertible to the return type of any cast from
+                                                // the positiveCasts set
+                                                positiveCasts.resultTypes().stream().allMatch(posResTp -> isConvertible(c.resultType(), posResTp, false) == Cast.Coverage.none)).collect(
+                                                                Collectors.toList()));
                 TypeExpr negative = negativeCasts.casts().stream().map(c -> TypeExpr.atom(c.resultType()).not()).reduce((res, te) -> res.and(te)).orElse(TypeExpr.ANYTHING);
 
                 return positive.and(negative);
@@ -388,7 +394,7 @@ public class CastUtils {
         }
 
         public static Casts createCastNodeCasts(Class<?> castNodeClass) {
-            return createCastsFromMethods(castNodeClass, Specialization.class);
+            return createCastsFromMethods(castNodeClass, Specialization.class, Fallback.class);
         }
 
         public static Casts createImplicitCasts() {
@@ -403,8 +409,9 @@ public class CastUtils {
             return new Casts(cs);
         }
 
-        public static Casts createCastsFromMethods(Class<?> clazz, Class<? extends Annotation> annotClass) {
-            List<Method> specs = getAnnotatedMethods(clazz, annotClass);
+        @SafeVarargs
+        public static Casts createCastsFromMethods(Class<?> clazz, Class<? extends Annotation>... annotClasses) {
+            List<Method> specs = getAnnotatedMethods(clazz, annotClasses);
             return new Casts(specs.stream().map(s -> new Cast(s.getParameterTypes()[0], s.getReturnType(), Cast.Coverage.full)).filter(c -> c.rt != Object.class).collect(Collectors.toList()));
         }
 
@@ -445,13 +452,22 @@ public class CastUtils {
         }
     }
 
-    public static List<Method> getAnnotatedMethods(Class<?> clazz, Class<? extends Annotation> annotClass) {
+    @SafeVarargs
+    public static List<Method> getAnnotatedMethods(Class<?> clazz, Class<? extends Annotation>... annotClasses) {
+        List<Method> annotMethList = new ArrayList<>();
+        for (Class<? extends Annotation> annotClass : annotClasses) {
+            annotMethList.addAll(getMethodsAnnotatedBy(clazz, annotClass));
+        }
+        return annotMethList;
+    }
+
+    private static List<Method> getMethodsAnnotatedBy(Class<?> clazz, Class<? extends Annotation> annotClass) {
         List<Method> annotMethList = new ArrayList<>(Arrays.asList(clazz.getDeclaredMethods()).stream().filter(dm -> {
             return dm.getAnnotation(annotClass) != null;
         }).collect(Collectors.toList()));
 
         if (clazz.getSuperclass() != Object.class) {
-            annotMethList.addAll(getAnnotatedMethods(clazz.getSuperclass(), annotClass));
+            annotMethList.addAll(getMethodsAnnotatedBy(clazz.getSuperclass(), annotClass));
         }
 
         return annotMethList;
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
index f68d4c13316cf162a85e463ecc718943486562e5..ae586797e841073045b5d473c304ea22975dc5ee 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/MarkLookup.java
@@ -234,5 +234,4 @@ public final class MarkLookup implements PipelineStepVisitor<Map<String, Object>
     public Map<String, Object> visit(MapToCharAt mapper, Map<String, Object> foundMarks) {
         return visitMapper(mapper, foundMarks);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
index 28d9ff8fff17fa4111c989f2922807e5896b068c..e0a147f0510293357274b01bd11dfa0116b55805 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/Not.java
@@ -74,7 +74,6 @@ public final class Not<T> implements Type, TypeAndInstanceCheck {
         if (isNegative(t)) {
             return getPositiveType(t);
         } else {
-            assert t instanceof Class;
             return new Not<>(t);
         }
     }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
index 782929e761a47fd0745e6ebbd48e365cb08c76cb..e95228ece265512befb8542b6165b1afe64752fe 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/ResultTypesAnalyser.java
@@ -416,5 +416,4 @@ public class ResultTypesAnalyser extends ExecutionPathVisitor<TypeExpr> implemen
     public TypeExpr visit(Dim dim, byte operation, TypeExpr previous) {
         return previous.and(NOT_NULL_NOT_MISSING);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
index e4a2b528cbb42b3328d75dfffc8351583a5d2a0f..7318fc93e76a730860ec878c60f210eab449b95e 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/SamplesCollector.java
@@ -458,5 +458,4 @@ public class SamplesCollector extends ExecutionPathVisitor<Consumer<Object>>
             this.size = size;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
index 9b512143f74f997f6f45efe9cf6276c6a1729a0d..400b54cc0e1517c9ea9a477da8fe39c7dd670d18 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TestCasts.java
@@ -53,12 +53,13 @@ import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.test.TestBase;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -82,13 +83,17 @@ public class TestCasts extends TestBase {
         private boolean isCompiled = false;
         @Child protected T node;
 
-        @SuppressWarnings("deprecation")
         protected TestRootNode(String name, T node) {
-            super(RContext.getRForeignAccessFactory().getTruffleLanguage(), RSyntaxNode.INTERNAL, descriptor);
+            super(TruffleRLanguageImpl.getCurrentLanguage(), descriptor);
             this.name = name;
             this.node = node;
         }
 
+        @Override
+        public SourceSection getSourceSection() {
+            return RSyntaxNode.INTERNAL;
+        }
+
         @Override
         public Object execute(VirtualFrame frame) {
             Object result = execute(frame, frame.getArguments()[0]);
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
index e5b115a5532ef8067afba1a5de1bbdc17c4e479b..30958f319aef093dfbc81d3e67c61f0c32d95c46 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/TypeAndInstanceCheck.java
@@ -49,9 +49,6 @@ public interface TypeAndInstanceCheck {
     Type normalize();
 
     static Coverage coverage(Type from, Type to, boolean includeImplicits) {
-        assert (from instanceof Not || from instanceof Class);
-        assert (to instanceof Not || to instanceof Class);
-
         if (Not.negateType(to).equals(from)) {
             return Coverage.none;
         }
@@ -94,6 +91,5 @@ public interface TypeAndInstanceCheck {
 
             return positiveCoverage.transpose(positiveFromCls, positiveToCls, fromPositive, toPositive);
         }
-
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
index f7475baa48f56cf224f344fb83d2ef52f56e4cbd..e4c03aa42f6a7a6c94816f336c0e7d94b12512c3 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/casts/UpperBoundsConjunction.java
@@ -117,7 +117,6 @@ public final class UpperBoundsConjunction implements WildcardType, TypeAndInstan
     }
 
     public Coverage coverageTo(Type to, boolean includeImplicits) {
-        assert to instanceof Not || to instanceof Class;
         return adjustCoverageTo(upperBounds.stream().map(ubt -> {
             return TypeAndInstanceCheck.coverage(ubt, to, includeImplicits);
         }).reduce((res, cvg) -> res == Coverage.none || cvg == Coverage.none ? Coverage.none : cvg.or(res)).orElse(Coverage.none));
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
index 1ae687272d0a714a1bcd32daf5b71b7d34606d71..817a66144fcecafb1cae808b9baca46ef9f8692a 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/CastBuilderTest.java
@@ -22,6 +22,8 @@
  */
 package com.oracle.truffle.r.nodes.castsTests;
 
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.abstractVectorValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.anyValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.asBoolean;
@@ -61,6 +63,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.rawValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.shouldBe;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.singleElement;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix;
@@ -101,11 +104,15 @@ 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.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.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.REnvironment.NewEnv;
+import com.oracle.truffle.r.test.generate.FastRSession;
+import java.util.Arrays;
+import java.util.List;
 
 /**
  * Tests the cast pipelines and also that the samples generation process matches the intended
@@ -125,7 +132,10 @@ public class CastBuilderTest {
     private CastNode castNode;
     private PreinitialPhaseBuilder arg;
 
+    private static FastRSession fastRSession;
+
     static {
+        fastRSession = FastRSession.create();
         CastNode.testingMode();
     }
 
@@ -887,12 +897,47 @@ public class CastBuilderTest {
         testPipeline();
     }
 
+    @Test
+    public void testIntOrRawPassing() {
+        arg.mustNotBeNull().mustBe(integerValue().or(rawValue()));
+        assertCastPreserves(1);
+        assertCastPreserves(RDataFactory.createIntVector(new int[]{1, 2}, true));
+        assertCastPreserves(RDataFactory.createRaw((byte) 2));
+        assertCastPreserves(RDataFactory.createRawVector(new byte[]{1, 2}));
+        assertCastFail(RNull.instance);
+        assertCastFail("abc");
+    }
+
+    @Test
+    public void testCastForeignArray() {
+        arg.mustBe(integerValue());
+        int[] array = new int[]{1, 2, 3};
+        Object value = cast(JavaInterop.asTruffleObject(array));
+        assertTrue(value instanceof RAbstractIntVector);
+    }
+
+    @Test
+    public void testCastJavaIterable() {
+        arg.mustBe(integerValue());
+        List<Integer> list = Arrays.asList(1, 2, 3);
+        Object value = cast(JavaInterop.asTruffleObject(list));
+        assertTrue(value instanceof RAbstractIntVector);
+    }
+
+    @Test
+    public void testCastForeignObjectDisabled() {
+        arg.castForeignObjects(false).mustBe(missingValue().not());
+        TruffleObject obj = JavaInterop.asTruffleObject(new int[]{1, 2, 3});
+        Object value = cast(obj);
+        assertTrue(value == obj);
+    }
+
     /**
      * Casts given object using the configured pipeline in {@link #arg}.
      */
     private Object cast(Object a) {
         CastNode.clearLastWarning();
-        NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(getCastNode(), (node, args) -> node.doCast(args[0]));
+        NodeHandle<CastNode> argCastNodeHandle = TestUtilities.createHandle(getCastNode(), (node, args) -> node.doCast(args[0]), fastRSession.getContext().getLanguage());
         return argCastNodeHandle.call(a);
     }
 
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
index 3cfa577f864115872c0ad8d9f93ce70677ce63d8..47670c9a92b000884ebb89f41e9dd2c5295f4e72 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/ResultTypesAnalyserTest.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.castsTests;
 
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
-import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicIntegerValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.atomicLogicalValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.chain;
@@ -32,6 +30,7 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.constant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.dimEq;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleToInt;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.elementAt;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.eq;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.intNA;
@@ -43,14 +42,15 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.mapIf;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.matrix;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.not;
+import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullConstant;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.squareMatrix;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue;
 import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean;
-import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom;
 import static com.oracle.truffle.r.nodes.casts.MarkLookup.mark;
+import static com.oracle.truffle.r.nodes.casts.TypeExpr.atom;
 
 import java.lang.reflect.Type;
 import java.util.Map;
@@ -71,7 +71,6 @@ import com.oracle.truffle.r.nodes.casts.TypeExpr;
 import com.oracle.truffle.r.nodes.castsTests.CastBuilderTest.DummyBuiltin;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
-import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
@@ -121,14 +120,13 @@ public class ResultTypesAnalyserTest {
     @Test
     public void testAsIntegerVector() {
         arg.asIntegerVector();
-        assertTypes(RNull.class, RMissing.class, int.class, RIntSequence.class, RIntVector.class);
+        assertTypes(RNull.class, RMissing.class, int.class, RIntSequence.class, RIntVector.class, RAbstractIntVector.class);
     }
 
     @Test
     public void testAsLogicalVector() {
         arg.asLogicalVector();
-        assertTypes(RNull.class, RMissing.class, byte.class, RLogicalVector.class,
-                        RArgsValuesAndNames.class);
+        assertTypes(RNull.class, RMissing.class, byte.class, RLogicalVector.class);
     }
 
     @Test
@@ -438,7 +436,7 @@ public class ResultTypesAnalyserTest {
     @Test
     public void testReturnIf2() {
         arg.returnIf(nullValue(), emptyIntegerVector()).returnIf(missingValue(), emptyIntegerVector()).asIntegerVector();
-        assertTypes(atom(int.class).or(atom(RIntSequence.class)).or(atom(RIntVector.class)), true);
+        assertTypes(atom(int.class).or(atom(RAbstractIntVector.class)).or(atom(RIntSequence.class)).or(atom(RIntVector.class)), true);
     }
 
     @Test
@@ -505,5 +503,4 @@ public class ResultTypesAnalyserTest {
         Assert.assertNotNull(result.get(mark));
         return result.get(mark);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
index 38f3f15c260a340b239dd0f24d2b5aaba0cc0944..b65aeb69feba61a6014fec96687784b0130bcdbd 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/castsTests/SampleCollectorTest.java
@@ -470,7 +470,6 @@ public class SampleCollectorTest {
             Set<Object> samples = (Set<Object>) item;
             return samples.stream().filter(s -> s instanceof String && s.toString().length() == expectedLength).findAny().isPresent();
         }
-
     }
 
     static final class VectorSizeMatcher extends CustomMatcher<Set<Object>> {
@@ -490,7 +489,6 @@ public class SampleCollectorTest {
             Set<Object> samples = (Set<Object>) item;
             return samples.stream().filter(s -> s instanceof RAbstractVector && ((RAbstractVector) s).getRType() == type && ((RAbstractVector) s).getLength() == expectedSize).findAny().isPresent();
         }
-
     }
 
     static final class VectorMatcher extends CustomMatcher<Set<Object>> {
@@ -530,6 +528,5 @@ public class SampleCollectorTest {
             }
             return false;
         }
-
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
index 809bf71bdebc1e335c4e84b0003c4ee3940b5730..bd4a571e6d9cffc765558f12e16526f9634a202e 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ChimneySweeping.java
@@ -227,7 +227,7 @@ class ChimneySweeping extends SingleBuiltinDiagnostics {
 
         this.castNodes = builtinFactory.getCastNodes();
 
-        print(0, "\n*** Chimney-sweeping of '" + builtinName + "' (" + builtinFactory.getBuiltinNodeClass().getName() + ") ***");
+        print(0, "\n*** Chimney-sweeping of '" + builtinName + "' (" + builtinFactory.getBuiltinMetaClass().getName() + ") ***");
 
         this.validArgsList = extractValidArgsForBuiltin();
         this.argSamples = createSamples();
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
index e422add155b3d2649d376645b7674fc56ef37b9b..c2ca8febb60c954191d495d4aed892cb9c8373de 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/ForwardedValuesAnalyserTest.java
@@ -429,5 +429,4 @@ public class ForwardedValuesAnalyserTest {
         assertTrue(result.isStringForwarded());
         assertTrue(result.isMissingForwarded());
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
index 444a877bf6a11d8a738e66673aebfcae3bd9d489..076b9cce21dc530e40ba989bd77d7d2cdffc1bd2 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/PipelineToCastNodeTests.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.test;
 
+import com.oracle.truffle.r.nodes.builtin.casts.CastForeignNode;
 import static junit.framework.TestCase.assertTrue;
 import static org.junit.Assert.assertEquals;
 
@@ -52,27 +53,59 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
 public class PipelineToCastNodeTests {
     @Test
     public void asLogicalVector() {
-        assertTrue(createPipeline(new CoercionStep<>(RType.Logical, false)) instanceof CastLogicalBaseNode);
+        // without first cast of foreign objects
+        CastNode pipeline = createPipeline(new CoercionStep<>(RType.Logical, false), false);
+        assertTrue(pipeline instanceof CastLogicalBaseNode);
+
+        // with first cast of foreign objects
+        pipeline = createPipeline(new CoercionStep<>(RType.Logical, false), true);
+        assertChainedCast(pipeline, CastForeignNode.class, CastLogicalBaseNode.class);
     }
 
     @Test
     public void asStringVectorFindFirst() {
-        assertChainedCast(createPipeline(new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null))), CastStringBaseNode.class, FindFirstNode.class);
-        FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) createPipeline(
-                        new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null)))).getSecondCast();
+        PipelineStep<?, ?> steps = new CoercionStep<>(RType.Character, false).setNext(new FindFirstStep<>("hello", String.class, null));
+
+        // without first cast of foreign objects
+        CastNode pipeline = createPipeline(steps, false);
+        assertChainedCast(pipeline, CastStringBaseNode.class, FindFirstNode.class);
+
+        FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) pipeline).getSecondCast();
         assertEquals("hello", findFirst.getDefaultValue());
+
+        // with first cast of foreign objects
+        pipeline = createPipeline(steps, true);
+        assertChainedCast(pipeline, ChainedCastNode.class, FindFirstNode.class);
+
+        CastNode next = ((ChainedCastNode) pipeline).getFirstCast();
+        assertChainedCast(next, CastForeignNode.class, CastStringBaseNode.class);
     }
 
     @Test
     public void mustBeREnvironmentAsIntegerVectorFindFirst() {
-        assertChainedCast(createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext(
-                        new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null)))), ChainedCastNode.class, FindFirstNode.class);
-        CastNode next = ((ChainedCastNode) createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext(
-                        new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null))))).getFirstCast();
+        PipelineStep<?, ?> steps = new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext(
+                        new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null)));
+
+        // without first cast of foreign objects
+        CastNode pipeline = createPipeline(steps, false);
+
+        assertChainedCast(pipeline, ChainedCastNode.class, FindFirstNode.class);
+        CastNode next = ((ChainedCastNode) pipeline).getFirstCast();
         assertChainedCast(next, FilterNode.class, CastIntegerBaseNode.class);
-        FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) createPipeline(new FilterStep<>(new TypeFilter<>(REnvironment.class), null, false).setNext(
-                        new CoercionStep<>(RType.Integer, false).setNext(new FindFirstStep<>("hello", String.class, null))))).getSecondCast();
+
+        FindFirstNode findFirst = (FindFirstNode) ((ChainedCastNode) pipeline).getSecondCast();
         assertEquals("hello", findFirst.getDefaultValue());
+
+        // with first cast of foreign objects
+        pipeline = createPipeline(steps, true);
+        assertChainedCast(pipeline, ChainedCastNode.class, FindFirstNode.class);
+
+        next = ((ChainedCastNode) pipeline).getFirstCast();
+        assertChainedCast(next, ChainedCastNode.class, CastIntegerBaseNode.class);
+
+        next = ((ChainedCastNode) next).getFirstCast();
+        assertChainedCast(next, CastForeignNode.class, FilterNode.class);
+
     }
 
     private static void assertChainedCast(CastNode node, Class<?> expectedFirst, Class<?> expectedSecond) {
@@ -81,9 +114,10 @@ public class PipelineToCastNodeTests {
         assertTrue(expectedSecond.isInstance(((ChainedCastNode) node).getSecondCast()));
     }
 
-    private static CastNode createPipeline(PipelineStep<?, ?> lastStep) {
+    private static CastNode createPipeline(PipelineStep<?, ?> lastStep, boolean castForeign) {
         PipelineConfigBuilder configBuilder = new PipelineConfigBuilder("x");
         configBuilder.setValueForwarding(false);
+        configBuilder.setCastForeignObjects(castForeign);
         return PipelineToCastNode.convert(configBuilder.build(), lastStep, ForwardingAnalysisResult.INVALID);
     }
 }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
index 2fce7678ee125b824b806395b3ff792a41d5ca73..38e550221e20a608ba3bf465fb949aa334564925 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/RBuiltinDiagnostics.java
@@ -38,6 +38,7 @@ import java.util.Set;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
 
+import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.GeneratedBy;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.Frame;
@@ -252,7 +253,7 @@ public class RBuiltinDiagnostics {
     }
 
     private static RBuiltinFactory findBuiltInFactory(Class<?> bltnCls, BasePackage bp) {
-        Optional<RBuiltinFactory> bltnFact = bp.getBuiltins().values().stream().filter(bf -> bf.getBuiltinNodeClass().isAssignableFrom(bltnCls)).findFirst();
+        Optional<RBuiltinFactory> bltnFact = bp.getBuiltins().values().stream().filter(bf -> bf.getBuiltinMetaClass().isAssignableFrom(bltnCls)).findFirst();
         if (bltnFact.isPresent()) {
             return bltnFact.get();
         } else {
@@ -359,24 +360,26 @@ public class RBuiltinDiagnostics {
         }
 
         SingleBuiltinDiagnostics init() throws Throwable {
-            String builtinClassName = builtinFactory.getBuiltinNodeClass().getName();
+            String builtinMetaClassName = builtinFactory.getBuiltinMetaClass().getName();
             // causes the invocation of the static initializer in the builtin node class
+            Class<?> bltnMetaCls = NodeWithArgumentCasts.Casts.getBuiltinClass(Class.forName(builtinMetaClassName));
+            String builtinClassName = builtinFactory.getBuiltinNodeClass().getName();
             Class<?> bltnCls = NodeWithArgumentCasts.Casts.getBuiltinClass(Class.forName(builtinClassName));
 
             try {
                 this.casts = builtinFactory.getCasts();
             } catch (RInternalError e) {
                 // It will be converted into an error after all builtins are fixed
-                throw new WarningException("Builtin " + builtinClassName + " should declare argument casts or use Casts.noCasts(" + bltnCls.getSimpleName() + ".class)");
+                throw new WarningException("Builtin " + builtinMetaClassName + " should declare argument casts or use Casts.noCasts(" + bltnMetaCls.getSimpleName() + ".class)");
             }
 
             if (this.casts == null || this.casts.declaresNoCasts()) {
-                throw new InfoException("Builtin " + builtinClassName + " has no-casts");
+                throw new InfoException("Builtin " + builtinMetaClassName + " has no-casts");
             }
 
             argResultSets = createArgResultSets();
 
-            List<Method> specs = CastUtils.getAnnotatedMethods(builtinFactory.getBuiltinNodeClass(), Specialization.class);
+            List<Method> specs = CastUtils.getAnnotatedMethods(bltnCls, Specialization.class, Fallback.class);
             this.specMethods = new ArrayList<>(specs);
             // N.B. The fallback method cannot be found by the Fallback annotation since
             // this annotation has the CLASS retention policy. Nonetheless, the fallback method can
@@ -459,7 +462,7 @@ public class RBuiltinDiagnostics {
             if (!headerPrinted && level <= diagSuite.diagConfig.outputMaxLevel) {
                 diagSuite.print(level, "\n");
                 diagSuite.print(level, "****************************************************************************");
-                diagSuite.print(level, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinNodeClass().getCanonicalName() + ")");
+                diagSuite.print(level, "Builtin: " + builtinName + " (" + builtinFactory.getBuiltinMetaClass().getCanonicalName() + ")");
                 diagSuite.print(level, "****************************************************************************");
                 headerPrinted = true;
                 diagSuite.reportedBuiltinsCounter++;
@@ -571,7 +574,6 @@ public class RBuiltinDiagnostics {
                                 te = te.and(rmissingType.not());
                             }
                         }
-
                     }
                 } catch (Exception e) {
                     throw new RuntimeException("Cannot create sampler for argument " + parameterNames[i], e);
@@ -654,6 +656,8 @@ public class RBuiltinDiagnostics {
 
         Class<?> getBuiltinNodeClass();
 
+        Class<?> getBuiltinMetaClass();
+
         String[] getParameterNames();
 
         Object[] getDefaultParameterValues();
@@ -687,13 +691,18 @@ public class RBuiltinDiagnostics {
             return fact.getBuiltinNodeClass();
         }
 
+        @Override
+        public Class<?> getBuiltinMetaClass() {
+            return fact.getBuiltinMetaClass();
+        }
+
         public RBuiltinKind getBuiltinKind() {
             return fact.getKind();
         }
 
         @Override
         public String[] getParameterNames() {
-            RBuiltin annotation = fact.getBuiltinNodeClass().getAnnotation(RBuiltin.class);
+            RBuiltin annotation = fact.getBuiltinMetaClass().getAnnotation(RBuiltin.class);
             String[] pn = annotation.parameterNames();
             return Arrays.stream(pn).map(n -> n.isEmpty() ? null : n).toArray(String[]::new);
         }
@@ -705,7 +714,11 @@ public class RBuiltinDiagnostics {
 
         @Override
         public NodeWithArgumentCasts.Casts getCasts() {
-            return NodeWithArgumentCasts.Casts.getCasts(fact.getBuiltinNodeClass());
+            try {
+                return NodeWithArgumentCasts.Casts.getCasts(fact.getBuiltinMetaClass());
+            } catch (RInternalError e) {
+                return NodeWithArgumentCasts.Casts.getCasts(fact.getBuiltinNodeClass());
+            }
         }
 
         @Override
@@ -759,6 +772,11 @@ public class RBuiltinDiagnostics {
             return nodeClass;
         }
 
+        @Override
+        public Class<?> getBuiltinMetaClass() {
+            return nodeClass;
+        }
+
         @Override
         public String[] getParameterNames() {
             return parameterNames;
@@ -775,7 +793,7 @@ public class RBuiltinDiagnostics {
 
         @Override
         public NodeWithArgumentCasts.Casts getCasts() {
-            return NodeWithArgumentCasts.Casts.getCasts(getBuiltinNodeClass());
+            return NodeWithArgumentCasts.Casts.getCasts(getBuiltinMetaClass());
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
index ae709c5c8b51eb5655f9229e11cd69f35f90eb9b..5c254881f4a0f3a4297d47eaa84b00e5b36427b0 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
@@ -26,17 +26,15 @@ import org.junit.Assert;
 import org.junit.Test;
 
 import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.r.engine.TruffleRLanguage;
+import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RootWithBody;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
@@ -186,8 +184,8 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("a <- c(1,2,3,4)", "a[0]", 1, 0, 1, 0);
         assertCallCounts("a <- c(1,2,3,4); b <- -1", "a[b]", 1, 0, 1, 0);
         assertCallCounts("a <- c(1,2,3,4)", "a[NA_integer_]", 1, 0, 1, 0);
+        assertCallCounts("a <- c(1,2,3,4)", "a[-1]", 2, 0, 2, 0);
 
-        assertCallCounts("a <- c(1,2,3,4)", "a[-1]", 0, 2, 0, 2); // "-1" is a unary expression
         assertCallCounts("a <- c(1,2,3,4)", "a[drop=T, 1]", 0, 1, 0, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[drop=F, 1]", 0, 1, 0, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[1, drop=F]", 0, 1, 0, 1);
@@ -223,7 +221,7 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("a <- c(1,2,3,4); b <- -1", "a[b] <- 1", 1, 0, 1, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[NA_integer_] <- 1", 1, 0, 1, 1);
 
-        assertCallCounts("a <- c(1,2,3,4)", "a[-1] <- 1", 0, 2, 0, 3); // "-1" is a unary expression
+        assertCallCounts("a <- c(1,2,3,4)", "a[-1] <- 1", 2, 0, 2, 1);
         assertCallCounts("a <- c(1,2,3,4)", "a[drop=T, 1] <- 1", 0, 1, 0, 2);
         assertCallCounts("a <- c(1,2,3,4)", "a[drop=F, 1] <- 1", 0, 1, 0, 2);
         assertCallCounts("a <- c(1,2,3,4)", "a[1, drop=F] <- 1", 0, 1, 0, 2);
@@ -254,20 +252,19 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("a <- 1", "('asdf')", 1, 0, 1, 0);
         assertCallCounts("a <- 1; b <- 2", "(a + b)", 2, 0, 2, 0);
         assertCallCounts("a <- 1; b <- 2; c <- 3", "a + (b + c)", 3, 0, 3, 0);
-        assertCallCounts("a <- 1; b <- 2; c <- 1:5", "a + (b + c)", 3, 0, 0, 3);
+        assertCallCounts("a <- 1; b <- 2; c <- 1:5", "a + (b + c)", 3, 0, 3, 0);
     }
 
     private static void assertCallCounts(String test, int initialSpecialCount, int initialNormalCount, int finalSpecialCount, int finalNormalCount) {
         assertCallCounts("{}", test, initialSpecialCount, initialNormalCount, finalSpecialCount, finalNormalCount);
     }
 
-    @SuppressWarnings("try")
     private static void assertCallCounts(String setup, String test, int initialSpecialCount, int initialNormalCount, int finalSpecialCount, int finalNormalCount) {
         if (!FastROptions.UseSpecials.getBooleanValue()) {
             return;
         }
-        Source setupSource = Source.newBuilder("{" + setup + "}").mimeType(TruffleRLanguage.MIME).name("test").build();
-        Source testSource = Source.newBuilder(test).mimeType(TruffleRLanguage.MIME).name("test").build();
+        Source setupSource = Source.newBuilder("{" + setup + "}").mimeType(TruffleRLanguageImpl.MIME).name("test").build();
+        Source testSource = Source.newBuilder(test).mimeType(TruffleRLanguageImpl.MIME).name("test").build();
 
         RExpression setupExpression = testVMContext.getThisEngine().parse(setupSource);
         RExpression testExpression = testVMContext.getThisEngine().parse(testSource);
@@ -276,14 +273,15 @@ public class SpecialCallTest extends TestBase {
         RootCallTarget setupCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) setupExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test");
         RootCallTarget testCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) testExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test");
 
-        try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) {
+        try {
             CountCallsVisitor count1 = new CountCallsVisitor(testCallTarget);
             Assert.assertEquals("initial special call count '" + setup + "; " + test + "': ", initialSpecialCount, count1.special);
             Assert.assertEquals("initial normal call count '" + setup + "; " + test + "': ", initialNormalCount, count1.normal);
 
+            MaterializedFrame frame = TestBase.testVMContext.stateREnvironment.getGlobalFrame();
             try {
-                setupCallTarget.call(REnvironment.globalEnv().getFrame());
-                testCallTarget.call(REnvironment.globalEnv().getFrame());
+                setupCallTarget.call(frame);
+                testCallTarget.call(frame);
             } catch (RError e) {
                 // ignore
             }
@@ -293,8 +291,8 @@ public class SpecialCallTest extends TestBase {
             Assert.assertEquals("normal call count after first call '" + setup + "; " + test + "': ", finalNormalCount, count2.normal);
 
             try {
-                setupCallTarget.call(REnvironment.globalEnv().getFrame());
-                testCallTarget.call(REnvironment.globalEnv().getFrame());
+                setupCallTarget.call(frame);
+                testCallTarget.call(frame);
             } catch (RError e) {
                 // ignore
             }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
index 819cf8c85c13abb4ce3c2438edfd1ef9641e88d3..17af249bd3ec7505813672ff1eca0f11d8cfc6e2 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
@@ -26,22 +26,23 @@ import java.util.function.Supplier;
 
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.ReturnException;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
 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.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public class TestUtilities {
 
@@ -158,11 +159,8 @@ public class TestUtilities {
      * Certain code needs to be run within valid RContext, e.g. copying, which tries to report to
      * memory tracer taken from RContext.
      */
-    @SuppressWarnings("try")
     public static <T> T withinTestContext(Supplier<T> action) {
-        try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) {
-            return action.get();
-        }
+        return action.get();
     }
 
     /**
@@ -173,6 +171,10 @@ public class TestUtilities {
         return new NodeHandle<>(Truffle.getRuntime().createCallTarget(new TestRoot<>(node, invoke)));
     }
 
+    public static <T extends Node> NodeHandle<T> createHandle(T node, NodeAdapter<T> invoke, TruffleRLanguage language) {
+        return new NodeHandle<>(Truffle.getRuntime().createCallTarget(new TestRoot<>(node, invoke, language)));
+    }
+
     public interface NodeAdapter<T extends Node> {
 
         Object invoke(T node, Object... args);
@@ -196,11 +198,8 @@ public class TestUtilities {
             return ((TestRoot<T>) target.getRootNode()).node;
         }
 
-        @SuppressWarnings("try")
         public Object call(Object... args) {
-            try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) {
-                return target.call(RArguments.createUnitialized((Object) args));
-            }
+            return target.call(RArguments.createUnitialized((Object) args));
         }
     }
 
@@ -209,13 +208,21 @@ public class TestUtilities {
         private final NodeAdapter<T> invoke;
         @Child private T node;
 
-        @SuppressWarnings("deprecation")
         TestRoot(T node, NodeAdapter<T> invoke) {
-            super(TruffleLanguage.class, null, null);
+            this(node, invoke, TruffleRLanguageImpl.getCurrentLanguage());
+        }
+
+        TestRoot(T node, NodeAdapter<T> invoke, TruffleRLanguage language) {
+            super(language);
             this.node = node;
             this.invoke = invoke;
         }
 
+        @Override
+        public SourceSection getSourceSection() {
+            return RSyntaxNode.INTERNAL;
+        }
+
         @Override
         public Object execute(VirtualFrame frame) {
             try {
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
index c575efa26a681a498bc5253cb5fe78ff1281aacc..ffee9580cf61c3e3f9b117dc0bc13fe7d8802efa 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/UnaryArithmeticNodeTest.java
@@ -52,7 +52,7 @@ import org.junit.runner.RunWith;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.r.nodes.builtin.base.Ceiling;
 import com.oracle.truffle.r.nodes.builtin.base.Floor;
-import com.oracle.truffle.r.nodes.builtin.base.Round;
+import com.oracle.truffle.r.nodes.builtin.base.Trunc;
 import com.oracle.truffle.r.nodes.test.TestUtilities.NodeHandle;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
@@ -64,6 +64,7 @@ import com.oracle.truffle.r.runtime.data.RSequence;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
 /**
@@ -77,7 +78,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
         // to make sure this file is recognized as a test
     }
 
-    public static final UnaryArithmeticFactory[] ALL = new UnaryArithmeticFactory[]{NEGATE, Round.ROUND, Floor.FLOOR, Ceiling.CEILING, PLUS};
+    public static final UnaryArithmeticFactory[] ALL = new UnaryArithmeticFactory[]{NEGATE, PLUS, Floor.FLOOR, Ceiling.CEILING, Trunc.TRUNC};
 
     @DataPoints public static final UnaryArithmeticFactory[] UNARY = ALL;
 
@@ -100,7 +101,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
         // sharing does not work if a is a scalar vector
         assumeThat(true, is(isShareable(operand, operand.getRType())));
 
-        RType resultType = getArgumentType(operand);
+        RType resultType = getArgumentType(factory, operand);
         Object sharedResult = null;
         if (isShareable(operand, resultType)) {
             sharedResult = operand;
@@ -161,7 +162,7 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
     public void testPlusFolding(RAbstractVector originalOperand) {
         RAbstractVector operand = copy(originalOperand);
         assumeThat(operand, is(not(instanceOf(RScalarVector.class))));
-        if (operand.getRType() == getArgumentType(operand)) {
+        if (operand.getRType() == getArgumentType(PLUS, operand)) {
             assertFold(true, operand, PLUS);
         } else {
             assertFold(false, operand, PLUS);
@@ -172,8 +173,8 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
     public void testSequenceFolding() {
         assertFold(true, createIntSequence(1, 3, 10), NEGATE);
         assertFold(true, createDoubleSequence(1, 3, 10), NEGATE);
-        assertFold(false, createIntSequence(1, 3, 10), Round.ROUND, Floor.FLOOR, Ceiling.CEILING);
-        assertFold(false, createDoubleSequence(1, 3, 10), Round.ROUND, Floor.FLOOR, Ceiling.CEILING);
+        assertFold(false, createIntSequence(1, 3, 10), Floor.FLOOR, Ceiling.CEILING);
+        assertFold(false, createDoubleSequence(1, 3, 10), Floor.FLOOR, Ceiling.CEILING);
     }
 
     @Theory
@@ -206,8 +207,9 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
         Assert.assertEquals(expectedAttributes, foundAttributes);
     }
 
-    private static RType getArgumentType(RAbstractVector operand) {
-        return RType.maxPrecedence(RType.Integer, operand.getRType());
+    private static RType getArgumentType(UnaryArithmeticFactory factory, RAbstractVector operand) {
+        UnaryArithmetic operation = factory.createOperation();
+        return operation.calculateResultType(RType.maxPrecedence(operation.getMinPrecedence(), operand.getRType()));
     }
 
     private static boolean isPrimitive(Object result) {
@@ -248,7 +250,6 @@ public class UnaryArithmeticNodeTest extends BinaryVectorTest {
     }
 
     private static NodeHandle<UnaryArithmeticNode> create(UnaryArithmeticFactory factory) {
-        return createHandle(UnaryArithmeticNodeGen.create(factory, null),
-                        (node, args) -> node.execute(args[0]));
+        return createHandle(UnaryArithmeticNodeGen.create(factory), (node, args) -> node.execute(args[0]));
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
index dd1255b68606e69de86c042c828f648d2f3bda96..c9b15ec27b5268dd74c9d2c14a40db624595a001 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -63,6 +63,7 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RShareable;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -123,9 +124,9 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
                         boolean switchArgs = "->".equals(symbol) || "->>".equals(symbol);
                         // fix the operators while keeping the correct source sections
                         if ("->>".equals(symbol)) {
-                            lhsLookup = ReadVariableNode.createForcedFunctionLookup(lhs.getLazySourceSection(), "<<-");
+                            lhsLookup = (RSyntaxLookup) ReadVariableNode.wrap(lhs.getLazySourceSection(), ReadVariableNode.createForcedFunctionLookup("<<-"));
                         } else if ("->".equals(symbol)) {
-                            lhsLookup = ReadVariableNode.createForcedFunctionLookup(lhs.getLazySourceSection(), "<-");
+                            lhsLookup = (RSyntaxLookup) ReadVariableNode.wrap(lhs.getLazySourceSection(), ReadVariableNode.createForcedFunctionLookup("<-"));
                         }
                         // switch the args if needed
                         RSyntaxNode lhsArg = args.get(switchArgs ? 1 : 0).value;
@@ -233,14 +234,14 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
     }
 
     @Override
-    public RSyntaxNode function(SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, Object assignedTo) {
+    public RSyntaxNode function(TruffleRLanguage language, SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, Object assignedTo) {
         String description = getFunctionDescription(source, assignedTo);
-        RootCallTarget callTarget = rootFunction(source, params, body, description);
+        RootCallTarget callTarget = rootFunction(language, source, params, body, description);
         return FunctionExpressionNode.create(source, callTarget);
     }
 
     @Override
-    public RootCallTarget rootFunction(SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, String name) {
+    public RootCallTarget rootFunction(TruffleRLanguage language, SourceSection source, List<Argument<RSyntaxNode>> params, RSyntaxNode body, String name) {
         // Parse argument list
         RNode[] defaultValues = new RNode[params.size()];
         SaveArgumentsNode saveArguments;
@@ -287,7 +288,7 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
 
         FrameDescriptor descriptor = new FrameDescriptor();
         FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(name != null && !name.isEmpty() ? name : "<function>", descriptor);
-        FunctionDefinitionNode rootNode = FunctionDefinitionNode.create(source, descriptor, argSourceSections, saveArguments, body, formals, name, argPostProcess);
+        FunctionDefinitionNode rootNode = FunctionDefinitionNode.create(language, source, descriptor, argSourceSections, saveArguments, body, formals, name, argPostProcess);
 
         if (FastROptions.ForceSources.getBooleanValue()) {
             // forces source sections to be generated
@@ -342,6 +343,6 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> {
                 return new ReadVariadicComponentNode(source, index > 0 ? index - 1 : index);
             }
         }
-        return functionLookup ? ReadVariableNode.createForcedFunctionLookup(source, symbol) : ReadVariableNode.create(source, symbol, false);
+        return ReadVariableNode.wrap(source, functionLookup ? ReadVariableNode.createForcedFunctionLookup(symbol) : ReadVariableNode.create(symbol));
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
index 2b3bbc78a7ea4c918f19177824499d8017c458da..5d556ba0bbbeda8b73eb0074c65075ebdc423497 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.r.nodes.function.RCallSpecialNode;
 import com.oracle.truffle.r.nodes.function.WrapArgumentBaseNode;
 import com.oracle.truffle.r.nodes.function.WrapArgumentNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
-import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -61,7 +60,11 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 /**
  * A collection of useful methods for working with {@code AST} instances.
  */
-public class RASTUtils {
+public final class RASTUtils {
+
+    private RASTUtils() {
+        // no instances
+    }
 
     /**
      * Central location for all node cloning operations, in preference to {@link NodeUtil#cloneNode}
@@ -121,14 +124,6 @@ public class RASTUtils {
         return element instanceof RSyntaxLookup && identifier.equals(((RSyntaxLookup) element).getIdentifier());
     }
 
-    /**
-     * Creates a standard {@link ReadVariableNode}.
-     */
-    @TruffleBoundary
-    public static RSyntaxNode createReadVariableNode(String name) {
-        return RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, name, false);
-    }
-
     /**
      * Handles constants and symbols as special cases as required by R: create symbols for simple
      * variables and actual values for constants.
@@ -227,22 +222,4 @@ public class RASTUtils {
         SourceSection sourceSection = sourceUnavailable ? RSyntaxNode.SOURCE_UNAVAILABLE : RSyntaxNode.LAZY_DEPARSE;
         return RCallSpecialNode.createCall(sourceSection, fnNode, signature, arguments);
     }
-
-    @TruffleBoundary
-    public static String expectName(RNode node) {
-        if (node instanceof ConstantNode) {
-            Object c = ((ConstantNode) node).getValue();
-            if (c instanceof String) {
-                return (String) c;
-            } else if (c instanceof Double) {
-                return ((Double) c).toString();
-            } else {
-                throw RInternalError.unimplemented();
-            }
-        } else if (node instanceof ReadVariableNode) {
-            return ((ReadVariableNode) node).getIdentifier();
-        } else {
-            throw RInternalError.unimplemented();
-        }
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
index f1ed9c18960d1dd7b7fdb932a1c27974c649d1b4..b4615b198f706a35a1dc00bd3a786f6051cf2906 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RRootNode.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
@@ -34,8 +35,7 @@ import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.runtime.HasSignature;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 
 /**
  * The base class for R code that can be executed, namely {@link FunctionDefinitionNode} and
@@ -47,12 +47,14 @@ public abstract class RRootNode extends RootNode implements HasSignature {
 
     private FastPathFactory fastPath;
 
-    @SuppressWarnings("deprecation")
-    protected RRootNode(FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
-        super(RContext.getRForeignAccessFactory().getTruffleLanguage(), RSyntaxNode.SOURCE_UNAVAILABLE, frameDescriptor);
+    protected RRootNode(TruffleRLanguage language, FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
+        super(language, frameDescriptor);
         this.fastPath = fastPath;
     }
 
+    @Override
+    public abstract SourceSection getSourceSection();
+
     @Override
     public abstract RootCallTarget duplicateWithNewFrameDescriptor();
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RSyntaxNodeVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RSyntaxNodeVisitor.java
index a1e220b24211f65774f3fef518ef8527310eea41..44166ba5e60271efdd1bd28377d39b3e830dc08b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RSyntaxNodeVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RSyntaxNodeVisitor.java
@@ -2,7 +2,7 @@ package com.oracle.truffle.r.nodes;
 
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.access.variables.LookupNode;
 import com.oracle.truffle.r.nodes.builtin.InternalNode;
 import com.oracle.truffle.r.nodes.control.*;
 import com.oracle.truffle.r.nodes.control.IfNode;
@@ -27,7 +27,7 @@ public interface RSyntaxNodeVisitor<T> extends IRSyntaxNodeVisitor<T> {
 
     public abstract T visit(final BlockNode block);
 
-    public abstract T visit(final ReadVariableNode var);
+    public abstract T visit(final LookupNode var);
 
     public abstract T visit(final WriteLocalFrameVariableNode var);
 
@@ -75,8 +75,8 @@ public interface RSyntaxNodeVisitor<T> extends IRSyntaxNodeVisitor<T> {
             return visit((BreakNode) node);
         if (node instanceof BlockNode)
             return visit((BlockNode) node);
-        if (node instanceof ReadVariableNode)
-            return visit((ReadVariableNode) node);
+        if (node instanceof LookupNode)
+            return visit((LookupNode) node);
         if (node instanceof WriteLocalFrameVariableNode)
             return visit((WriteLocalFrameVariableNode) node);
         if (node instanceof FunctionExpressionNode)
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java
index 535ed30b70b737426d63326036b21181d04570f5..edc1696e2cbfa1435934e7b172844622627121ea 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java
@@ -32,7 +32,6 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinRootNode;
 import com.oracle.truffle.r.nodes.function.ArgumentStatePush;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
@@ -49,6 +48,7 @@ import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
 import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 
 /**
  * This {@link RNode} returns a function's argument specified by its formal index. It is used to
@@ -156,7 +156,7 @@ public final class AccessArgumentNode extends RNode {
 
             // TODO: all tests pass without it but perhaps we should "re-wrap" promises here?
             if (isOptimizableDefault(arg)) {
-                optDefaultArgNode = new OptVariableDefaultPromiseNode(factory, (ReadVariableNode) RASTUtils.cloneNode(arg), ArgumentStatePush.INVALID_INDEX);
+                optDefaultArgNode = new OptVariableDefaultPromiseNode(factory, (RSyntaxLookup) arg.asRSyntaxNode(), ArgumentStatePush.INVALID_INDEX);
             } else {
                 Object optimizableConstant = getOptimizableConstant(arg);
                 if (optimizableConstant != null) {
@@ -174,8 +174,8 @@ public final class AccessArgumentNode extends RNode {
 
     private final class OptVariableDefaultPromiseNode extends OptVariablePromiseBaseNode {
 
-        OptVariableDefaultPromiseNode(RPromiseFactory factory, ReadVariableNode rvn, int wrapIndex) {
-            super(factory, rvn, wrapIndex);
+        OptVariableDefaultPromiseNode(RPromiseFactory factory, RSyntaxLookup lookup, int wrapIndex) {
+            super(factory, lookup, wrapIndex);
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
index 61f7c1074d7076934b15812a134481813c0953eb..c0f82b72babaf1c8b67175a6028a7f3ac5a56210 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java
@@ -85,9 +85,9 @@ public abstract class AccessSlotNode extends RBaseNode {
             CompilerDirectives.transferToInterpreter();
             RStringVector classAttr = getClassNode.getClassAttr(object);
             if (classAttr == null) {
-                throw RError.error(this, RError.Message.SLOT_CANNOT_GET, name, TypeofNode.getTypeof(object).getName());
+                throw error(RError.Message.SLOT_CANNOT_GET, name, TypeofNode.getTypeof(object).getName());
             } else {
-                throw RError.error(this, RError.Message.SLOT_NONE, name, classAttr.getLength() == 0 ? RRuntime.STRING_NA : classAttr.getDataAt(0));
+                throw error(RError.Message.SLOT_NONE, name, classAttr.getLength() == 0 ? RRuntime.STRING_NA : classAttr.getDataAt(0));
             }
         }
         if (value instanceof RSymbol) {
@@ -101,7 +101,7 @@ public abstract class AccessSlotNode extends RBaseNode {
 
     @Specialization
     protected Object getSlotS4(@SuppressWarnings("unused") RNull object, String name) {
-        throw RError.error(this, RError.Message.SLOT_BASIC_CLASS, name, "NULL");
+        throw error(RError.Message.SLOT_BASIC_CLASS, name, "NULL");
     }
 
     @Specialization(guards = {"slotAccessAllowed(object)"})
@@ -138,10 +138,10 @@ public abstract class AccessSlotNode extends RBaseNode {
         if (classAttr == null) {
             RStringVector implicitClassVec = ImplicitClassHierarchyNode.getImplicitClass(object, false);
             assert implicitClassVec.getLength() > 0;
-            throw RError.error(this, RError.Message.SLOT_BASIC_CLASS, name, implicitClassVec.getDataAt(0));
+            throw error(RError.Message.SLOT_BASIC_CLASS, name, implicitClassVec.getDataAt(0));
         } else {
             assert classAttr.getLength() > 0;
-            throw RError.error(this, RError.Message.SLOT_NON_S4, name, classAttr.getDataAt(0));
+            throw error(RError.Message.SLOT_NON_S4, name, classAttr.getDataAt(0));
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
index 19334b09e2066a604b4023ff6051b5c155075d2e..809ee9face9979c4f155c1da2e4172ea185a92a4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LocalReadVariableNode.java
@@ -31,12 +31,14 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.UnexpectedResultException;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.data.RTypesGen;
 import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 
@@ -136,4 +138,16 @@ public final class LocalReadVariableNode extends Node {
         }
         return result;
     }
+
+    public int executeInteger(VirtualFrame frame) throws UnexpectedResultException {
+        return RTypesGen.expectInteger(execute(frame));
+    }
+
+    public double executeDouble(VirtualFrame frame) throws UnexpectedResultException {
+        return RTypesGen.expectDouble(execute(frame));
+    }
+
+    public byte executeByte(VirtualFrame frame) throws UnexpectedResultException {
+        return RTypesGen.expectByte(execute(frame));
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LookupNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..358f657156255e6af910516015a176d0f2d1c473
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/LookupNode.java
@@ -0,0 +1,50 @@
+package com.oracle.truffle.r.nodes.access.variables;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
+import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+
+public final class LookupNode extends RSourceSectionNode implements RSyntaxNode, RSyntaxLookup {
+
+    @Child private ReadVariableNode read;
+    @Child private SetVisibilityNode visibility;
+
+    LookupNode(SourceSection sourceSection, ReadVariableNode read) {
+        super(sourceSection);
+        this.read = read;
+    }
+
+    @Override
+    public void voidExecute(VirtualFrame frame) {
+        read.executeInternal(frame, frame);
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        return read.executeInternal(frame, frame);
+    }
+
+    @Override
+    public Object visibleExecute(VirtualFrame frame) {
+        if (visibility == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            visibility = insert(SetVisibilityNode.create());
+        }
+        visibility.execute(frame, true);
+        return read.executeInternal(frame, frame);
+    }
+
+    @Override
+    public String getIdentifier() {
+        return read.getIdentifier();
+    }
+
+    @Override
+    public boolean isFunctionLookup() {
+        return read.isFunctionLookup();
+    }
+}
\ No newline at end of file
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
index dc171181ab5335a264ed0dc034392008002875f6..5b9aa4568a6e5ed0f5ea01ef1c78fa11fbe08479 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/variables/ReadVariableNode.java
@@ -48,7 +48,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
-import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
@@ -76,8 +75,6 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.FrameAndSlo
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.LookupResult;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.MultiSlotData;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
-import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
@@ -85,7 +82,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
  * a particular layout of frame descriptors and enclosing environments, and re-specializes in case
  * the layout changes.
  */
-public final class ReadVariableNode extends RSourceSectionNode implements RSyntaxNode, RSyntaxLookup {
+public final class ReadVariableNode extends RBaseNode {
 
     private static final int MAX_INVALIDATION_COUNT = 8;
 
@@ -98,36 +95,46 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         // start the lookup in the enclosing frame
         Super,
         // whether a promise should be forced to check its type or not during lookup
-        ForcedTypeCheck;
+        ForcedTypeCheck,
+        // whether reads of RMissing should not throw error and just proceed, this is the case for
+        // inlined varargs, which should not show missing value error
+        SilentMissing
     }
 
     public static ReadVariableNode create(String name) {
-        return new ReadVariableNode(RSyntaxNode.SOURCE_UNAVAILABLE, name, RType.Any, ReadKind.Normal);
+        return new ReadVariableNode(name, RType.Any, ReadKind.Normal);
     }
 
-    public static ReadVariableNode create(SourceSection src, String name, boolean shouldCopyValue) {
-        return new ReadVariableNode(src, name, RType.Any, shouldCopyValue ? ReadKind.Copying : ReadKind.Normal);
+    public static ReadVariableNode create(String name, boolean shouldCopyValue) {
+        return new ReadVariableNode(name, RType.Any, shouldCopyValue ? ReadKind.Copying : ReadKind.Normal);
     }
 
     public static ReadVariableNode createSilent(String name, RType mode) {
-        return new ReadVariableNode(RSyntaxNode.SOURCE_UNAVAILABLE, name, mode, ReadKind.Silent);
+        return new ReadVariableNode(name, mode, ReadKind.Silent);
     }
 
-    public static ReadVariableNode createSuperLookup(SourceSection src, String name) {
-        return new ReadVariableNode(src, name, RType.Any, ReadKind.Super);
+    public static ReadVariableNode createSilentMissing(String name, RType mode) {
+        return new ReadVariableNode(name, mode, ReadKind.SilentMissing);
     }
 
-    public static ReadVariableNode createFunctionLookup(SourceSection src, String identifier) {
-        return new ReadVariableNode(src, identifier, RType.Function, ReadKind.Normal);
+    public static ReadVariableNode createSuperLookup(String name) {
+        return new ReadVariableNode(name, RType.Any, ReadKind.Super);
     }
 
-    public static ReadVariableNode createForcedFunctionLookup(SourceSection src, String name) {
-        return new ReadVariableNode(src, name, RType.Function, ReadKind.ForcedTypeCheck);
+    public static ReadVariableNode createFunctionLookup(String identifier) {
+        return new ReadVariableNode(identifier, RType.Function, ReadKind.Normal);
+    }
+
+    public static ReadVariableNode createForcedFunctionLookup(String name) {
+        return new ReadVariableNode(name, RType.Function, ReadKind.ForcedTypeCheck);
+    }
+
+    public static RSyntaxNode wrap(SourceSection sourceSection, ReadVariableNode read) {
+        return new LookupNode(sourceSection, read);
     }
 
     @Child private PromiseHelperNode promiseHelper;
     @Child private CheckTypeNode checkTypeNode;
-    @Child private SetVisibilityNode visibility;
 
     @CompilationFinal private FrameLevel read;
     @CompilationFinal private boolean needsCopying;
@@ -146,8 +153,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
 
     @CompilationFinal(dimensions = 1) private final boolean[] seenValueKinds = new boolean[FrameSlotKind.values().length];
 
-    private ReadVariableNode(SourceSection sourceSection, Object identifier, RType mode, ReadKind kind) {
-        super(sourceSection);
+    private ReadVariableNode(Object identifier, RType mode, ReadKind kind) {
         this.identifier = identifier;
         this.identifierAsString = identifier.toString().intern();
         this.mode = mode;
@@ -156,7 +162,6 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         this.copyProfile = kind != ReadKind.Copying ? null : ConditionProfile.createBinaryProfile();
     }
 
-    @Override
     public String getIdentifier() {
         return identifierAsString;
     }
@@ -165,38 +170,16 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         return mode;
     }
 
-    @Override
-    public boolean isSyntax() {
-        return identifier instanceof String;
-    }
-
-    @Override
-    public void voidExecute(VirtualFrame frame) {
-        executeInternal(frame, frame);
-    }
-
-    @Override
     public Object execute(VirtualFrame frame) {
         return executeInternal(frame, frame);
     }
 
-    @Override
-    public Object visibleExecute(VirtualFrame frame) {
-        assert kind != ReadKind.Silent;
-        if (visibility == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            visibility = insert(SetVisibilityNode.create());
-        }
-        visibility.execute(frame, true);
-        return executeInternal(frame, frame);
-    }
-
     public Object execute(VirtualFrame frame, Frame variableFrame) {
         assert frame != null;
         return executeInternal(frame, variableFrame);
     }
 
-    private Object executeInternal(VirtualFrame frame, Frame initialFrame) {
+    Object executeInternal(VirtualFrame frame, Frame initialFrame) {
         Frame variableFrame = kind == ReadKind.Super ? superEnclosingFrameProfile.profile(RArguments.getEnclosingFrame(initialFrame)) : initialFrame;
 
         Object result;
@@ -853,7 +836,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         if ((isNullProfile == null && obj == null) || (isNullProfile != null && isNullProfile.profile(obj == null))) {
             return false;
         }
-        if (obj == RMissing.instance) {
+        if (kind != ReadKind.SilentMissing && obj == RMissing.instance) {
             unexpectedMissingProfile.enter();
             throw RError.error(RError.SHOW_CALLER, RError.Message.ARGUMENT_MISSING, getIdentifier());
         }
@@ -893,7 +876,7 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         if (obj == null) {
             return false;
         }
-        if (obj == RMissing.instance) {
+        if (kind != ReadKind.SilentMissing && obj == RMissing.instance) {
             throw RError.error(RError.SHOW_CALLER, RError.Message.ARGUMENT_MISSING, getIdentifier());
         }
         if (mode == RType.Any) {
@@ -936,7 +919,6 @@ public final class ReadVariableNode extends RSourceSectionNode implements RSynta
         return kind == ReadKind.ForcedTypeCheck;
     }
 
-    @Override
     public boolean isFunctionLookup() {
         return mode == RType.Function;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
index d6c7237c94a74eda98afe7663f56b53645e57c47..db90dae6c50d38ff99d11dd4e0073fa4f1846018 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
@@ -93,14 +93,16 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
     private final RType castType;
     private final boolean updatePositionNames;
 
+    private final boolean isValueGt1;
+
     @Child private WriteIndexedVectorNode writeVectorNode;
     @Child private PositionsCheckNode positionsCheckNode;
     @Child private CastNode castVectorNode;
-    @Child private CachedReplaceVectorNode copyPositionNames;
+    @Child private ReplaceVectorNode copyPositionNames;
     @Child private DeleteElementsNode deleteElementsNode;
     @Child private SetNamesAttributeNode setNamesNode;
 
-    CachedReplaceVectorNode(ElementAccessMode mode, RTypedValue vector, Object[] positions, RTypedValue value, boolean updatePositionNames, boolean recursive) {
+    CachedReplaceVectorNode(ElementAccessMode mode, RTypedValue vector, Object[] positions, Class<?> valueClass, RType valueType, boolean updatePositionNames, boolean recursive, boolean isValueGt1) {
         super(mode, vector, positions, recursive);
 
         if (numberOfDimensions == 1 && positions[0] instanceof String || positions[0] instanceof RAbstractStringVector) {
@@ -110,8 +112,9 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         }
 
         this.vectorClass = vector.getClass();
-        this.valueClass = value.getClass();
-        this.valueType = value.getRType();
+        this.valueClass = valueClass;
+        this.valueType = valueType;
+        this.isValueGt1 = isValueGt1;
         this.castType = resolveCastVectorType();
         verifyCastType(this.castType);
         this.castVectorNode = createCastVectorNode();
@@ -124,9 +127,13 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         }
     }
 
+    public static boolean isValueLengthGreaterThanOne(Object values) {
+        return (values instanceof RAbstractContainer) && ((RAbstractContainer) values).getLength() > 1;
+    }
+
     public boolean isSupported(Object target, Object[] positions, Object values) {
         if (vectorClass == target.getClass() && values.getClass() == valueClass) {
-            return positionsCheckNode.isSupported(positions);
+            return positionsCheckNode.isSupported(positions) && isValueLengthGreaterThanOne(values) == isValueGt1;
         }
         return false;
     }
@@ -142,7 +149,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         Object castVector = vectorClass.cast(originalVector);
         Object castValue = valueClass.cast(originalValues);
 
-        RTypedValue value;
+        Object value;
         if (valueType == RType.Null) {
             if (vectorType == RType.Null) {
                 // we cast Null to Logical, but in the end it will fold and return Null
@@ -153,7 +160,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
                 value = castType.getEmpty();
             }
         } else {
-            value = (RTypedValue) castValue;
+            value = castValue;
         }
 
         int appliedValueLength;
@@ -330,7 +337,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
                 }
             }
             error = () -> {
-                throw RError.error(this, message, valueType.getName(), vectorType.getName(), false);
+                throw error(message, valueType.getName(), vectorType.getName(), false);
             };
         }
     }
@@ -394,7 +401,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
             return RType.maxPrecedence(value, vector);
         } else if (vector.isNull() || value.isNull()) {
             if (!value.isNull()) {
-                return (mode == ElementAccessMode.FIELD_SUBSCRIPT) ? RType.List : value;
+                return (mode == ElementAccessMode.FIELD_SUBSCRIPT || (mode == ElementAccessMode.SUBSCRIPT && isValueGt1)) ? RType.List : value;
             }
             if (mode.isSubscript() && numberOfDimensions > 1) {
                 return null;
@@ -471,7 +478,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
             }
             env.put(positionString, value);
         } catch (PutException ex) {
-            throw RError.error(this, ex);
+            throw error(ex);
         }
         return env;
     }
@@ -562,9 +569,8 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         }
         if (copyPositionNames == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            copyPositionNames = insert(new CachedReplaceVectorNode(mode, names, positions, positionNames, false, recursive));
+            copyPositionNames = insert(ReplaceVectorNode.create(ElementAccessMode.SUBSET, true));
         }
-        assert copyPositionNames.isSupported(names, positions, positionNames);
         RAbstractStringVector newNames = (RAbstractStringVector) copyPositionNames.apply(names, positions, positionNames);
         if (updateNamesProfile.profile(newNames != originalNames)) {
             if (setNamesNode == null) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
index f0cccef4459b5b57ae5934c4c1d3fc8ad4951629..a493d13ce2c342db57e014c1216d48975984bd55 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ExtractVectorNode.java
@@ -27,12 +27,10 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.KeyInfo;
 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.java.JavaInterop;
 import com.oracle.truffle.api.nodes.Node;
@@ -52,9 +50,14 @@ 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.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.Foreign2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R.CollectedElements;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
-public abstract class ExtractVectorNode extends Node {
+public abstract class ExtractVectorNode extends RBaseNode {
 
     protected static final int CACHE_LIMIT = 5;
 
@@ -76,12 +79,12 @@ public abstract class ExtractVectorNode extends Node {
         return mode;
     }
 
-    public final Object applyAccessField(VirtualFrame frame, Object vector, String singlePosition) {
-        return apply(frame, vector, new Object[]{singlePosition}, RLogical.valueOf(false), RMissing.instance);
+    public final Object applyAccessField(Object vector, String singlePosition) {
+        return apply(vector, new Object[]{singlePosition}, RLogical.valueOf(false), RMissing.instance);
     }
 
-    public final Object apply(VirtualFrame frame, Object vector, Object[] positions, Object exact, Object dropDimensions) {
-        return execute(frame, boxVector.execute(vector), positions, boxExact.execute(exact), boxDropdimensions.execute(dropDimensions));
+    public final Object apply(Object vector, Object[] positions, Object exact, Object dropDimensions) {
+        return execute(boxVector.execute(vector), positions, boxExact.execute(exact), boxDropdimensions.execute(dropDimensions));
     }
 
     public static ExtractVectorNode create(ElementAccessMode accessMode, boolean ignoreRecursive) {
@@ -92,101 +95,18 @@ public abstract class ExtractVectorNode extends Node {
         return ExtractVectorNodeGen.create(accessMode, true, false);
     }
 
-    protected abstract Object execute(VirtualFrame frame, Object vector, Object[] positions, Object exact, Object dropDimensions);
-
-    protected static boolean isForeignObject(TruffleObject object) {
-        return RRuntime.isForeignObject(object);
-    }
-
-    protected static FirstStringNode createFirstString() {
-        return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot coerce position to character for foreign access.");
-    }
-
-    @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"})
-    protected Object accessField(TruffleObject object, Object[] positions, @SuppressWarnings("unused") Object exact, @SuppressWarnings("unused") Object dropDimensions,
-                    @Cached("READ.createNode()") Node foreignRead,
-                    @Cached("KEY_INFO.createNode()") Node keyInfoNode,
-                    @Cached("positions.length") @SuppressWarnings("unused") int cachedLength,
-                    @Cached("create()") CastStringNode castNode,
-                    @Cached("createFirstString()") FirstStringNode firstString,
-                    @Cached("createClassProfile()") ValueProfile positionProfile,
-                    @Cached("IS_NULL.createNode()") Node isNullNode,
-                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
-                    @Cached("UNBOX.createNode()") Node unboxNode) {
-        if (positions.length == 0) {
-            throw RError.error(this, RError.Message.GENERIC, "No positions for foreign access.");
-        }
-        positions = positionProfile.profile(positions);
-        try {
-            try {
-                // TODO implicite unboxing ok? method calls seem to behave this way
-                Object result = object;
-                for (int i = 0; i < positions.length; i++) {
-                    result = read(this, positions[i], foreignRead, keyInfoNode, (TruffleObject) result, firstString, castNode);
-                    if (positions.length > 1 && i < positions.length - 1) {
-                        assert result instanceof TruffleObject;
-                    }
-                }
-                return unbox(result, isNullNode, isBoxedNode, unboxNode);
-            } catch (UnknownIdentifierException | NoSuchFieldError e) {
-                throw RError.interopError(RError.findParentRBase(this), e, object);
-            }
-        } catch (InteropException e) {
-            throw RError.interopError(RError.findParentRBase(this), e, object);
-        }
-    }
-
-    private Object unbox(Object obj, Node isNullNode, Node isBoxedNode, Node unboxNode) throws UnsupportedMessageException {
-        if (RRuntime.isForeignObject(obj)) {
-            if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) obj)) {
-                return RNull.instance;
-            }
-            if (ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) obj)) {
-                return RRuntime.java2R(ForeignAccess.sendUnbox(unboxNode, (TruffleObject) obj));
-            }
-        }
-        return RRuntime.java2R(obj);
-    }
-
-    public static Object read(Node caller, Object position, Node foreignRead, Node keyInfoNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode)
-                    throws RError, InteropException {
-        if (position instanceof Integer) {
-            position = ((int) position) - 1;
-        } else if (position instanceof Double) {
-            position = ((double) position) - 1;
-        } else if (position instanceof RAbstractDoubleVector) {
-            position = ((RAbstractDoubleVector) position).getDataAt(0) - 1;
-        } else if (position instanceof RAbstractIntVector) {
-            position = ((RAbstractIntVector) position).getDataAt(0) - 1;
-        } else if (position instanceof RAbstractStringVector) {
-            position = firstString.executeString(castNode.doCast(position));
-        } else if (!(position instanceof String)) {
-            throw RError.error(caller, RError.Message.GENERIC, "invalid index during foreign access");
-        }
-
-        int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
-        if (KeyInfo.isReadable(info)) {
-            return ForeignAccess.sendRead(foreignRead, object, position);
-        } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
-            TruffleObject clazz = JavaInterop.toJavaClass(object);
-            info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position);
-            if (KeyInfo.isReadable(info)) {
-                return ForeignAccess.sendRead(foreignRead, clazz, position);
-            }
-        }
-        throw RError.error(caller, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
-    }
+    protected abstract Object execute(Object vector, Object[] positions, Object exact, Object dropDimensions);
 
     @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"})
-    protected Object doExtractSameDimensions(VirtualFrame frame, RAbstractVector vector, Object[] positions, Object exact, Object dropDimensions,  //
+    protected Object doExtractSameDimensions(RAbstractVector vector, Object[] positions, Object exact, Object dropDimensions,  //
                     @Cached("createRecursiveCache(vector, positions)") RecursiveExtractSubscriptNode cached) {
-        return cached.apply(frame, vector, positions, exact, dropDimensions);
+        return cached.apply(vector, positions, exact, dropDimensions);
     }
 
     @Specialization(guards = {"cached != null", "cached.isSupported(vector, positions)"})
-    protected Object doExtractRecursive(VirtualFrame frame, RAbstractListVector vector, Object[] positions, Object exact, Object dropDimensions,  //
+    protected Object doExtractRecursive(RAbstractListVector vector, Object[] positions, Object exact, Object dropDimensions,  //
                     @Cached("createRecursiveCache(vector, positions)") RecursiveExtractSubscriptNode cached) {
-        return cached.apply(frame, vector, positions, exact, dropDimensions);
+        return cached.apply(vector, positions, exact, dropDimensions);
     }
 
     protected RecursiveExtractSubscriptNode createRecursiveCache(Object vector, Object[] positions) {
@@ -196,11 +116,27 @@ public abstract class ExtractVectorNode extends Node {
         return null;
     }
 
+    protected static boolean isForeignObject(Object object) {
+        return RRuntime.isForeignObject(object);
+    }
+
+    protected static FirstStringNode createFirstString() {
+        return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot coerce position to character for foreign access.");
+    }
+
+    protected static Foreign2R createForeign2RNode() {
+        return Foreign2RNodeGen.create();
+    }
+
+    protected boolean positionsByVector(Object[] positions) {
+        return positions.length == 1 && positions[0] instanceof RAbstractVector && ((RAbstractVector) positions[0]).getLength() > 1;
+    }
+
     private boolean isRecursiveSubscript(Object vector, Object[] positions) {
         return !recursive && !ignoreRecursive && mode.isSubscript() && vector instanceof RAbstractListVector && positions.length == 1;
     }
 
-    @Specialization(limit = "CACHE_LIMIT", guards = {"cached != null", "cached.isSupported(vector, positions, exact, dropDimensions)"})
+    @Specialization(limit = "CACHE_LIMIT", guards = {"!isForeignObject(vector)", "cached != null", "cached.isSupported(vector, positions, exact, dropDimensions)"})
     protected Object doExtractDefaultCached(Object vector, Object[] positions, Object exact, Object dropDimensions,  //
                     @Cached("createDefaultCache(getThis(), vector, positions, exact, dropDimensions)") CachedExtractVectorNode cached) {
         assert !isRecursiveSubscript(vector, positions);
@@ -211,7 +147,7 @@ public abstract class ExtractVectorNode extends Node {
         return new CachedExtractVectorNode(node.getMode(), (RTypedValue) vector, positions, (RTypedValue) exact, (RTypedValue) dropDimensions, node.recursive);
     }
 
-    @Specialization(replaces = "doExtractDefaultCached")
+    @Specialization(replaces = "doExtractDefaultCached", guards = "!isForeignObject(vector)")
     @TruffleBoundary
     protected Object doExtractDefaultGeneric(Object vector, Object[] positions, Object exact, Object dropDimensions,  //
                     @Cached("new(createDefaultCache(getThis(), vector, positions, exact, dropDimensions))") GenericVectorExtractNode generic) {
@@ -239,4 +175,118 @@ public abstract class ExtractVectorNode extends Node {
             return cached;
         }
     }
+
+    @Specialization(guards = {"isForeignObject(object)", "positionsByVector(positions)"})
+    protected Object accessFieldByVectorPositions(TruffleObject object, Object[] positions, @SuppressWarnings("unused") Object exact, @SuppressWarnings("unused") Object dropDimensions,
+                    @Cached("READ.createNode()") Node foreignRead,
+                    @Cached("KEY_INFO.createNode()") Node keyInfoNode,
+                    @Cached("HAS_SIZE.createNode()") Node hasSizeNode,
+                    @Cached("create()") CastStringNode castNode,
+                    @Cached("createFirstString()") FirstStringNode firstString,
+                    @Cached("IS_NULL.createNode()") Node isNullNode,
+                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
+                    @Cached("UNBOX.createNode()") Node unboxNode,
+                    @Cached("createForeign2RNode()") Foreign2R foreign2RNode) {
+
+        RAbstractVector vec = (RAbstractVector) positions[0];
+        CollectedElements ce = new CollectedElements();
+
+        try {
+            for (int i = 0; i < vec.getLength(); i++) {
+                Object res = read(this, vec.getDataAtAsObject(i), foreignRead, keyInfoNode, hasSizeNode, object, firstString, castNode);
+                if (RRuntime.isForeignObject(res)) {
+                    if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) res)) {
+                        res = RNull.instance;
+                    }
+                    if (ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) res)) {
+                        res = ForeignAccess.sendUnbox(unboxNode, (TruffleObject) res);
+                    }
+                }
+                ce.getTypeCheck().checkForeign(res);
+                ce.getElements().add(foreign2RNode.execute(res));
+            }
+            return ForeignArray2R.asAbstractVector(ce);
+        } catch (InteropException | NoSuchFieldError e) {
+            throw RError.interopError(RError.findParentRBase(this), e, object);
+        }
+    }
+
+    @Specialization(guards = {"isForeignObject(object)", "!positionsByVector(positions)", "positions.length == cachedLength"})
+    protected Object accessField(TruffleObject object, Object[] positions, @SuppressWarnings("unused") Object exact, @SuppressWarnings("unused") Object dropDimensions,
+                    @Cached("READ.createNode()") Node foreignRead,
+                    @Cached("KEY_INFO.createNode()") Node keyInfoNode,
+                    @Cached("HAS_SIZE.createNode()") Node hasSizeNode,
+                    @Cached("positions.length") @SuppressWarnings("unused") int cachedLength,
+                    @Cached("create()") CastStringNode castNode,
+                    @Cached("createFirstString()") FirstStringNode firstString,
+                    @Cached("createClassProfile()") ValueProfile positionProfile,
+                    @Cached("IS_NULL.createNode()") Node isNullNode,
+                    @Cached("IS_BOXED.createNode()") Node isBoxedNode,
+                    @Cached("UNBOX.createNode()") Node unboxNode,
+                    @Cached("createForeign2RNode()") Foreign2R foreign2RNode) {
+        Object[] pos = positionProfile.profile(positions);
+        if (pos.length == 0) {
+            throw error(RError.Message.GENERIC, "No positions for foreign access.");
+        }
+        try {
+            // TODO implicite unboxing ok? method calls seem to behave this way
+            Object result = object;
+            for (int i = 0; i < pos.length; i++) {
+                result = read(this, pos[i], foreignRead, keyInfoNode, hasSizeNode, (TruffleObject) result, firstString, castNode);
+                if (pos.length > 1 && i < pos.length - 1) {
+                    assert result instanceof TruffleObject;
+                }
+            }
+            return unbox(result, isNullNode, isBoxedNode, unboxNode, foreign2RNode);
+        } catch (InteropException | NoSuchFieldError e) {
+            throw RError.interopError(RError.findParentRBase(this), e, object);
+        }
+    }
+
+    private static Object unbox(Object obj, Node isNullNode, Node isBoxedNode, Node unboxNode, Foreign2R foreign2RNode) throws UnsupportedMessageException {
+        if (RRuntime.isForeignObject(obj)) {
+            if (ForeignAccess.sendIsNull(isNullNode, (TruffleObject) obj)) {
+                return RNull.instance;
+            }
+            if (ForeignAccess.sendIsBoxed(isBoxedNode, (TruffleObject) obj)) {
+                return foreign2RNode.execute(ForeignAccess.sendUnbox(unboxNode, (TruffleObject) obj));
+            }
+        }
+        return foreign2RNode.execute(obj);
+    }
+
+    public static Object read(RBaseNode caller, Object positions, Node foreignRead, Node keyInfoNode, Node hasSizeNode, TruffleObject object, FirstStringNode firstString, CastStringNode castNode)
+                    throws RError, InteropException {
+        Object pos = positions;
+        if (pos instanceof Integer) {
+            pos = ((int) pos) - 1;
+        } else if (pos instanceof Double) {
+            pos = ((double) pos) - 1;
+        } else if (pos instanceof RAbstractDoubleVector) {
+            pos = ((RAbstractDoubleVector) pos).getDataAt(0) - 1;
+        } else if (pos instanceof RAbstractIntVector) {
+            pos = ((RAbstractIntVector) pos).getDataAt(0) - 1;
+        } else if (pos instanceof RAbstractStringVector) {
+            pos = firstString.executeString(castNode.doCast(pos));
+        } else if (!(pos instanceof String)) {
+            throw caller.error(RError.Message.GENERIC, "invalid index during foreign access");
+        }
+
+        int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, pos);
+        if (KeyInfo.isReadable(info) || ForeignAccess.sendHasSize(hasSizeNode, object)) {
+            return ForeignAccess.sendRead(foreignRead, object, pos);
+        } else if (pos instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
+            TruffleObject clazz = toJavaClass(object);
+            info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, pos);
+            if (KeyInfo.isReadable(info)) {
+                return ForeignAccess.sendRead(foreignRead, clazz, pos);
+            }
+        }
+        throw caller.error(RError.Message.GENERIC, "invalid index/identifier during foreign access: " + pos);
+    }
+
+    @TruffleBoundary
+    private static TruffleObject toJavaClass(TruffleObject obj) {
+        return JavaInterop.toJavaClass(obj);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java
index 80e0e05b7b17ed0a4272a2ef163f6cdb8ef35610..85fd7dccbb97a442e24ae7df633603bd622f2937 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen;
@@ -50,9 +49,10 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 
-abstract class PositionCastNode extends Node {
+abstract class PositionCastNode extends RBaseNode {
 
     private final ElementAccessMode mode;
     private final boolean replace;
@@ -74,6 +74,11 @@ abstract class PositionCastNode extends Node {
         return RInteger.valueOf(position);
     }
 
+    @Specialization
+    protected RAbstractVector doLong(long position, @Cached("create()") NACheck check) {
+        return doDouble(position, check);
+    }
+
     @Specialization
     protected RAbstractVector doString(String position) {
         return RString.valueOf(position);
@@ -137,7 +142,7 @@ abstract class PositionCastNode extends Node {
         if (position.getName().length() == 0) {
             return doMissing(RMissing.instance);
         } else {
-            throw RError.error(this, RError.Message.INVALID_SUBSCRIPT_TYPE, "symbol");
+            throw error(RError.Message.INVALID_SUBSCRIPT_TYPE, "symbol");
         }
     }
 
@@ -145,9 +150,9 @@ abstract class PositionCastNode extends Node {
     protected RMissing doMissing(@SuppressWarnings("unused") RMissing position) {
         if (mode.isSubscript()) {
             if (replace) {
-                throw RError.error(this, RError.Message.MISSING_SUBSCRIPT);
+                throw error(RError.Message.MISSING_SUBSCRIPT);
             } else {
-                throw RError.error(this, RError.Message.INVALID_SUBSCRIPT_TYPE, "symbol");
+                throw error(RError.Message.INVALID_SUBSCRIPT_TYPE, "symbol");
             }
         } else {
             return RMissing.instance;
@@ -167,7 +172,7 @@ abstract class PositionCastNode extends Node {
 
     @Specialization(guards = "getInvalidType(position) != null")
     protected RAbstractVector doInvalidType(Object position) {
-        throw RError.error(this, RError.Message.INVALID_SUBSCRIPT_TYPE, getInvalidType(position).getName());
+        throw error(RError.Message.INVALID_SUBSCRIPT_TYPE, getInvalidType(position).getName());
     }
 
     protected static RType getInvalidType(Object positionValue) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java
index d1566a34ef7d7e82285deaf7e11e5edddb106d54..44ec6ed95164d3a046a4727612384d2f4b92c004 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCharacterLookupNode.java
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.nodes.access.vector;
 
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
@@ -35,8 +34,9 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-final class PositionCharacterLookupNode extends Node {
+final class PositionCharacterLookupNode extends RBaseNode {
 
     private final ElementAccessMode mode;
     private final int numDimensions;
@@ -73,7 +73,7 @@ final class PositionCharacterLookupNode extends Node {
                     result = searchNode.apply(dimName, position, notFoundStartIndex, null);
                 } else {
                     emptyProfile.enter();
-                    throw RError.error(this, Message.SUBSCRIPT_BOUNDS);
+                    throw error(Message.SUBSCRIPT_BOUNDS);
                 }
             } else {
                 emptyProfile.enter();
@@ -85,9 +85,9 @@ final class PositionCharacterLookupNode extends Node {
 
     private RError noDimNames() {
         if (mode.isSubset()) {
-            throw RError.error(this, Message.NO_ARRAY_DIMNAMES);
+            throw error(Message.NO_ARRAY_DIMNAMES);
         } else {
-            throw RError.error(this, Message.SUBSCRIPT_BOUNDS);
+            throw error(Message.SUBSCRIPT_BOUNDS);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckNode.java
index dfe5493cb8ead7bdfe125b44c114b37616d0640b..bcd27aa7d7134782db82d91803ae2e21858a7d7e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckNode.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
@@ -45,8 +44,9 @@ 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.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-abstract class PositionCheckNode extends Node {
+abstract class PositionCheckNode extends RBaseNode {
 
     private final Class<?> positionClass;
     private final int dimensionIndex;
@@ -199,7 +199,7 @@ abstract class PositionCheckNode extends Node {
      *
      * A zero/NA anywhere in a row will cause a zero/NA in the same position in the result.
      */
-    public abstract static class Mat2indsubNode extends Node {
+    public abstract static class Mat2indsubNode extends RBaseNode {
 
         public abstract RAbstractVector execute(int[] vectorDimensions, RAbstractVector pos, int[] positionDimensions);
 
@@ -228,12 +228,12 @@ abstract class PositionCheckNode extends Node {
                     }
                     if (k < 0) {
                         error.enter();
-                        throw RError.error(this, RError.Message.GENERIC, "negative values are not allowed in a matrix subscript");
+                        throw error(RError.Message.GENERIC, "negative values are not allowed in a matrix subscript");
                     }
                     int dim = vectorDimensions[j];
                     if (k > dim) {
                         error.enter();
-                        throw RError.error(this, RError.Message.SUBSCRIPT_BOUNDS);
+                        throw error(RError.Message.SUBSCRIPT_BOUNDS);
                     }
                     iv[i] += (k - 1) * tdim;
                     tdim *= dim;
@@ -263,12 +263,12 @@ abstract class PositionCheckNode extends Node {
                     }
                     if (k < 0) {
                         error.enter();
-                        throw RError.error(this, RError.Message.GENERIC, "negative values are not allowed in a matrix subscript");
+                        throw error(RError.Message.GENERIC, "negative values are not allowed in a matrix subscript");
                     }
                     int dim = vectorDimensions[j];
                     if (k > dim) {
                         error.enter();
-                        throw RError.error(this, RError.Message.SUBSCRIPT_BOUNDS);
+                        throw error(RError.Message.SUBSCRIPT_BOUNDS);
                     }
                     iv[i] += (k - 1) * tdim;
                     tdim *= dim;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubscriptNode.java
index 2514a0825a9618297348320a72c91db76eef80ef..d11144c8c2e8a2439546f6f3d208b9bcc756a160 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubscriptNode.java
@@ -66,12 +66,12 @@ abstract class PositionCheckSubscriptNode extends PositionCheckNode {
         if (positionLength != 1) {
             error.enter();
             if (positionLength >= 3) {
-                throw RError.error(this, RError.Message.SELECT_MORE_1);
+                throw error(RError.Message.SELECT_MORE_1);
             } else {
                 if (value == RRuntime.LOGICAL_TRUE) {
-                    throw RError.error(this, RError.Message.SELECT_MORE_1);
+                    throw error(RError.Message.SELECT_MORE_1);
                 } else {
-                    throw RError.error(this, RError.Message.SELECT_LESS_1);
+                    throw error(RError.Message.SELECT_LESS_1);
                 }
             }
         }
@@ -95,7 +95,7 @@ abstract class PositionCheckSubscriptNode extends PositionCheckNode {
             } else {
                 message = RError.Message.SELECT_LESS_1;
             }
-            throw RError.error(this, message);
+            throw error(message);
         }
         assert positionLength == 1;
         positionNACheck.enable(position);
@@ -153,9 +153,9 @@ abstract class PositionCheckSubscriptNode extends PositionCheckNode {
                 }
             }
             if (selected <= 1) {
-                throw RError.error(this, RError.Message.SELECT_LESS_1);
+                throw error(RError.Message.SELECT_LESS_1);
             } else {
-                throw RError.error(this, RError.Message.SELECT_MORE_1);
+                throw error(RError.Message.SELECT_MORE_1);
             }
         }
     }
@@ -173,7 +173,7 @@ abstract class PositionCheckSubscriptNode extends PositionCheckNode {
                     message = RError.Message.SELECT_MORE_1;
                 }
             }
-            throw RError.error(this, message);
+            throw error(message);
         } else {
             if (numDimensions == 1 && isListLike(containerType) && !recursive) {
                 // lists pass on the NA value
@@ -188,7 +188,7 @@ abstract class PositionCheckSubscriptNode extends PositionCheckNode {
         if (recursive) {
             throw new RecursiveIndexNotFoundError();
         } else {
-            throw RError.error(this, RError.Message.SUBSCRIPT_BOUNDS);
+            throw error(RError.Message.SUBSCRIPT_BOUNDS);
         }
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
index f45d9018a6394c39ec670548a3d687d52059680a..2549c6cfcd58ec8fcb06268d4e0fc7d932070d14 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
@@ -108,7 +108,7 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
                 outOfBoundsProfile.enter();
                 if (isMultiDimension()) {
                     error.enter();
-                    throw RError.error(this, RError.Message.LOGICAL_SUBSCRIPT_LONG);
+                    throw error(RError.Message.LOGICAL_SUBSCRIPT_LONG);
                 }
                 length = positionLength;
             }
@@ -265,11 +265,11 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
         if (hasSeenPositive || hasSeenNA) {
             if (numDimensions > 1 && outOfBoundsCount > 0) {
                 error.enter();
-                throw RError.error(this, RError.Message.SUBSCRIPT_BOUNDS);
+                throw error(RError.Message.SUBSCRIPT_BOUNDS);
             }
             if (hasSeenNegative) {
                 error.enter();
-                throw RError.error(this, RError.Message.ONLY_0_MIXED);
+                throw error(RError.Message.ONLY_0_MIXED);
             }
             profile.maxOutOfBoundsIndex = maxOutOfBoundsIndex;
             profile.selectedPositionsCount = positionLength - zeroCount;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
index 34d28947e3f545c798d980c8e5b9c6d6f155df98..6258cd007b0e2b660436958efac19b521fac5f02 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionsCheckNode.java
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.access.vector;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
-import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
@@ -35,13 +34,13 @@ import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-final class PositionsCheckNode extends Node {
+final class PositionsCheckNode extends RBaseNode {
 
     @Children private final PositionCheckNode[] positionsCheck;
 
     private final ElementAccessMode mode;
-    private final BranchProfile errorBranch = BranchProfile.create();
     private final VectorLengthProfile selectedPositionsCountProfile = VectorLengthProfile.create();
     private final VectorLengthProfile maxOutOfBoundsProfile = VectorLengthProfile.create();
     private final ConditionProfile containsNAProfile = ConditionProfile.createBinaryProfile();
@@ -113,12 +112,10 @@ final class PositionsCheckNode extends Node {
     private void verifyDimensions(int[] vectorDimensions) {
         if (vectorDimensions == null) {
             if (isMultiDimension()) {
-                errorBranch.enter();
                 throw dimensionsError();
             }
         } else {
             if (getDimensions() > vectorDimensions.length || getDimensions() < vectorDimensions.length) {
-                errorBranch.enter();
                 throw dimensionsError();
             }
         }
@@ -129,15 +126,15 @@ final class PositionsCheckNode extends Node {
         if (replace) {
             if (mode.isSubset()) {
                 if (getDimensions() == 2) {
-                    throw RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS_MATRIX);
+                    throw error(RError.Message.INCORRECT_SUBSCRIPTS_MATRIX);
                 } else {
-                    throw RError.error(this, RError.Message.INCORRECT_SUBSCRIPTS);
+                    throw error(RError.Message.INCORRECT_SUBSCRIPTS);
                 }
             } else {
-                throw RError.error(this, RError.Message.IMPROPER_SUBSCRIPT);
+                throw error(RError.Message.IMPROPER_SUBSCRIPT);
             }
         } else {
-            throw RError.error(this, RError.Message.INCORRECT_DIMENSIONS);
+            throw error(RError.Message.INCORRECT_DIMENSIONS);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
index 621139cc8a374fc495e28a0bb029665cefc392c1..559bde561745bfe572235378367464503a4fe499 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveExtractSubscriptNode.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RLogical;
@@ -45,55 +44,50 @@ abstract class RecursiveExtractSubscriptNode extends RecursiveSubscriptNode {
         return RecursiveExtractSubscriptNodeGen.create(vector, position);
     }
 
-    public final Object apply(VirtualFrame frame, Object vector, Object[] positions, Object exact, Object dropDimensions) {
+    public final Object apply(Object vector, Object[] positions, Object exact, Object dropDimensions) {
         Object firstPosition = positions[0];
-        int length = positionLengthNode.executeInteger(frame, firstPosition);
-        return execute(frame, vector, positions, firstPosition, length, exact, dropDimensions);
+        int length = positionLengthNode.executeInteger(firstPosition);
+        return execute(vector, positions, firstPosition, length, exact, dropDimensions);
     }
 
-    protected abstract Object execute(VirtualFrame frame, Object vector, Object[] positions, Object firstPosition, int positionLength, Object exact, Object dropDimensions);
+    protected abstract Object execute(Object vector, Object[] positions, Object firstPosition, int positionLength, Object exact, Object dropDimensions);
 
     @Specialization(guards = "positionLength <= 1")
-    protected Object doDefault(VirtualFrame frame, Object vector, Object[] positions, @SuppressWarnings("unused") Object firstPosition, @SuppressWarnings("unused") int positionLength, Object exact,
+    protected Object doDefault(Object vector, Object[] positions, @SuppressWarnings("unused") Object firstPosition, @SuppressWarnings("unused") int positionLength, Object exact,
                     Object dropDimensions) {
         try {
-            return subscriptExtract.apply(frame, vector, positions, exact, dropDimensions);
+            return subscriptExtract.apply(vector, positions, exact, dropDimensions);
         } catch (RecursiveIndexNotFoundError e) {
-            errorBranch.enter();
-            throw RError.error(this, RError.Message.SUBSCRIPT_BOUNDS);
+            throw error(RError.Message.SUBSCRIPT_BOUNDS);
         }
     }
 
     @Specialization(replaces = "doDefault")
-    protected Object doRecursive(VirtualFrame frame, Object vector, @SuppressWarnings("unused") Object[] positions, Object originalFirstPosition, int positionLength, Object exact,
+    protected Object doRecursive(Object vector, @SuppressWarnings("unused") Object[] positions, Object originalFirstPosition, int positionLength, Object exact,
                     Object dropDimensions,
                     @Cached("createPositionCast()") PositionCastNode positionCast) {
         Object firstPosition = positionCast.execute(originalFirstPosition);
         Object currentVector = vector;
         for (int i = 1; i < positionLength; i++) {
-            Object selection = getPositionExtract.apply(frame, firstPosition, new Object[]{RInteger.valueOf(i)}, RLogical.TRUE, RLogical.TRUE);
+            Object selection = getPositionExtract.apply(firstPosition, new Object[]{RInteger.valueOf(i)}, RLogical.TRUE, RLogical.TRUE);
             try {
                 if (!(currentVector instanceof RAbstractListVector)) {
-                    errorBranch.enter();
                     throw indexingFailed(i);
                 }
-                currentVector = recursiveSubscriptExtract.apply(frame, currentVector, new Object[]{selection}, exact, dropDimensions);
+                currentVector = recursiveSubscriptExtract.apply(currentVector, new Object[]{selection}, exact, dropDimensions);
 
                 if (currentVector == RNull.instance) {
-                    errorBranch.enter();
-                    throw RError.error(this, RError.Message.SUBSCRIPT_BOUNDS);
+                    throw error(RError.Message.SUBSCRIPT_BOUNDS);
                 }
             } catch (RecursiveIndexNotFoundError e) {
-                errorBranch.enter();
                 throw noSuchIndex(i);
             }
         }
-        Object selection = getPositionExtract.apply(frame, firstPosition, new Object[]{RInteger.valueOf(positionLength)}, RLogical.TRUE, RLogical.TRUE);
+        Object selection = getPositionExtract.apply(firstPosition, new Object[]{RInteger.valueOf(positionLength)}, RLogical.TRUE, RLogical.TRUE);
         try {
-            return subscriptExtract.apply(frame, currentVector, new Object[]{selection}, exact, dropDimensions);
+            return subscriptExtract.apply(currentVector, new Object[]{selection}, exact, dropDimensions);
         } catch (RecursiveIndexNotFoundError e) {
-            errorBranch.enter();
-            throw RError.error(this, RError.Message.SUBSCRIPT_BOUNDS);
+            throw error(RError.Message.SUBSCRIPT_BOUNDS);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveReplaceSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveReplaceSubscriptNode.java
index f24cc637446d06438573bbd9ad2c2bc09e485c40..8af694da2eaa16c096299cecdc7c85f36bac4e75 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveReplaceSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveReplaceSubscriptNode.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.access.vector;
 
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -45,18 +44,18 @@ abstract class RecursiveReplaceSubscriptNode extends RecursiveSubscriptNode {
         return RecursiveReplaceSubscriptNodeGen.create(vector, position);
     }
 
-    public final Object apply(VirtualFrame frame, Object vector, Object[] positions, Object value) {
+    public final Object apply(Object vector, Object[] positions, Object value) {
         assert isSupported(vector, positions);
         Object firstPosition = positionClass.cast(positions[0]);
-        int length = positionLengthNode.executeInteger(frame, firstPosition);
-        return execute(frame, vectorClass.cast(vector), positions, firstPosition, length, value);
+        int length = positionLengthNode.executeInteger(firstPosition);
+        return execute(vectorClass.cast(vector), positions, firstPosition, length, value);
     }
 
-    protected abstract Object execute(VirtualFrame frame, Object vector, Object[] positions, Object firstPosition, int positionLength, Object value);
+    protected abstract Object execute(Object vector, Object[] positions, Object firstPosition, int positionLength, Object value);
 
     @Specialization(guards = "positionLength <= 1")
-    protected Object doDefault(VirtualFrame frame, Object vector, Object[] positions, @SuppressWarnings("unused") Object firstPosition, @SuppressWarnings("unused") int positionLength, Object value) {
-        return subscriptReplace.apply(frame, vector, positions, value);
+    protected Object doDefault(Object vector, Object[] positions, @SuppressWarnings("unused") Object firstPosition, @SuppressWarnings("unused") int positionLength, Object value) {
+        return subscriptReplace.apply(vector, positions, value);
     }
 
     /**
@@ -82,7 +81,7 @@ abstract class RecursiveReplaceSubscriptNode extends RecursiveSubscriptNode {
      * </code>
      */
     @Specialization(replaces = "doDefault")
-    protected Object doRecursive(VirtualFrame frame, Object vector, @SuppressWarnings("unused") Object[] positions, Object originalFirstPosition, int positionLength, Object value,
+    protected Object doRecursive(Object vector, @SuppressWarnings("unused") Object[] positions, Object originalFirstPosition, int positionLength, Object value,
                     @Cached("createPositionCast()") PositionCastNode positionCast) {
         Object firstPosition = positionCast.execute(originalFirstPosition);
         Object[] positionStack = new Object[positionLength];
@@ -90,13 +89,13 @@ abstract class RecursiveReplaceSubscriptNode extends RecursiveSubscriptNode {
         valueStack[0] = vector;
         Object currentVector = vector;
         for (int i = 1; i < positionLength; i++) {
-            Object parentPosition = getPositionValue(frame, firstPosition, i - 1);
+            Object parentPosition = getPositionValue(firstPosition, i - 1);
             positionStack[i - 1] = parentPosition;
             try {
                 if (!(currentVector instanceof RAbstractListVector)) {
                     throw indexingFailed(i);
                 }
-                currentVector = recursiveSubscriptExtract.apply(frame, currentVector, new Object[]{parentPosition}, RLogical.TRUE, RLogical.TRUE);
+                currentVector = recursiveSubscriptExtract.apply(currentVector, new Object[]{parentPosition}, RLogical.TRUE, RLogical.TRUE);
                 if (currentVector == RNull.instance) {
                     throw noSuchIndex(i);
                 }
@@ -106,12 +105,12 @@ abstract class RecursiveReplaceSubscriptNode extends RecursiveSubscriptNode {
             }
         }
         Object recursiveValue = value;
-        positionStack[positionLength - 1] = getPositionValue(frame, firstPosition, positionLength - 1);
+        positionStack[positionLength - 1] = getPositionValue(firstPosition, positionLength - 1);
         for (int i = positionLength - 1; i >= 1; i--) {
-            recursiveValue = recursiveSubscriptReplace.apply(frame, valueStack[i], new Object[]{positionStack[i]}, recursiveValue);
+            recursiveValue = recursiveSubscriptReplace.apply(valueStack[i], new Object[]{positionStack[i]}, recursiveValue);
         }
         // the last recursive replace need to have recursive set to false
-        recursiveValue = subscriptReplace.apply(frame, valueStack[0], new Object[]{positionStack[0]}, recursiveValue);
+        recursiveValue = subscriptReplace.apply(valueStack[0], new Object[]{positionStack[0]}, recursiveValue);
 
         return recursiveValue;
     }
@@ -120,7 +119,7 @@ abstract class RecursiveReplaceSubscriptNode extends RecursiveSubscriptNode {
         return PositionCastNode.create(ElementAccessMode.SUBSCRIPT, false);
     }
 
-    private Object getPositionValue(VirtualFrame frame, Object firstPosition, int i) {
-        return getPositionExtract.apply(frame, firstPosition, new Object[]{RInteger.valueOf(i + 1)}, RLogical.TRUE, RLogical.TRUE);
+    private Object getPositionValue(Object firstPosition, int i) {
+        return getPositionExtract.apply(firstPosition, new Object[]{RInteger.valueOf(i + 1)}, RLogical.TRUE, RLogical.TRUE);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
index 0e4e9b5030820afc3b8e39f7b87e81944dc86264..72a24f39e2db858bb474e438586818bf604adf2b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/RecursiveSubscriptNode.java
@@ -22,19 +22,16 @@
  */
 package com.oracle.truffle.r.nodes.access.vector;
 
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
-abstract class RecursiveSubscriptNode extends Node {
+abstract class RecursiveSubscriptNode extends RBaseNode {
 
     protected final Class<?> vectorClass;
     protected final Class<?> positionClass;
 
-    protected final BranchProfile errorBranch = BranchProfile.create();
-
     @Child protected RLengthNode positionLengthNode = RLengthNode.create();
 
     RecursiveSubscriptNode(RAbstractListVector vector, Object position) {
@@ -50,12 +47,10 @@ abstract class RecursiveSubscriptNode extends Node {
     }
 
     protected final RError indexingFailed(int i) {
-        errorBranch.enter();
-        throw RError.error(this, RError.Message.RECURSIVE_INDEXING_FAILED, i);
+        throw error(RError.Message.RECURSIVE_INDEXING_FAILED, i);
     }
 
     protected final RError noSuchIndex(int i) {
-        errorBranch.enter();
-        throw RError.error(this, RError.Message.NO_SUCH_INDEX, i);
+        throw error(RError.Message.NO_SUCH_INDEX, i);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
index 77ce1d830a852c0c6074d374f4ef396aee94ef4d..cef08a1982e2309d3ad3e293ea3a8220dade57e3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/ReplaceVectorNode.java
@@ -27,7 +27,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.KeyInfo;
@@ -41,17 +40,21 @@ import com.oracle.truffle.r.nodes.unary.CastStringNode;
 import com.oracle.truffle.r.nodes.unary.FirstStringNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
 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.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Syntax node for element writes.
  */
 @ImportStatic({RRuntime.class, com.oracle.truffle.api.interop.Message.class})
-public abstract class ReplaceVectorNode extends Node {
+public abstract class ReplaceVectorNode extends RBaseNode {
 
     protected static final int CACHE_LIMIT = 5;
 
@@ -68,11 +71,11 @@ public abstract class ReplaceVectorNode extends Node {
         this.ignoreRecursive = ignoreRecursive;
     }
 
-    public final Object apply(VirtualFrame frame, Object vector, Object[] positions, Object value) {
-        return execute(frame, boxVector.execute(vector), positions, boxValue.execute(value));
+    public final Object apply(Object vector, Object[] positions, Object value) {
+        return execute(boxVector.execute(vector), positions, boxValue.execute(value));
     }
 
-    protected abstract Object execute(VirtualFrame frame, Object vector, Object[] positions, Object value);
+    protected abstract Object execute(Object vector, Object[] positions, Object value);
 
     public static ReplaceVectorNode create(ElementAccessMode mode, boolean ignoreRecursive) {
         return ReplaceVectorNodeGen.create(mode, false, ignoreRecursive);
@@ -84,76 +87,86 @@ public abstract class ReplaceVectorNode extends Node {
 
     protected Node createForeignWrite(Object[] positions) {
         if (positions.length != 1) {
-            throw RError.error(this, RError.Message.GENERIC, "Invalid number positions for foreign access.");
+            throw error(RError.Message.GENERIC, "Invalid number positions for foreign access.");
         }
         return Message.WRITE.createNode();
     }
 
-    protected static boolean isForeignObject(TruffleObject object) {
-        return RRuntime.isForeignObject(object);
-    }
-
     protected FirstStringNode createFirstString() {
         return FirstStringNode.createWithError(RError.Message.GENERIC, "Cannot corce position to character for foreign access.");
     }
 
+    protected R2Foreign createR2Foreign() {
+        return R2ForeignNodeGen.create();
+    }
+
     @Specialization(guards = {"isForeignObject(object)", "positions.length == cachedLength"})
     protected Object accessField(TruffleObject object, Object[] positions, Object value,
                     @Cached("WRITE.createNode()") Node foreignWrite,
                     @Cached("READ.createNode()") Node foreignRead,
-                    @Cached("KEY_INFO.createNode()") Node keyInfo,
+                    @Cached("KEY_INFO.createNode()") Node keyInfoNode,
+                    @Cached("HAS_SIZE.createNode()") Node hasSizeNode,
                     @SuppressWarnings("unused") @Cached("positions.length") int cachedLength,
                     @Cached("create()") CastStringNode castNode,
-                    @Cached("createFirstString()") FirstStringNode firstString) {
-        Object writtenValue = RRuntime.r2Java(value);
+                    @Cached("createFirstString()") FirstStringNode firstString,
+                    @Cached("createR2Foreign()") R2Foreign r2Foreign) {
+        Object writtenValue = value;
         try {
             TruffleObject result = object;
             for (int i = 0; i < positions.length - 1; i++) {
-                result = (TruffleObject) ExtractVectorNode.read(this, positions[i], foreignRead, keyInfo, result, firstString, castNode);
+                result = (TruffleObject) ExtractVectorNode.read(this, positions[i], foreignRead, keyInfoNode, hasSizeNode, result, firstString, castNode);
             }
-            write(positions[positions.length - 1], foreignWrite, keyInfo, result, writtenValue, firstString, castNode);
+            write(positions[positions.length - 1], foreignWrite, keyInfoNode, hasSizeNode, result, writtenValue, firstString, castNode, r2Foreign);
             return object;
         } catch (InteropException e) {
             throw RError.interopError(RError.findParentRBase(this), e, object);
         }
     }
 
-    private void write(Object position, Node foreignWrite, Node keyInfoNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode)
+    private void write(Object position, Node foreignWrite, Node keyInfoNode, Node hasSizeNode, TruffleObject object, Object writtenValue, FirstStringNode firstString, CastStringNode castNode,
+                    R2Foreign r2Foreign)
                     throws InteropException, RError {
-        if (position instanceof Integer) {
-            position = ((Integer) position) - 1;
-        } else if (position instanceof Double) {
-            position = ((Double) position) - 1;
-        } else if (position instanceof RAbstractDoubleVector) {
-            position = ((RAbstractDoubleVector) position).getDataAt(0) - 1;
-        } else if (position instanceof RAbstractIntVector) {
-            position = ((RAbstractIntVector) position).getDataAt(0) - 1;
-        } else if (position instanceof RAbstractStringVector) {
-            String string = firstString.executeString(castNode.doCast(position));
-            position = string;
-        } else if (!(position instanceof String)) {
-            throw RError.error(this, RError.Message.GENERIC, "invalid index during foreign access");
+        Object pos = position;
+        if (pos instanceof Integer) {
+            pos = ((Integer) pos) - 1;
+        } else if (pos instanceof Double) {
+            pos = ((Double) pos) - 1;
+        } else if (pos instanceof RAbstractDoubleVector) {
+            pos = ((RAbstractDoubleVector) pos).getDataAt(0) - 1;
+        } else if (pos instanceof RAbstractIntVector) {
+            pos = ((RAbstractIntVector) pos).getDataAt(0) - 1;
+        } else if (pos instanceof RAbstractStringVector) {
+            String string = firstString.executeString(castNode.doCast(pos));
+            pos = string;
+        } else if (!(pos instanceof String)) {
+            throw error(RError.Message.GENERIC, "invalid index during foreign access");
         }
 
-        int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, position);
-        if (KeyInfo.isWritable(info)) {
-            ForeignAccess.sendWrite(foreignWrite, object, position, RRuntime.r2Java(writtenValue));
+        int info = ForeignAccess.sendKeyInfo(keyInfoNode, object, pos);
+        if (KeyInfo.isWritable(info) || ForeignAccess.sendHasSize(hasSizeNode, object) ||
+                        (pos instanceof String && !JavaInterop.isJavaObject(Object.class, object))) {
+            ForeignAccess.sendWrite(foreignWrite, object, pos, r2Foreign.execute(writtenValue));
             return;
-        } else if (position instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
-            TruffleObject clazz = JavaInterop.toJavaClass(object);
-            info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, position);
+        } else if (pos instanceof String && !KeyInfo.isExisting(info) && JavaInterop.isJavaObject(Object.class, object)) {
+            TruffleObject clazz = toJavaClass(object);
+            info = ForeignAccess.sendKeyInfo(keyInfoNode, clazz, pos);
             if (KeyInfo.isWritable(info)) {
-                ForeignAccess.sendWrite(foreignWrite, clazz, position, RRuntime.r2Java(writtenValue));
+                ForeignAccess.sendWrite(foreignWrite, clazz, pos, r2Foreign.execute(writtenValue));
                 return;
             }
         }
-        throw RError.error(this, RError.Message.GENERIC, "invalid index/identifier during foreign access: " + position);
+        throw error(RError.Message.GENERIC, "invalid index/identifier during foreign access: " + pos);
+    }
+
+    @TruffleBoundary
+    private static TruffleObject toJavaClass(TruffleObject obj) {
+        return JavaInterop.toJavaClass(obj);
     }
 
     @Specialization(limit = "CACHE_LIMIT", guards = {"cached != null", "cached.isSupported(vector, positions)"})
-    protected Object doRecursive(VirtualFrame frame, RAbstractListVector vector, Object[] positions, Object value,  //
+    protected Object doRecursive(RAbstractListVector vector, Object[] positions, Object value,  //
                     @Cached("createRecursiveCache(vector, positions)") RecursiveReplaceSubscriptNode cached) {
-        return cached.apply(frame, vector, positions, value);
+        return cached.apply(vector, positions, value);
     }
 
     protected RecursiveReplaceSubscriptNode createRecursiveCache(Object vector, Object[] positions) {
@@ -175,7 +188,8 @@ public abstract class ReplaceVectorNode extends Node {
     }
 
     protected static CachedReplaceVectorNode createDefaultCached(ReplaceVectorNode node, Object vector, Object[] positions, Object value) {
-        return new CachedReplaceVectorNode(node.mode, (RTypedValue) vector, positions, (RTypedValue) value, true, node.recursive);
+        return new CachedReplaceVectorNode(node.mode, (RTypedValue) vector, positions, value.getClass(), RRuntime.isForeignObject(value) ? RType.TruffleObject : ((RTypedValue) value).getRType(), true,
+                        node.recursive, CachedReplaceVectorNode.isValueLengthGreaterThanOne(value));
     }
 
     public ElementAccessMode getMode() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java
index 8f9270d9ccd8e45a5b8f76099ba5f391ac604cd8..ab744903fc74bb2b3cadb87d7d754738ed94428c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/WriteIndexedVectorNode.java
@@ -44,7 +44,6 @@ import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RScalarVector;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
@@ -85,12 +84,12 @@ abstract class WriteIndexedVectorNode extends Node {
     private final NACheck positionNACheck = NACheck.create();
     private final ConditionProfile resetIndexProfile = ConditionProfile.createBinaryProfile();
 
-    @Child private WriteIndexedScalarNode<RAbstractVector, RTypedValue> scalarNode;
+    @Child private WriteIndexedScalarNode<RAbstractVector, Object> scalarNode;
     @Child private WriteIndexedVectorNode innerVectorNode;
 
     @SuppressWarnings("unchecked")
     protected WriteIndexedVectorNode(RType vectorType, int totalDimensions, int dimensionIndex, boolean positionAppliesToRight, boolean skipNA, boolean setListElementAsObject, boolean isReplace) {
-        this.scalarNode = (WriteIndexedScalarNode<RAbstractVector, RTypedValue>) createIndexedAction(vectorType, setListElementAsObject, isReplace);
+        this.scalarNode = (WriteIndexedScalarNode<RAbstractVector, Object>) createIndexedAction(vectorType, setListElementAsObject, isReplace);
         this.dimensionIndex = dimensionIndex;
         this.totalDimensions = totalDimensions;
         this.positionsApplyToRight = positionAppliesToRight;
@@ -125,7 +124,7 @@ abstract class WriteIndexedVectorNode extends Node {
     }
 
     public final void apply(RAbstractVector left, int leftLength,
-                    Object[] positions, RTypedValue right, int rightLength, int[] positionTargetDimensions) {
+                    Object[] positions, Object right, int rightLength, int[] positionTargetDimensions) {
         assert left.getLength() == leftLength;
         assert totalDimensions == positions.length : "totalDimensions must be constant per vector write node";
 
@@ -162,7 +161,7 @@ abstract class WriteIndexedVectorNode extends Node {
     private int applyImpl(//
                     RAbstractVector left, Object leftStore, int leftBase, int leftLength, Object targetDimensions, int targetDimension,
                     Object[] positions, int positionOffset,
-                    RTypedValue right, Object rightStore, int rightBase, int rightLength, boolean parentNA) {
+                    Object right, Object rightStore, int rightBase, int rightLength, boolean parentNA) {
 
         Object position = positionClassProfile.profile(positions[dimensionIndex]);
 
@@ -188,7 +187,7 @@ abstract class WriteIndexedVectorNode extends Node {
 
     protected abstract int execute(RAbstractVector left, Object leftStore, int storeBase, int storeLength, Object targetDimensions, int targetDimension,
                     Object[] positions, Object position, int positionOffset, int positionLength,
-                    RTypedValue right, Object rightStore, int valueBase, int valueLength, boolean parentNA);
+                    Object right, Object rightStore, int valueBase, int valueLength, boolean parentNA);
 
     @Specialization
     protected int doMissing(RAbstractVector left, Object leftStore, int leftBase, int leftLength, Object targetDimensions, int targetDimension,
@@ -209,7 +208,7 @@ abstract class WriteIndexedVectorNode extends Node {
     @Specialization
     protected int doLogicalPosition(RAbstractVector left, Object leftStore, int leftBase, int leftLength, Object targetDimensions, int targetDimension,
                     Object[] positions, RAbstractLogicalVector position, int positionOffset, int positionLength,
-                    RTypedValue right, Object rightStore, int rightBase, int rightLength, boolean parentNA,
+                    Object right, Object rightStore, int rightBase, int rightLength, boolean parentNA,
                     @Cached("create()") BranchProfile wasTrue,
                     @Cached("create()") AlwaysOnBranchProfile outOfBounds,
                     @Cached("createCountingProfile()") LoopConditionProfile profile,
@@ -254,7 +253,7 @@ abstract class WriteIndexedVectorNode extends Node {
     @Specialization(rewriteOn = SlowPathException.class)
     protected int doIntegerSequencePosition(RAbstractVector left, Object leftStore, int leftBase, int leftLength, Object targetDimensions, @SuppressWarnings("unused") int targetDimension,
                     Object[] positions, RIntSequence position, int positionOffset, int positionLength,
-                    RTypedValue right, Object rightStore, int rightBase, int rightLength, boolean parentNA,
+                    Object right, Object rightStore, int rightBase, int rightLength, boolean parentNA,
                     @Cached("create()") IntValueProfile startProfile,
                     @Cached("create()") IntValueProfile strideProfile,
                     @Cached("createBinaryProfile()") ConditionProfile conditionProfile,
@@ -293,7 +292,7 @@ abstract class WriteIndexedVectorNode extends Node {
     @Specialization(replaces = "doIntegerSequencePosition")
     protected int doIntegerPosition(RAbstractVector left, Object leftStore, int leftBase, int leftLength, Object targetDimensions, @SuppressWarnings("unused") int targetDimension,
                     Object[] positions, RAbstractIntVector position, int positionOffset, int positionLength,
-                    RTypedValue right, Object rightStore, int rightBase, int rightLength, boolean parentNA,
+                    Object right, Object rightStore, int rightBase, int rightLength, boolean parentNA,
                     @Cached("createCountingProfile()") LoopConditionProfile lengthProfile) {
         positionNACheck.enable(position);
         int rightIndex = rightBase;
@@ -318,7 +317,7 @@ abstract class WriteIndexedVectorNode extends Node {
     private int applyInner(//
                     RAbstractVector left, Object leftStore, int leftBase, int leftLength, Object targetDimensions,
                     Object[] positions, int positionOffset, int positionValue,
-                    RTypedValue right, Object rightStore, int rightLength, int actionIndex, boolean isNA) {
+                    Object right, Object rightStore, int rightLength, int actionIndex, boolean isNA) {
         int newTargetIndex = leftBase + positionValue * positionOffset;
         if (dimensionIndex == 0) {
             // for-loops leaf for innermost dimension
@@ -354,7 +353,7 @@ abstract class WriteIndexedVectorNode extends Node {
         }
     }
 
-    private static WriteIndexedScalarNode<? extends RAbstractVector, ? extends RTypedValue> createIndexedAction(RType type, boolean setListElementAsObject, boolean isReplace) {
+    private static WriteIndexedScalarNode<? extends RAbstractVector, ? extends Object> createIndexedAction(RType type, boolean setListElementAsObject, boolean isReplace) {
         switch (type) {
             case Logical:
                 return new WriteLogicalAction();
@@ -378,7 +377,7 @@ abstract class WriteIndexedVectorNode extends Node {
         }
     }
 
-    private abstract static class WriteIndexedScalarNode<A extends RAbstractVector, V extends RTypedValue> extends Node {
+    private abstract static class WriteIndexedScalarNode<A extends RAbstractVector, V extends Object> extends Node {
 
         final NACheck valueNACheck = NACheck.create();
 
@@ -483,7 +482,7 @@ abstract class WriteIndexedVectorNode extends Node {
         }
     }
 
-    private static final class WriteListAction extends WriteIndexedScalarNode<RAbstractListBaseVector, RTypedValue> {
+    private static final class WriteListAction extends WriteIndexedScalarNode<RAbstractListBaseVector, Object> {
 
         private final boolean setListElementAsObject;
         private final boolean isReplace;
@@ -501,7 +500,7 @@ abstract class WriteIndexedVectorNode extends Node {
         }
 
         @Override
-        void apply(RAbstractListBaseVector leftAccess, Object leftStore, int leftIndex, RTypedValue rightAccess, Object rightStore, int rightIndex) {
+        void apply(RAbstractListBaseVector leftAccess, Object leftStore, int leftIndex, Object rightAccess, Object rightStore, int rightIndex) {
             Object rightValue;
             if (setListElementAsObject) {
                 rightValue = rightAccess;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b2ff7d4ac84c82df65563975ed47c450165da2a
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetAttributesNode.java
@@ -0,0 +1,141 @@
+/*
+ * 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.nodes.attributes;
+
+import java.util.Arrays;
+
+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.object.DynamicObject;
+import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+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.RLanguage;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+/**
+ * Transforms the attributes from {@link DynamicObject} into {@link RList}.
+ */
+public abstract class GetAttributesNode extends RBaseNode {
+
+    private final BranchProfile rownamesBranch = BranchProfile.create();
+    @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
+    @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
+
+    public static GetAttributesNode create() {
+        return GetAttributesNodeGen.create();
+    }
+
+    public abstract Object execute(RAttributable attributable);
+
+    @Specialization
+    protected Object attributesNull(RAbstractContainer container,
+                    @Cached("createBinaryProfile()") ConditionProfile hasAttributesProfile) {
+        if (hasAttributesProfile.profile(hasAttributes(container))) {
+            return createResult(container, container instanceof RLanguage);
+        } else {
+            return RNull.instance;
+        }
+    }
+
+    /**
+     * Unusual cases that it is not worth specializing on as they are not performance-centric,
+     * basically any type that is not an {@link RAbstractContainer} but is {@link RAttributable},
+     * e.g. {@link REnvironment}.
+     */
+    @Fallback
+    @TruffleBoundary
+    protected Object attributes(RAttributable object) {
+        if (hasAttributes(object)) {
+            return createResult(object, false);
+        } else {
+            return RNull.instance;
+        }
+    }
+
+    public static Object getFullRowNames(Object a) {
+        if (a == RNull.instance) {
+            return RNull.instance;
+        } else {
+            if (a instanceof RAbstractIntVector) {
+                RAbstractIntVector rowNames = (RAbstractIntVector) a;
+                if (rowNames.getLength() == 2 && RRuntime.isNA(rowNames.getDataAt(0))) {
+                    return RDataFactory.createIntSequence(1, 1, Math.abs(rowNames.getDataAt(1)));
+                }
+            }
+            return a;
+        }
+    }
+
+    /**
+     * {@code language} objects behave differently regarding "names"; they don't get included.
+     */
+    private Object createResult(RAttributable attributable, boolean ignoreNames) {
+        DynamicObject attributes = attributable.getAttributes();
+        int size = attributes.size();
+        String[] names = new String[size];
+        Object[] values = new Object[size];
+        int z = 0;
+        for (RAttributesLayout.RAttribute attr : arrayAttrAccess.execute(attributes)) {
+            String name = attr.getName();
+            if (ignoreNames && name.equals(RRuntime.NAMES_ATTR_KEY)) {
+                continue;
+            }
+            names[z] = name;
+            if (name.equals(RRuntime.ROWNAMES_ATTR_KEY)) {
+                rownamesBranch.enter();
+                values[z] = getFullRowNames(attr.getValue());
+            } else {
+                values[z] = attr.getValue();
+            }
+            z++;
+        }
+        if (ignoreNames && z != names.length) {
+            if (z == 0) {
+                return RNull.instance;
+            } else {
+                names = Arrays.copyOfRange(names, 0, names.length - 1);
+                values = Arrays.copyOfRange(values, 0, values.length - 1);
+            }
+        }
+        RList result = RDataFactory.createList(values);
+        setNamesNode.setNames(result, RDataFactory.createStringVector(names, true));
+        return result;
+    }
+
+    private static boolean hasAttributes(RAttributable attributable) {
+        return attributable.getAttributes() != null && !attributable.getAttributes().isEmpty();
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/HasAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/HasAttributesNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..a544ed3f278df0d6eaf62a15947fe7ec67e2f792
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/HasAttributesNode.java
@@ -0,0 +1,64 @@
+/*
+ * 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.nodes.attributes;
+
+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.object.DynamicObject;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RAttributeStorage;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+public abstract class HasAttributesNode extends RBaseNode {
+
+    public abstract boolean execute(Object attrs);
+
+    public static HasAttributesNode create() {
+        return HasAttributesNodeGen.create();
+    }
+
+    @Specialization
+    protected boolean handleAttributable(RAttributable x,
+                    @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
+                    @Cached("createClassProfile()") ValueProfile xTypeProfile) {
+
+        DynamicObject attributes;
+        if (attrStorageProfile.profile(x instanceof RAttributeStorage)) {
+            attributes = ((RAttributeStorage) x).getAttributes();
+        } else {
+            attributes = xTypeProfile.profile(x).getAttributes();
+        }
+
+        return attributes != null;
+    }
+
+    @Fallback
+    protected boolean handleOthers(@SuppressWarnings("unused") Object x) {
+        return false;
+    }
+
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
index 4ad3dfb7616f78d0df1cd03b70a010f6b7ed38b7..30896b1446fccb004ddfc74b1a6964a6637fbf8a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
@@ -446,7 +446,9 @@ public final class SpecialAttributesFunctions {
                 RList dimNames = getDimNames.getDimNames(x);
                 if (dimNames != null && dimNames.getLength() == 1) {
                     dimNamesAvlProfile.enter();
-                    return dimNames.getDataAt(0);
+                    Object dimName = dimNames.getDataAt(0);
+                    return (dimName != RNull.instance) ? dimName : null; // For
+                                                                         // ".Dimnames=list(NULL)"
                 }
                 return null;
             }
@@ -764,16 +766,14 @@ public final class SpecialAttributesFunctions {
             for (int i = 0; loopProfile.inject(i < newDimNamesLength); i++) {
                 Object dimObject = newDimNames.getDataAt(i);
 
-                if ((dimObject instanceof String && dimensions[i] != 1) ||
+                if (dimObject instanceof RStringVector && ((RStringVector) dimObject).getLength() == 0) {
+                    nullDimProfile.enter();
+                    newDimNames.updateDataAt(i, RNull.instance, null);
+                } else if ((dimObject instanceof String && dimensions[i] != 1) ||
                                 (dimObject instanceof RStringVector && !isValidDimLength((RStringVector) dimObject, dimensions[i]))) {
                     CompilerDirectives.transferToInterpreter();
                     throw error(RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
                 }
-
-                if (dimObject == null || (dimObject instanceof RStringVector && ((RStringVector) dimObject).getLength() == 0)) {
-                    nullDimProfile.enter();
-                    newDimNames.updateDataAt(i, RNull.instance, null);
-                }
             }
 
             RList resDimNames = newDimNames;
@@ -840,7 +840,8 @@ public final class SpecialAttributesFunctions {
         }
 
         public final RList getDimNames(Object x) {
-            return (RList) execute(x);
+            Object result = execute(x);
+            return result == RNull.instance ? null : (RList) result;
         }
 
         @Specialization(insertBefore = "getAttrFromAttributable")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
index 56f24c6840969e6049dfd536a99694f3c015011e..3ca986a2bb6fa5c664383b5bf2e67831fe6bd189 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java
@@ -27,6 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -36,6 +37,7 @@ import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNode;
 import com.oracle.truffle.r.nodes.unary.UnaryArithmeticNodeGen;
 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.RType;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RMissing;
@@ -122,7 +124,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode.Arg2 {
             throw error(RError.Message.ARGUMENT_EMPTY, 2);
         } else {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            return UnaryArithmeticNodeGen.create(unary, RError.Message.INVALID_ARG_TYPE_UNARY);
+            return UnaryArithmeticNodeGen.create(unary);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
index ee507eba25d5427948199f6d1d3654836b3e5549..df79a03c484b97c66b4900950a24a7d3e0abd0e1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticSpecial.java
@@ -23,18 +23,19 @@
 package com.oracle.truffle.r.nodes.binary;
 
 import com.oracle.truffle.api.CompilerDirectives;
-
 import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.binary.BinaryArithmeticSpecialNodeGen.IntegerBinaryArithmeticSpecialNodeGen;
+import com.oracle.truffle.r.nodes.unary.UnaryArithmeticSpecialNodeGen;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
 /**
  * Fast-path for scalar values: these cannot have any class attribute. Note: we intentionally use
@@ -47,37 +48,58 @@ import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory;
 public abstract class BinaryArithmeticSpecial extends RNode {
 
     private final boolean handleNA;
+    private final BinaryArithmeticFactory binaryFactory;
+    private final UnaryArithmeticFactory unaryFactory;
+
     @Child private BinaryArithmetic operation;
 
-    public BinaryArithmeticSpecial(BinaryArithmeticFactory opFactory) {
-        this.operation = opFactory.createOperation();
-        this.handleNA = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.MOD);
+    public BinaryArithmeticSpecial(BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) {
+        this.binaryFactory = binaryFactory;
+        this.unaryFactory = unaryFactory;
+        this.operation = binaryFactory.createOperation();
+        this.handleNA = !(binaryFactory == BinaryArithmetic.POW || binaryFactory == BinaryArithmetic.MOD);
     }
 
-    public static RSpecialFactory createSpecialFactory(BinaryArithmeticFactory opFactory) {
-        boolean handleIntegers = !(opFactory == BinaryArithmetic.POW || opFactory == BinaryArithmetic.DIV);
-        if (handleIntegers) {
-            return (signature, arguments, inReplacement) -> signature.getNonNullCount() == 0 && arguments.length == 2
-                            ? IntegerBinaryArithmeticSpecialNodeGen.create(opFactory, arguments[0], arguments[1]) : null;
-        } else {
-            return (signature, arguments, inReplacement) -> signature.getNonNullCount() == 0 && arguments.length == 2
-                            ? BinaryArithmeticSpecialNodeGen.create(opFactory, arguments[0], arguments[1]) : null;
-        }
+    public static RSpecialFactory createSpecialFactory(BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) {
+        return (signature, arguments, inReplacement) -> {
+            if (signature.getNonNullCount() == 0) {
+                if (arguments.length == 2) {
+                    boolean handleIntegers = !(binaryFactory == BinaryArithmetic.POW || binaryFactory == BinaryArithmetic.DIV);
+                    if (handleIntegers) {
+                        return IntegerBinaryArithmeticSpecialNodeGen.create(binaryFactory, unaryFactory, arguments[0], arguments[1]);
+                    } else {
+                        return BinaryArithmeticSpecialNodeGen.create(binaryFactory, unaryFactory, arguments[0], arguments[1]);
+                    }
+                } else if (arguments.length == 1 && unaryFactory != null) {
+                    return UnaryArithmeticSpecialNodeGen.create(unaryFactory, arguments[0]);
+                }
+            }
+            return null;
+        };
     }
 
     @Specialization
-    protected double doDoubles(double left, double right) {
-        if (RRuntime.isNA(left) || RRuntime.isNA(right)) {
+    protected double doDoubles(double left, double right,
+                    @Cached("createBinaryProfile()") ConditionProfile leftNanProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile rightNaProfile) {
+        if (leftNanProfile.profile(Double.isNaN(left))) {
+            checkFullCallNeededOnNA();
+            return left;
+        } else if (rightNaProfile.profile(RRuntime.isNA(right))) {
             checkFullCallNeededOnNA();
-            return isNaN(left) ? Double.NaN : RRuntime.DOUBLE_NA;
+            return RRuntime.DOUBLE_NA;
         }
         return getOperation().op(left, right);
     }
 
-    @Fallback
-    @SuppressWarnings("unused")
-    protected double doFallback(Object left, Object right) {
-        throw RSpecialFactory.throwFullCallNeeded();
+    protected BinaryArithmeticNode createFull() {
+        return BinaryArithmeticNodeGen.create(binaryFactory, unaryFactory);
+    }
+
+    @Specialization
+    protected Object doFallback(VirtualFrame frame, Object left, Object right,
+                    @Cached("createFull()") BinaryArithmeticNode binary) {
+        return binary.call(frame, left, right);
     }
 
     protected BinaryArithmetic getOperation() {
@@ -100,11 +122,11 @@ public abstract class BinaryArithmeticSpecial extends RNode {
      */
     abstract static class IntegerBinaryArithmeticSpecial extends BinaryArithmeticSpecial {
 
-        IntegerBinaryArithmeticSpecial(BinaryArithmeticFactory opFactory) {
-            super(opFactory);
+        IntegerBinaryArithmeticSpecial(BinaryArithmeticFactory binaryFactory, UnaryArithmeticFactory unaryFactory) {
+            super(binaryFactory, unaryFactory);
         }
 
-        @Specialization
+        @Specialization(insertBefore = "doFallback")
         public int doIntegers(int left, int right,
                         @Cached("createBinaryProfile()") ConditionProfile naProfile) {
             if (naProfile.profile(RRuntime.isNA(left) || RRuntime.isNA(right))) {
@@ -114,7 +136,7 @@ public abstract class BinaryArithmeticSpecial extends RNode {
             return getOperation().op(left, right);
         }
 
-        @Specialization
+        @Specialization(insertBefore = "doFallback")
         public double doIntDouble(int left, double right,
                         @Cached("createBinaryProfile()") ConditionProfile naProfile) {
             if (naProfile.profile(RRuntime.isNA(left) || RRuntime.isNA(right))) {
@@ -124,12 +146,16 @@ public abstract class BinaryArithmeticSpecial extends RNode {
             return getOperation().op(left, right);
         }
 
-        @Specialization
+        @Specialization(insertBefore = "doFallback")
         public double doDoubleInt(double left, int right,
-                        @Cached("createBinaryProfile()") ConditionProfile naProfile) {
-            if (naProfile.profile(RRuntime.isNA(left) || RRuntime.isNA(right))) {
+                        @Cached("createBinaryProfile()") ConditionProfile leftNanProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile rightNaProfile) {
+            if (leftNanProfile.profile(Double.isNaN(left))) {
+                checkFullCallNeededOnNA();
+                return left;
+            } else if (rightNaProfile.profile(RRuntime.isNA(right))) {
                 checkFullCallNeededOnNA();
-                return isNaN(left) ? Double.NaN : RRuntime.DOUBLE_NA;
+                return RRuntime.DOUBLE_NA;
             }
             return getOperation().op(left, right);
         }
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 0a8d63ec7ed252318654e764ef1e79573fbcfcf3..4aac9d4b03aa25c3b7117f06684dac68da56df95 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
@@ -35,9 +35,18 @@ import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RComplex;
+import com.oracle.truffle.r.runtime.data.RComplexVector;
+import com.oracle.truffle.r.runtime.data.RDoubleVector;
+import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLanguage;
+import com.oracle.truffle.r.runtime.data.RLogicalVector;
+import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RString;
+import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
+import com.oracle.truffle.r.runtime.data.RVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
@@ -153,19 +162,66 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 {
         return RString.valueOf(RDeparse.deparse(val, RDeparse.MAX_CUTOFF, false, RDeparse.KEEPINTEGER, -1));
     }
 
+    protected static boolean isOneList(Object left, Object right) {
+        return isRAbstractListVector(left) ^ isRAbstractListVector(right);
+    }
+
+    @Specialization(guards = {"isOneList(left, right)"})
+    protected Object doList(VirtualFrame frame, RAbstractVector left, RAbstractVector right,
+                    @Cached("create()") CastTypeNode cast,
+                    @Cached("createRecursive()") BinaryBooleanNode recursive) {
+        Object recursiveLeft = left;
+        if (isRAbstractListVector(left)) {
+            recursiveLeft = castListToAtomic(left, cast, right.getRType());
+        }
+        Object recursiveRight = right;
+        if (isRAbstractListVector(right)) {
+            recursiveRight = castListToAtomic(right, cast, left.getRType());
+        }
+        return recursive.execute(frame, recursiveLeft, recursiveRight);
+    }
+
+    @TruffleBoundary
+    private static Object castListToAtomic(RAbstractVector source, CastTypeNode cast, RType type) {
+        RVector<?> result = type.create(source.getLength(), false);
+        Object store = result.getInternalStore();
+        for (int i = 0; i < source.getLength(); i++) {
+            Object value = source.getDataAtAsObject(i);
+            if (type == RType.Character) {
+                value = RDeparse.deparse(value);
+                ((RStringVector) result).setDataAt(store, i, (String) value);
+            } else {
+                value = cast.execute(value, type);
+                if (value instanceof RAbstractVector && ((RAbstractVector) value).getLength() == 1) {
+                    value = ((RAbstractVector) value).getDataAtAsObject(0);
+                }
+                if (type == RType.Integer && value instanceof Integer) {
+                    ((RIntVector) result).setDataAt(store, i, (int) value);
+                } else if (type == RType.Double && value instanceof Double) {
+                    ((RDoubleVector) result).setDataAt(store, i, (double) value);
+                } else if (type == RType.Logical && value instanceof Byte) {
+                    ((RLogicalVector) result).setDataAt(store, i, (byte) value);
+                } else if (type == RType.Complex && value instanceof RComplex) {
+                    ((RComplexVector) result).setDataAt(store, i, (RComplex) value);
+                } else if (type == RType.Raw && value instanceof RRaw) {
+                    ((RRawVector) result).setRawDataAt(store, i, ((RRaw) value).getValue());
+                }
+            }
+        }
+        return result;
+    }
+
     protected BinaryBooleanNode createRecursive() {
         return BinaryBooleanNode.create(factory);
     }
 
-    @SuppressWarnings("unused")
     @Specialization(guards = {"isRNullOrEmptyAndNotMissing(left, right)"})
-    protected static Object doEmptyOrNull(Object left, Object right) {
+    protected static Object doEmptyOrNull(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") Object right) {
         return RType.Logical.getEmpty();
     }
 
-    @SuppressWarnings("unused")
     @Specialization(guards = {"(isRMissing(left) || isRMissing(right))"})
-    protected Object doOneArg(Object left, Object right) {
+    protected Object doOneArg(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") Object right) {
         throw error(RError.Message.IS_OF_WRONG_ARITY, 1, factory.createOperation().opName(), 2);
     }
 
@@ -181,9 +237,8 @@ public abstract class BinaryBooleanNode extends RBuiltinNode.Arg2 {
         return (isRAbstractVector(value) && ((RAbstractVector) value).getLength() == 0);
     }
 
-    @SuppressWarnings("unused")
     @Fallback
-    protected Object doInvalidType(Object left, Object right) {
+    protected Object doInvalidType(@SuppressWarnings("unused") Object left, @SuppressWarnings("unused") Object right) {
         throw error(Message.OPERATIONS_NUMERIC_LOGICAL_COMPLEX);
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
index 444696a3f70eddfded9e68f72af65a821195e2c9..00ca1de4b2fd47b3fb02d295656e62d46701a4d6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanScalarNode.java
@@ -26,8 +26,12 @@ import com.oracle.truffle.api.CompilerAsserts;
 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.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.binary.BinaryBooleanScalarNodeGen.LogicalScalarCastNodeGen;
@@ -39,6 +43,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.BooleanOperation;
 import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory;
@@ -85,6 +90,7 @@ public abstract class BinaryBooleanScalarNode extends RBuiltinNode.Arg2 {
         return left;
     }
 
+    @ImportStatic({ForeignArray2R.class, Message.class})
     protected abstract static class LogicalScalarCastNode extends RBaseNode {
 
         protected static final int CACHE_LIMIT = 3;
@@ -147,6 +153,19 @@ public abstract class BinaryBooleanScalarNode extends RBuiltinNode.Arg2 {
             return null;
         }
 
+        @Specialization(guards = {"isForeignVector(operand, hasSize)"})
+        protected byte doForeignVector(TruffleObject operand,
+                        @Cached("HAS_SIZE.createNode()") Node hasSize,
+                        @Cached("createForeignArray2R()") ForeignArray2R foreignArray2R,
+                        @Cached("createRecursive()") LogicalScalarCastNode recursive) {
+            Object o = foreignArray2R.execute(operand, true);
+            return recursive.executeCast(o);
+        }
+
+        protected LogicalScalarCastNode createRecursive() {
+            return LogicalScalarCastNodeGen.create(opName, argumentName, check);
+        }
+
         @Fallback
         protected byte doFallback(@SuppressWarnings("unused") Object operand) {
             throw RError.error(this, RError.Message.INVALID_TYPE_IN, argumentName, opName);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
index 965ea3aa0343b8228cbad4d89ebaf6c77639dad6..70f34a3d31d1afd35087958cefe70a8de97c20a1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java
@@ -772,7 +772,7 @@ public final class CastBuilder {
         public static Function<Object, String> typeName() {
             return arg -> {
                 CompilerAsserts.neverPartOfCompilation();
-                return ((RTypedValue) RRuntime.asAbstractVector(arg)).getRType().getName();
+                return RRuntime.isForeignObject(arg) ? "external object" : ((RTypedValue) RRuntime.convertScalarVectors(arg)).getRType().getName();
             };
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
index 7b9821cf939a82abfaf28afd57fa7eda7a5fad15..3be03b99133e8b48791416edae3f4fbcfcbdcb0b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/InternalNode.java
@@ -42,8 +42,6 @@ import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.REmpty;
-import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -126,16 +124,15 @@ public abstract class InternalNode extends OperatorNode {
                 throw RError.error(RError.SHOW_CALLER, Message.INVALID_ARG, ".Internal()");
             }
 
-            RFunction function = RContext.lookupBuiltin(name);
-            if (function == null || function.isBuiltin() && function.getRBuiltin().getKind() != RBuiltinKind.INTERNAL) {
+            RBuiltinFactory factory = (RBuiltinFactory) RContext.lookupBuiltinDescriptor(name);
+            if (factory == null || factory.getKind() != RBuiltinKind.INTERNAL) {
                 // determine whether we're supposed to implement this builtin
-                if (function == null && NOT_IMPLEMENTED.contains(name)) {
+                if (factory == null && NOT_IMPLEMENTED.contains(name)) {
                     throw RInternalError.unimplemented(".Internal " + name);
                 }
                 throw RError.error(RError.SHOW_CALLER, RError.Message.NO_SUCH_INTERNAL, name);
             }
 
-            RBuiltinFactory factory = (RBuiltinFactory) function.getRBuiltin();
             RSyntaxElement[] callArgs = call.getSyntaxArguments();
             if (needsCopy) {
                 callArgs = callArgs.clone();
@@ -246,7 +243,6 @@ public abstract class InternalNode extends OperatorNode {
             Object[] args = new Object[arguments.length];
             for (int i = 0; i < args.length; i++) {
                 args[i] = arguments[i].execute(frame);
-                assert !(args[i] instanceof RPromise);
             }
             return args;
         }
@@ -275,7 +271,6 @@ public abstract class InternalNode extends OperatorNode {
                     value = forcePromises(frame, (RArgsValuesAndNames) value);
                 }
                 args[i] = value;
-                assert !(args[i] instanceof RPromise);
             }
             return args;
         }
@@ -284,7 +279,6 @@ public abstract class InternalNode extends OperatorNode {
             Object[] array = new Object[varArgs.getLength()];
             for (int i = 0; i < array.length; i++) {
                 array[i] = promiseHelper.checkEvaluate(frame, varArgs.getArgument(i));
-                assert !(array[i] instanceof RPromise);
             }
             return new RArgsValuesAndNames(array, varArgs.getSignature());
         }
@@ -307,12 +301,10 @@ public abstract class InternalNode extends OperatorNode {
 
             for (int i = 0; i < args.length - 1; i++) {
                 args[i] = arguments[i].execute(frame);
-                assert !(args[i] instanceof RPromise);
             }
             Object[] varArgs = new Object[arguments.length - (factory.getSignature().getLength() - 1)];
             for (int i = 0; i < varArgs.length; i++) {
                 varArgs[i] = arguments[args.length - 1 + i].execute(frame);
-                assert !(varArgs[i] instanceof RPromise);
             }
             args[args.length - 1] = new RArgsValuesAndNames(varArgs, ArgumentsSignature.empty(varArgs.length));
             return args;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
index 90e34ba0ecdbde856e17300a70ec6a40eea09bce..bccdcb3119d398dc1f845849cb69260d43682f20 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinFactory.java
@@ -36,9 +36,10 @@ public final class RBuiltinFactory extends RBuiltinDescriptor {
 
     private final Supplier<RBuiltinNode> constructor;
 
-    RBuiltinFactory(String name, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs, boolean splitCaller,
+    RBuiltinFactory(String name, Class<?> builtinMetaClass, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs,
+                    boolean splitCaller,
                     boolean alwaysSplit, RDispatch dispatch, String genericName, Supplier<RBuiltinNode> constructor, RBehavior behavior, RSpecialFactory specialCall) {
-        super(name, builtinNodeClass, visibility, aliases, kind, signature, nonEvalArgs, splitCaller, alwaysSplit, dispatch, genericName, behavior, specialCall);
+        super(name, builtinMetaClass, builtinNodeClass, visibility, aliases, kind, signature, nonEvalArgs, splitCaller, alwaysSplit, dispatch, genericName, behavior, specialCall);
         this.constructor = constructor;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
index 32eb510cc7ad64356f927f4ade21c5daef213820..59f8e137407371489ff75d290648b83bf1eeb627 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java
@@ -28,6 +28,7 @@ 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.nodes.ExplodeLoop;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.AccessArgumentNode;
 import com.oracle.truffle.r.nodes.function.FormalArguments;
@@ -37,8 +38,11 @@ import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public final class RBuiltinRootNode extends RRootNode {
 
@@ -48,12 +52,17 @@ public final class RBuiltinRootNode extends RRootNode {
 
     private final RBuiltinFactory factory;
 
-    RBuiltinRootNode(RBuiltinFactory factory, FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
-        super(frameDescriptor, fastPath);
+    RBuiltinRootNode(TruffleRLanguage language, RBuiltinFactory factory, FrameDescriptor frameDescriptor, FastPathFactory fastPath) {
+        super(language, frameDescriptor, fastPath);
         this.factory = factory;
         this.args = new AccessArgumentNode[factory.getSignature().getLength()];
     }
 
+    @Override
+    public SourceSection getSourceSection() {
+        return RSyntaxNode.INTERNAL;
+    }
+
     @Override
     public FormalArguments getFormalArguments() {
         initialize();
@@ -70,7 +79,7 @@ public final class RBuiltinRootNode extends RRootNode {
     public RootCallTarget duplicateWithNewFrameDescriptor() {
         FrameDescriptor frameDescriptor = new FrameDescriptor();
         FrameSlotChangeMonitor.initializeFunctionFrameDescriptor("builtin", frameDescriptor);
-        return Truffle.getRuntime().createCallTarget(new RBuiltinRootNode(factory, frameDescriptor, getFastPath()));
+        return Truffle.getRuntime().createCallTarget(new RBuiltinRootNode(getLanguage(RContext.getTruffleRLanguage()), factory, frameDescriptor, getFastPath()));
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..450f30bb90ad4b7d6600b949ccf308d7a3e47e61
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/CastForeignNode.java
@@ -0,0 +1,52 @@
+/*
+ * 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.nodes.builtin.casts;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.nodes.unary.CastNode;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+
+@ImportStatic({ForeignArray2R.class, Message.class})
+public abstract class CastForeignNode extends CastNode {
+
+    protected CastForeignNode() {
+    }
+
+    @Specialization(guards = {"isForeignVector(obj, hasSize)"})
+    protected Object castForeign(TruffleObject obj,
+                    @Cached("HAS_SIZE.createNode()") Node hasSize,
+                    @Cached("createForeignArray2R()") ForeignArray2R foreignArray2R) {
+        return foreignArray2R.execute(obj, true);
+    }
+
+    @Fallback
+    protected Object passThrough(Object x) {
+        return x;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java
index 4c163d8518f554858d58b6ade8a9d286af81981b..a5b1b9b4a4701a404d06f1b97081fc4c14a7a87a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/ExecutionPathVisitor.java
@@ -94,5 +94,4 @@ public abstract class ExecutionPathVisitor<T> implements PipelineStepVisitor<T>
             return null;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
index ad1729b0ab65416d363f3ab32156920839f55275..4a644f967f71829869af582ee5f85017766acb47 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/Filter.java
@@ -166,7 +166,6 @@ public abstract class Filter<T, R extends T> {
         public ResultForArg resultForMissing() {
             return ResultForArg.FALSE;
         }
-
     }
 
     /**
@@ -393,7 +392,6 @@ public abstract class Filter<T, R extends T> {
                 return ResultForArg.FALSE;
             }
         }
-
     }
 
     public abstract static class MatrixFilter<T extends RAbstractVector> extends Filter<T, T> {
@@ -597,7 +595,6 @@ public abstract class Filter<T, R extends T> {
             public ResultForArg or(ResultForArg other) {
                 return TRUE;
             }
-
         },
         FALSE {
 
@@ -615,7 +612,6 @@ public abstract class Filter<T, R extends T> {
             public ResultForArg or(ResultForArg other) {
                 return other;
             }
-
         },
         UNDEFINED {
 
@@ -641,5 +637,4 @@ public abstract class Filter<T, R extends T> {
 
         public abstract ResultForArg or(ResultForArg other);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
index 607f55a25861a11743c224f8c488bb4f2dc0e505..0e487adfd247a494ecf1bfeac924c0813216b5c0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineConfig.java
@@ -35,12 +35,14 @@ public class PipelineConfig {
     private final String argumentName;
     private final MessageData defaultError;
     private final MessageData defaultWarning;
-    private boolean valueForwarding;
+    private final boolean valueForwarding;
+    private final boolean castForeign;
 
-    public PipelineConfig(String argumentName, MessageData defaultError, MessageData defaultWarning, boolean valueForwarding) {
+    public PipelineConfig(String argumentName, MessageData defaultError, MessageData defaultWarning, boolean valueForwarding, boolean castForeign) {
         this.defaultError = defaultError;
         this.defaultWarning = defaultWarning;
         this.valueForwarding = valueForwarding;
+        this.castForeign = castForeign;
         this.argumentName = argumentName;
     }
 
@@ -63,4 +65,8 @@ public class PipelineConfig {
     public boolean getValueForwarding() {
         return valueForwarding;
     }
+
+    public boolean getCastForeign() {
+        return castForeign;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
index 79aa7369fffad8721bea07bc47382e7d6ceeecda..12aaa0ec1f3df2f353fbc0bc633110f87b42698f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/PipelineToCastNode.java
@@ -116,7 +116,9 @@ public final class PipelineToCastNode {
         boolean singleMapStep = firstStepIn.getNext() == null && firstStepIn instanceof MapIfStep;
         PipelineStep<?, ?> firstStep = singleMapStep ? ((MapIfStep<?, ?>) firstStepIn).withoutReturns() : firstStepIn;
 
-        Supplier<CastNode> originalPipelineFactory = () -> convert(firstStep, new CastNodeFactory(config.getDefaultError(), config.getDefaultWarning(), config.getDefaultDefaultMessage()));
+        CastNode firstCastNode = config.getCastForeign() ? CastForeignNodeGen.create() : null;
+        Supplier<CastNode> originalPipelineFactory = () -> convert(firstCastNode, firstStep,
+                        new CastNodeFactory(config.getDefaultError(), config.getDefaultWarning(), config.getDefaultDefaultMessage()));
 
         if (!config.getValueForwarding()) {
             return originalPipelineFactory.get();
@@ -132,12 +134,12 @@ public final class PipelineToCastNode {
     /**
      * Converts chain of pipeline steps to cast nodes.
      */
-    private static CastNode convert(PipelineStep<?, ?> firstStep, PipelineStepVisitor<CastNode> nodeFactory) {
+    private static CastNode convert(CastNode firstCastNode, PipelineStep<?, ?> firstStep, PipelineStepVisitor<CastNode> nodeFactory) {
         if (firstStep == null) {
             return null;
         }
 
-        CastNode prevCastNode = null;
+        CastNode prevCastNode = firstCastNode;
         PipelineStep<?, ?> currCastStep = firstStep;
         while (currCastStep != null) {
             CastNode node = currCastStep.accept(nodeFactory, prevCastNode);
@@ -145,8 +147,7 @@ public final class PipelineToCastNode {
                 if (prevCastNode == null) {
                     prevCastNode = node;
                 } else {
-                    CastNode finalPrevCastNode = prevCastNode;
-                    prevCastNode = new ChainedCastNode(finalPrevCastNode, node, currCastStep.getNext() == null);
+                    prevCastNode = new ChainedCastNode(prevCastNode, node, currCastStep.getNext() == null);
                 }
             }
 
@@ -261,8 +262,8 @@ public final class PipelineToCastNode {
         public CastNode visit(MapIfStep<?, ?> step, CastNode previous) {
             @SuppressWarnings("unchecked")
             ArgumentFilter<Object, Object> condition = (ArgumentFilter<Object, Object>) ArgumentFilterFactoryImpl.INSTANCE.createFilter(step.getFilter());
-            CastNode trueCastNode = PipelineToCastNode.convert(step.getTrueBranch(), this);
-            CastNode falseCastNode = PipelineToCastNode.convert(step.getFalseBranch(), this);
+            CastNode trueCastNode = PipelineToCastNode.convert(null, step.getTrueBranch(), this);
+            CastNode falseCastNode = PipelineToCastNode.convert(null, step.getFalseBranch(), this);
             return ConditionalMapNode.create(condition, trueCastNode, falseCastNode, ResultForArg.TRUE.equals(step.getFilter().resultForNull()),
                             ResultForArg.TRUE.equals(step.getFilter().resultForMissing()), step.isReturns());
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
index 9fa3ffa3109970c15cc104782385cd2fe69235d6..8d2e7119bc9a5a976ae6b160000aa00a8cd1035a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PipelineConfigBuilder.java
@@ -39,6 +39,7 @@ public final class PipelineConfigBuilder {
     private MessageData defaultWarning;
 
     private boolean valueForwarding = true;
+    private boolean castForeign = true;
 
     public PipelineConfigBuilder(String argumentName) {
         this.argumentName = argumentName;
@@ -47,7 +48,7 @@ public final class PipelineConfigBuilder {
     }
 
     public PipelineConfig build() {
-        return new PipelineConfig(argumentName, defaultError, defaultWarning, valueForwarding);
+        return new PipelineConfig(argumentName, defaultError, defaultWarning, valueForwarding, castForeign);
     }
 
     void setDefaultError(MessageData defaultError) {
@@ -62,4 +63,9 @@ public final class PipelineConfigBuilder {
         this.valueForwarding = flag;
         return this;
     }
+
+    public PipelineConfigBuilder setCastForeignObjects(boolean flag) {
+        this.castForeign = flag;
+        return this;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
index 3c959e0bb414bd8e34556e3c3ebfff77377daf82..8a29918d6408dd60d46a1ff2fa1aa3646a0eef38 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/casts/fluent/PreinitialPhaseBuilder.java
@@ -96,6 +96,15 @@ public final class PreinitialPhaseBuilder extends InitialPhaseBuilder<Object> {
         return this;
     }
 
+    /**
+     * Determines whether foreign arrays are implicitly casted to a R vector/list or not. <br>
+     * The default setting is <code>true</code>.
+     */
+    public PreinitialPhaseBuilder castForeignObjects(boolean flag) {
+        pipelineBuilder().getPipelineConfig().setCastForeignObjects(flag);
+        return this;
+    }
+
     public PreinitialPhaseBuilder defaultWarning(Message message, Object... args) {
         pipelineBuilder().getPipelineConfig().setDefaultWarning(new MessageData(message, args));
         return this;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/AbstractLoopNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/AbstractLoopNode.java
index 723c904d36c930ecd77fc9e46a180d3ca4d6d7a8..8b44c6d0176fe299f073733c4ef47d53eda03998 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/AbstractLoopNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/AbstractLoopNode.java
@@ -22,12 +22,17 @@
  */
 package com.oracle.truffle.r.nodes.control;
 
+import com.oracle.truffle.api.instrumentation.InstrumentableFactory.WrapperNode;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.RepeatingNode;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.RRootNode;
+import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /** Marker class for loops. */
 public abstract class AbstractLoopNode extends OperatorNode {
@@ -43,13 +48,34 @@ public abstract class AbstractLoopNode extends OperatorNode {
         if (rootNode instanceof RRootNode) {
             function = rootNode.toString();
         }
-        SourceSection sourceSection = getSourceSection();
+        SourceSection sourceSection = getLazySourceSection();
         int startLine = -1;
-        if (sourceSection != null) {
+        if (sourceSection != null && sourceSection != RSyntaxNode.LAZY_DEPARSE && sourceSection != RSyntaxNode.INTERNAL && sourceSection != RSyntaxNode.SOURCE_UNAVAILABLE) {
             startLine = sourceSection.getStartLine();
         }
         RSyntaxElement call = ((RSyntaxCall) this).getSyntaxLHS();
         String name = ((RSyntaxLookup) call).getIdentifier();
         return String.format("%s-<%s:%d>", name, function, startLine);
     }
+
+    protected abstract static class AbstractRepeatingNode extends Node implements RepeatingNode {
+
+        @Child protected RNode body;
+
+        public AbstractRepeatingNode(RNode body) {
+            this.body = body;
+        }
+    }
+
+    /**
+     * Tests if the provided node is a loop-body node (also considering wrappers).
+     */
+    public static boolean isLoopBody(Node n) {
+        Node parent = n.getParent();
+        if (parent instanceof WrapperNode) {
+            Node grandparent = parent.getParent();
+            return grandparent instanceof AbstractRepeatingNode && ((AbstractRepeatingNode) grandparent).body == parent;
+        }
+        return parent instanceof AbstractRepeatingNode && ((AbstractRepeatingNode) parent).body == n;
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
index 064888fb244ae0e45205bab0e42347d81f41fa88..b66f41e9d5190bc5e5af1e36a33afe0ae0276be7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ForNode.java
@@ -22,24 +22,24 @@
  */
 package com.oracle.truffle.r.nodes.control;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.instrumentation.InstrumentableFactory.WrapperNode;
 import com.oracle.truffle.api.nodes.LoopNode;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.nodes.RepeatingNode;
 import com.oracle.truffle.api.nodes.UnexpectedResultException;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.nodes.RASTBuilder;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.AnonymousFrameVariable;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
@@ -48,11 +48,13 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyntaxCall {
 
+    @Child private RNode range;
+    @Child private RLengthNode length;
     @Child private WriteVariableNode writeLengthNode;
     @Child private WriteVariableNode writeIndexNode;
     @Child private WriteVariableNode writeRangeNode;
     @Child private LoopNode loopNode;
-    @Child private SetVisibilityNode visibility = SetVisibilityNode.create();
+    @Child private SetVisibilityNode visibility;
 
     private final RSyntaxLookup var;
 
@@ -63,18 +65,36 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn
         String rangeName = AnonymousFrameVariable.create("FOR_RANGE");
         String lengthName = AnonymousFrameVariable.create("FOR_LENGTH");
 
+        this.range = range;
+        this.length = RLengthNodeGen.create();
         this.writeIndexNode = WriteVariableNode.createAnonymous(indexName, Mode.REGULAR, null);
-        this.writeRangeNode = WriteVariableNode.createAnonymous(rangeName, Mode.REGULAR, range);
-        this.writeLengthNode = WriteVariableNode.createAnonymous(lengthName, Mode.REGULAR, RLengthNodeGen.create(ReadVariableNode.create(rangeName)));
+        this.writeRangeNode = WriteVariableNode.createAnonymous(rangeName, Mode.REGULAR, null);
+        this.writeLengthNode = WriteVariableNode.createAnonymous(lengthName, Mode.REGULAR, null);
         this.loopNode = Truffle.getRuntime().createLoopNode(new ForRepeatingNode(this, var.getIdentifier(), body, indexName, lengthName, rangeName));
     }
 
     @Override
-    public Object execute(VirtualFrame frame) {
+    public void voidExecute(VirtualFrame frame) {
+        Object obj = range.execute(frame);
         writeIndexNode.execute(frame, 1);
-        writeRangeNode.execute(frame);
-        writeLengthNode.execute(frame);
+        writeRangeNode.execute(frame, obj);
+        writeLengthNode.execute(frame, length.executeInteger(obj));
         loopNode.executeLoop(frame);
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        voidExecute(frame);
+        return RNull.instance;
+    }
+
+    @Override
+    public Object visibleExecute(VirtualFrame frame) {
+        voidExecute(frame);
+        if (visibility == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            visibility = insert(SetVisibilityNode.create());
+        }
         visibility.execute(frame, false);
         return RNull.instance;
     }
@@ -91,36 +111,35 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn
         return ((ForRepeatingNode) loopNode.getRepeatingNode()).body;
     }
 
-    private static final class ForRepeatingNode extends Node implements RepeatingNode {
+    private static final class ForRepeatingNode extends AbstractRepeatingNode {
 
         private final ConditionProfile conditionProfile = ConditionProfile.createCountingProfile();
         private final BranchProfile breakBlock = BranchProfile.create();
         private final BranchProfile nextBlock = BranchProfile.create();
 
         @Child private WriteVariableNode writeElementNode;
-        @Child private RNode body;
 
-        @Child private ReadVariableNode readIndexNode;
-        @Child private ReadVariableNode readLengthNode;
+        @Child private LocalReadVariableNode readIndexNode;
+        @Child private LocalReadVariableNode readLengthNode;
         @Child private WriteVariableNode writeIndexNode;
 
         // only used for toString
         private final ForNode forNode;
 
         ForRepeatingNode(ForNode forNode, String var, RNode body, String indexName, String lengthName, String rangeName) {
+            super(body);
             this.forNode = forNode;
             this.writeElementNode = WriteVariableNode.createAnonymous(var, Mode.REGULAR, createIndexedLoad(indexName, rangeName), false);
-            this.body = body;
 
-            this.readIndexNode = ReadVariableNode.create(indexName);
-            this.readLengthNode = ReadVariableNode.create(lengthName);
+            this.readIndexNode = LocalReadVariableNode.create(indexName, true);
+            this.readLengthNode = LocalReadVariableNode.create(lengthName, true);
             this.writeIndexNode = WriteVariableNode.createAnonymous(indexName, Mode.REGULAR, null);
             // pre-initialize the profile so that loop exits to not deoptimize
             conditionProfile.profile(false);
         }
 
         private static RNode createIndexedLoad(String indexName, String rangeName) {
-            RASTBuilder builder = new RASTBuilder();
+            RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder();
             RSyntaxNode receiver = builder.lookup(RSyntaxNode.INTERNAL, rangeName, false);
             RSyntaxNode index = builder.lookup(RSyntaxNode.INTERNAL, indexName, false);
             RSyntaxNode access = builder.lookup(RSyntaxNode.INTERNAL, "[[", true);
@@ -135,7 +154,7 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn
                 length = readLengthNode.executeInteger(frame);
                 index = readIndexNode.executeInteger(frame);
             } catch (UnexpectedResultException e1) {
-                throw new AssertionError("For index must be Integer.");
+                throw RInternalError.shouldNotReachHere("For index must be Integer.");
             }
             try {
                 if (conditionProfile.profile(index <= length)) {
@@ -165,23 +184,11 @@ public final class ForNode extends AbstractLoopNode implements RSyntaxNode, RSyn
     @Override
     public RSyntaxElement[] getSyntaxArguments() {
         ForRepeatingNode repeatingNode = (ForRepeatingNode) loopNode.getRepeatingNode();
-        return new RSyntaxElement[]{var, writeRangeNode.getRhs().asRSyntaxNode(), repeatingNode.body.asRSyntaxNode()};
+        return new RSyntaxElement[]{var, range.asRSyntaxNode(), repeatingNode.body.asRSyntaxNode()};
     }
 
     @Override
     public ArgumentsSignature getSyntaxSignature() {
         return ArgumentsSignature.empty(3);
     }
-
-    /**
-     * Tests if the provided node is a loop-body node (also considering wrappers).
-     */
-    public static boolean isLoopBody(Node n) {
-        Node parent = n.getParent();
-        if (parent instanceof WrapperNode) {
-            Node grandparent = parent.getParent();
-            return grandparent instanceof ForRepeatingNode && ((ForRepeatingNode) grandparent).body == parent;
-        }
-        return parent instanceof ForRepeatingNode && ((ForRepeatingNode) parent).body == n;
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RLengthNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RLengthNode.java
index a7a57f523a4f14412abb09f5440eb82abaf47a1a..f1e7dce2b696feb9b17f621912ad64e6a13055fb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RLengthNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RLengthNode.java
@@ -23,39 +23,42 @@
 package com.oracle.truffle.r.nodes.control;
 
 import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.NodeChild;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.ArityException;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 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.nodes.Node;
+import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 /**
  * Gets length of given container. Does not actually dispatch to the 'length' function, which may be
  * overridden for some S3/S4 classes. Check if you need to get actual length, or what the 'length'
  * function returns, like in {@code seq_along}.
  */
-@NodeChild("operand")
-public abstract class RLengthNode extends RNode {
+@ImportStatic({Message.class, ForeignArray2R.class})
+public abstract class RLengthNode extends RBaseNode {
 
-    @Override
-    public abstract int executeInteger(VirtualFrame frame);
-
-    public abstract int executeInteger(VirtualFrame frame, Object value);
+    public abstract int executeInteger(Object value);
 
     public static RLengthNode create() {
-        return RLengthNodeGen.create(null);
+        return RLengthNodeGen.create();
     }
 
     @Specialization
@@ -118,6 +121,11 @@ public abstract class RLengthNode extends RNode {
         return lengthProfile.profile(env.ls(true, null, false).getLength());
     }
 
+    @Specialization
+    protected int getLength(RArgsValuesAndNames vargs) {
+        return vargs.getLength();
+    }
+
     @Specialization
     protected int getLength(@SuppressWarnings("unused") RFunction func) {
         return 1;
@@ -135,7 +143,43 @@ public abstract class RLengthNode extends RNode {
         return RRuntime.isForeignObject(object);
     }
 
-    @Specialization(guards = "isForeignObject(object)")
+    @Specialization(guards = "isJavaIterable(object)")
+    protected int getJavaIterableSize(TruffleObject object,
+                    @Cached("READ.createNode()") Node read,
+                    @Cached("createExecute(0).createNode()") Node execute,
+                    @Cached("createBinaryProfile()") ConditionProfile profile) {
+        try {
+            Number sizeByMethod = null;
+            for (String method : new String[]{"size", "getSize", "length", "getLength"}) {
+                TruffleObject sizeFunction;
+                try {
+                    sizeFunction = (TruffleObject) ForeignAccess.sendRead(read, object, method);
+                } catch (UnknownIdentifierException ex) {
+                    continue;
+                }
+                Object value = ForeignAccess.sendExecute(execute, sizeFunction);
+                if (value instanceof Number) {
+                    sizeByMethod = (Number) value;
+                }
+            }
+            if (profile.profile(sizeByMethod != null)) {
+                return sizeByMethod.intValue();
+            }
+
+            TruffleObject itMethod = (TruffleObject) ForeignAccess.sendRead(read, object, "iterator");
+            TruffleObject it = (TruffleObject) ForeignAccess.sendExecute(execute, itMethod);
+            TruffleObject hasNextMethod = (TruffleObject) ForeignAccess.sendRead(read, it, "hasNext");
+            int size = 0;
+            while ((boolean) ForeignAccess.sendExecute(execute, hasNextMethod)) {
+                ++size;
+            }
+            return size;
+        } catch (ArityException | UnsupportedTypeException | UnknownIdentifierException | UnsupportedMessageException ex) {
+            throw error(RError.Message.GENERIC, "error while accessing java iterable: " + ex.getMessage());
+        }
+    }
+
+    @Specialization(guards = {"isForeignObject(object)", "!isJavaIterable(object)"})
     protected int getForeignSize(TruffleObject object,
                     @Cached("createHasSize()") Node hasSizeNode,
                     @Cached("createGetSize()") Node getSizeNode) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RepeatNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RepeatNode.java
index 0e489ec557ee45c7f65efc2671a0b534e2b37ef4..e29f22a7c8cfbe17721c44f97193e1e150166508 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RepeatNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/RepeatNode.java
@@ -25,8 +25,6 @@ package com.oracle.truffle.r.nodes.control;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.LoopNode;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.nodes.RepeatingNode;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
@@ -55,9 +53,7 @@ public final class RepeatNode extends AbstractLoopNode implements RSyntaxNode, R
         return RNull.instance;
     }
 
-    private static final class RepeatRepeatingNode extends Node implements RepeatingNode {
-
-        @Child private RNode body;
+    private static final class RepeatRepeatingNode extends AbstractRepeatingNode {
 
         private final BranchProfile normalBlock = BranchProfile.create();
         private final BranchProfile breakBlock = BranchProfile.create();
@@ -67,8 +63,8 @@ public final class RepeatNode extends AbstractLoopNode implements RSyntaxNode, R
         private final RepeatNode whileNode;
 
         RepeatRepeatingNode(RepeatNode whileNode, RNode body) {
+            super(body);
             this.whileNode = whileNode;
-            this.body = body;
         }
 
         @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
index cc06348a556c7376b626163fe3b21560b174c358..719b54a06200ad11ed8fb5afeefcffed841449d4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementDispatchNode.java
@@ -34,7 +34,6 @@ import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableSyntaxNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -158,16 +157,7 @@ public final class ReplacementDispatchNode extends OperatorNode {
             current = call.getSyntaxArguments()[0];
         }
         RSyntaxLookup variable = (RSyntaxLookup) current;
-        ReadVariableNode varRead = createReplacementForVariableUsing(variable, isSuper);
-        return ReplacementNode.create(getLazySourceSection(), operator, varRead, lhs.asRSyntaxNode(), rhs, calls, variable.getIdentifier(), isSuper, tempNamesStartIndex, isVoid);
-    }
-
-    private static ReadVariableNode createReplacementForVariableUsing(RSyntaxLookup var, boolean isSuper) {
-        if (isSuper) {
-            return ReadVariableNode.createSuperLookup(var.getLazySourceSection(), var.getIdentifier());
-        } else {
-            return ReadVariableNode.create(var.getLazySourceSection(), var.getIdentifier(), true);
-        }
+        return ReplacementNode.create(getLazySourceSection(), operator, variable, lhs.asRSyntaxNode(), rhs, calls, isSuper, tempNamesStartIndex, isVoid);
     }
 
     /*
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
index 2eb77334c9d86cdb3b18af0e955c8b07a448931b..bf28bec6ccf021021efe50b103d1c98c778ad9be 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReplacementNode.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.access.RemoveAndAnswerNode;
 import com.oracle.truffle.r.nodes.access.WriteVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.function.PeekLocalVariableNode;
 import com.oracle.truffle.r.nodes.function.RCallSpecialNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.nodes.unary.GetNonSharedNode;
@@ -65,8 +66,8 @@ abstract class ReplacementNode extends OperatorNode {
         return RContext.getASTBuilder().process(this).asRNode();
     }
 
-    public static ReplacementNode create(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls,
-                    String targetVarName, boolean isSuper, int tempNamesStartIndex, boolean isVoid) {
+    public static ReplacementNode create(SourceSection source, RSyntaxLookup operator, RSyntaxLookup variable, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls,
+                    boolean isSuper, int tempNamesStartIndex, boolean isVoid) {
         CompilerAsserts.neverPartOfCompilation();
         // Note: if specials are turned off in FastR, onlySpecials will never be true
         boolean createSpecial = hasOnlySpecialCalls(calls);
@@ -76,12 +77,12 @@ abstract class ReplacementNode extends OperatorNode {
              * special call for "replace".
              */
             if (isVoid) {
-                return new SpecialVoidReplacementNode(source, operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex);
+                return new SpecialVoidReplacementNode(source, operator, variable, lhs, rhs, calls, isSuper, tempNamesStartIndex);
             } else {
-                return new SpecialReplacementNode(source, operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex);
+                return new SpecialReplacementNode(source, operator, variable, lhs, rhs, calls, isSuper, tempNamesStartIndex);
             }
         } else {
-            return new GenericReplacementNode(source, operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex);
+            return new GenericReplacementNode(source, operator, variable, lhs, rhs, calls, isSuper, tempNamesStartIndex);
         }
     }
 
@@ -163,6 +164,19 @@ abstract class ReplacementNode extends OperatorNode {
         return null;
     }
 
+    private static RSyntaxNode createLookup(SourceSection source, String idenifier) {
+        return RContext.getASTBuilder().lookup(source, idenifier, false);
+    }
+
+    private static RNode createReplacementTarget(RSyntaxLookup variable, boolean isSuper, boolean localPeek) {
+        if (isSuper) {
+            return ReadVariableNode.wrap(variable.getLazySourceSection(), ReadVariableNode.createSuperLookup(variable.getIdentifier())).asRNode();
+        } else {
+            return localPeek ? new PeekLocalVariableNode(variable.getIdentifier())
+                            : ReadVariableNode.wrap(variable.getLazySourceSection(), ReadVariableNode.create(variable.getIdentifier(), true)).asRNode();
+        }
+    }
+
     private abstract static class ReplacementWithRhsNode extends ReplacementNode {
 
         @Child private WriteVariableNode storeRhs;
@@ -226,15 +240,12 @@ abstract class ReplacementNode extends OperatorNode {
         private final List<RSyntaxCall> calls;
         private final int tempNamesStartIndex;
         private final boolean isSuper;
-        private final String targetVarName;
-        private final RNode target;
+        private final RSyntaxLookup variable;
 
-        SpecialReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName,
-                        boolean isSuper, int tempNamesStartIndex) {
+        SpecialReplacementNode(SourceSection source, RSyntaxLookup operator, RSyntaxLookup variable, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, boolean isSuper, int tempNamesStartIndex) {
             super(source, operator, lhs, rhs, tempNamesStartIndex);
-            this.target = target;
+            this.variable = variable;
             this.calls = calls;
-            this.targetVarName = targetVarName;
             this.isSuper = isSuper;
             this.tempNamesStartIndex = tempNamesStartIndex;
 
@@ -242,12 +253,13 @@ abstract class ReplacementNode extends OperatorNode {
              * Creates a replacement that consists only of {@link RCallSpecialNode} calls.
              */
             CodeBuilderContext codeBuilderContext = new CodeBuilderContext(tempNamesStartIndex + 2);
-            RNode extractFunc = target;
+            RNode extractFunc = createReplacementTarget(variable, isSuper, true);
             for (int i = calls.size() - 1; i >= 1; i--) {
                 extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext);
                 ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException();
             }
-            this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), ReadVariableNode.create(getRHSTemp(tempNamesStartIndex)), calls.get(0), codeBuilderContext);
+            this.replaceCall = (RCallSpecialNode) createFunctionUpdate(source, extractFunc.asRSyntaxNode(), createLookup(RSyntaxNode.INTERNAL, getRHSTemp(tempNamesStartIndex)), calls.get(0),
+                            codeBuilderContext);
             this.replaceCall.setPropagateFullCallNeededException();
         }
 
@@ -261,7 +273,8 @@ abstract class ReplacementNode extends OperatorNode {
                 replaceCall.execute(frame);
             } catch (FullCallNeededException e) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                replace(new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex)).executeReplacement(frame);
+                replace(new GenericReplacementNode(getLazySourceSection(), operator, variable, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), calls, isSuper,
+                                tempNamesStartIndex)).executeReplacement(frame);
             }
         }
     }
@@ -279,16 +292,14 @@ abstract class ReplacementNode extends OperatorNode {
         private final List<RSyntaxCall> calls;
         private final int tempNamesStartIndex;
         private final boolean isSuper;
-        private final String targetVarName;
-        private final RNode target;
+        private final RSyntaxLookup variable;
 
-        SpecialVoidReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName,
-                        boolean isSuper, int tempNamesStartIndex) {
+        SpecialVoidReplacementNode(SourceSection source, RSyntaxLookup operator, RSyntaxLookup variable, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, boolean isSuper,
+                        int tempNamesStartIndex) {
             super(source, operator, lhs);
-            this.target = target;
+            this.variable = variable;
             this.rhs = rhs;
             this.calls = calls;
-            this.targetVarName = targetVarName;
             this.isSuper = isSuper;
             this.tempNamesStartIndex = tempNamesStartIndex;
 
@@ -296,7 +307,7 @@ abstract class ReplacementNode extends OperatorNode {
              * Creates a replacement that consists only of {@link RCallSpecialNode} calls.
              */
             CodeBuilderContext codeBuilderContext = new CodeBuilderContext(tempNamesStartIndex + 2);
-            RNode extractFunc = target;
+            RNode extractFunc = createReplacementTarget(variable, isSuper, true);
             for (int i = calls.size() - 1; i >= 1; i--) {
                 extractFunc = createSpecialFunctionQuery(calls.get(i), extractFunc.asRSyntaxNode(), codeBuilderContext);
                 ((RCallSpecialNode) extractFunc).setPropagateFullCallNeededException();
@@ -308,7 +319,8 @@ abstract class ReplacementNode extends OperatorNode {
         @Override
         public Object execute(VirtualFrame frame) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            GenericReplacementNode replacement = new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex);
+            GenericReplacementNode replacement = new GenericReplacementNode(getLazySourceSection(), operator, variable, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), calls,
+                            isSuper, tempNamesStartIndex);
             return replace(replacement).execute(frame);
         }
 
@@ -322,7 +334,9 @@ abstract class ReplacementNode extends OperatorNode {
                 replaceCall.execute(frame);
             } catch (FullCallNeededException e) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                GenericReplacementNode replacement = replace(new GenericReplacementNode(getLazySourceSection(), operator, target, lhs, rhs, calls, targetVarName, isSuper, tempNamesStartIndex));
+                GenericReplacementNode replacement = replace(
+                                new GenericReplacementNode(getLazySourceSection(), operator, variable, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(),
+                                                calls, isSuper, tempNamesStartIndex));
 
                 if (e.rhsValue == null) {
                     // we haven't queried the rhs value yet
@@ -349,9 +363,8 @@ abstract class ReplacementNode extends OperatorNode {
 
         @Children private final WriteVariableNode[] updates;
 
-        GenericReplacementNode(SourceSection source, RSyntaxLookup operator, RNode target, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, String targetVarName, boolean isSuper,
-                        int tempNamesStartIndex) {
-            super(source, operator, lhs, RContext.getASTBuilder().process(rhs.asRSyntaxNode()).asRNode(), tempNamesStartIndex);
+        GenericReplacementNode(SourceSection source, RSyntaxLookup operator, RSyntaxLookup variable, RSyntaxElement lhs, RNode rhs, List<RSyntaxCall> calls, boolean isSuper, int tempNamesStartIndex) {
+            super(source, operator, lhs, rhs, tempNamesStartIndex);
             /*
              * When there are more than two function calls in LHS, then we save some function calls
              * by saving the intermediate results into temporary variables and reusing them.
@@ -360,6 +373,7 @@ abstract class ReplacementNode extends OperatorNode {
             CodeBuilderContext codeBuilderContext = new CodeBuilderContext(tempNamesStartIndex + calls.size() + 1);
 
             int targetIndex = tempNamesStartIndex;
+            RNode target = createReplacementTarget(variable, isSuper, false);
             instructions.add(WriteVariableNode.createAnonymous(getTargetTemp(targetIndex), WriteVariableNode.Mode.INVISIBLE, wrapForSlotUpdate(target, calls.get(calls.size() - 1))));
             /*
              * Create the calls that extract inner components - only needed for complex replacements
@@ -369,7 +383,7 @@ abstract class ReplacementNode extends OperatorNode {
              * replacement, 'x' in our example (the assignment from 'x' is not done in this loop).
              */
             for (int i = calls.size() - 1; i >= 1; i--) {
-                ReadVariableNode newFirstArg = ReadVariableNode.create(getTargetTemp(targetIndex));
+                RSyntaxNode newFirstArg = createLookup(RSyntaxNode.INTERNAL, getTargetTemp(targetIndex));
                 RNode extract = createSpecialFunctionQuery(calls.get(i), newFirstArg, codeBuilderContext);
                 instructions.add(WriteVariableNode.createAnonymous(getTargetTemp(++targetIndex), WriteVariableNode.Mode.INVISIBLE, wrapForSlotUpdate(extract, calls.get(i - 1))));
             }
@@ -379,12 +393,13 @@ abstract class ReplacementNode extends OperatorNode {
              */
             int replacementIndex = tempNamesStartIndex;
             for (int i = 0; i < calls.size(); i++) {
-                RNode update = createFunctionUpdate(source, ReadVariableNode.create(getTargetTemp(targetIndex--)), ReadVariableNode.create(getRHSTemp(replacementIndex)), calls.get(i),
+                RNode update = createFunctionUpdate(source, createLookup(RSyntaxNode.INTERNAL, getTargetTemp(targetIndex--)), createLookup(RSyntaxNode.INTERNAL, getRHSTemp(replacementIndex)),
+                                calls.get(i),
                                 codeBuilderContext);
                 if (i < calls.size() - 1) {
                     instructions.add(WriteVariableNode.createAnonymous(getRHSTemp(++replacementIndex), WriteVariableNode.Mode.INVISIBLE, update));
                 } else {
-                    instructions.add(WriteVariableNode.createAnonymous(targetVarName, WriteVariableNode.Mode.REGULAR, update, isSuper));
+                    instructions.add(WriteVariableNode.createAnonymous(variable.getIdentifier(), WriteVariableNode.Mode.REGULAR, update, isSuper));
                 }
             }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/WhileNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/WhileNode.java
index 9ff7b83674a1860f9399ab55e07dcaed03b0f24b..b41dc4b0873dd05685e19b53f152348dd592d570 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/WhileNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/WhileNode.java
@@ -25,8 +25,6 @@ package com.oracle.truffle.r.nodes.control;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.LoopNode;
-import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.nodes.RepeatingNode;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.SourceSection;
@@ -66,10 +64,9 @@ public final class WhileNode extends AbstractLoopNode implements RSyntaxNode, RS
         return ((WhileRepeatingNode) loop.getRepeatingNode()).body;
     }
 
-    private static final class WhileRepeatingNode extends Node implements RepeatingNode {
+    private static final class WhileRepeatingNode extends AbstractRepeatingNode {
 
         @Child private ConvertBooleanNode condition;
-        @Child private RNode body;
 
         private final ConditionProfile conditionProfile = ConditionProfile.createCountingProfile();
         private final BranchProfile normalBlock = BranchProfile.create();
@@ -80,9 +77,9 @@ public final class WhileNode extends AbstractLoopNode implements RSyntaxNode, RS
         private final WhileNode whileNode;
 
         WhileRepeatingNode(WhileNode whileNode, ConvertBooleanNode condition, RNode body) {
+            super(body);
             this.whileNode = whileNode;
             this.condition = condition;
-            this.body = body;
             // pre-initialize the profile so that loop exits to not deoptimize
             conditionProfile.profile(false);
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
deleted file mode 100644
index f1420a80ceb006a19d14f758496a16e642c608f3..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/FFIUpCallRootNode.java
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * 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
- * 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.ffi;
-
-import java.util.function.Supplier;
-
-import com.oracle.truffle.api.RootCallTarget;
-import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.frame.FrameDescriptor;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.RootNode;
-import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CADDRNodeGen;
-import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CADRNodeGen;
-import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CARNodeGen;
-import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDDRNodeGen;
-import com.oracle.truffle.r.nodes.ffi.ListAccessNodesFactory.CDRNodeGen;
-import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.LENGTHNodeGen;
-import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoNewObjectNodeGen;
-import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoSlotNodeGen;
-import com.oracle.truffle.r.nodes.ffi.MiscNodesFactory.RDoSlotAssignNodeGen;
-import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.context.RContext;
-
-public final class FFIUpCallRootNode extends RootNode {
-    private static final RootCallTarget[] rootCallTargets = new RootCallTarget[RFFIUpCallMethod.values().length];
-
-    @Child private FFIUpCallNode theFFIUpCallNode;
-    private final int numArgs;
-
-    @SuppressWarnings("deprecation")
-    private FFIUpCallRootNode(FFIUpCallNode child) {
-        super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
-        theFFIUpCallNode = child;
-        this.numArgs = child.numArgs();
-    }
-
-    @Override
-    public Object execute(VirtualFrame frame) {
-        Object[] args = frame.getArguments();
-        switch (numArgs) {
-            case 0:
-                return ((FFIUpCallNode.Arg0) theFFIUpCallNode).executeObject();
-            case 1:
-                return ((FFIUpCallNode.Arg1) theFFIUpCallNode).executeObject(args[0]);
-            case 2:
-                return ((FFIUpCallNode.Arg2) theFFIUpCallNode).executeObject(args[0], args[1]);
-            case 3:
-                return ((FFIUpCallNode.Arg3) theFFIUpCallNode).executeObject(args[0], args[1], args[2]);
-            default:
-                throw RInternalError.shouldNotReachHere();
-        }
-    }
-
-    static void add(RFFIUpCallMethod upCallMethod, Supplier<FFIUpCallNode> constructor) {
-
-        FFIUpCallRootNode rootNode = new FFIUpCallRootNode(constructor.get());
-        rootCallTargets[upCallMethod.ordinal()] = Truffle.getRuntime().createCallTarget(rootNode);
-    }
-
-    public static RootCallTarget getCallTarget(RFFIUpCallMethod upCallMethod) {
-        RootCallTarget target = rootCallTargets[upCallMethod.ordinal()];
-        assert target != null;
-        return target;
-    }
-
-    static void register() {
-        FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_asReal, AsRealNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_asLogical, AsLogicalNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_asInteger, AsIntegerNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_asChar, AsCharNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.Rf_coerceVector, CoerceVectorNode::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.CAR, CARNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.CDR, CDRNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.CADR, CADRNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.CADDR, CADDRNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.CDDR, CDDRNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.LENGTH, LENGTHNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_new_object, RDoNewObjectNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_slot, RDoSlotNodeGen::create);
-        FFIUpCallRootNode.add(RFFIUpCallMethod.R_do_slot_assign, RDoSlotAssignNodeGen::create);
-    }
-
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
deleted file mode 100644
index 218f407e58ce9c011ad1f2ed260a191360236f0d..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/RFFIUpCallMethod.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (c) 2017, 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.ffi;
-
-import com.oracle.truffle.r.runtime.ffi.UpCallsRFFI;
-
-/**
- * Generated from {@link UpCallsRFFI}. Any native code that is dependent on the ordinal value of
- * these enums must be kept in sync. The {@link #main} method will generate the appropriate C
- * #define statements.
- */
-public enum RFFIUpCallMethod {
-    CADDR("(object) : object"),
-    CADR("(object) : object"),
-    CAR("(object) : object"),
-    CDDR("(object) : object"),
-    CDR("(object) : object"),
-    DUPLICATE_ATTRIB("(object, object) : void"),
-    ENCLOS("(object) : object"),
-    GetRNGstate("() : void"),
-    INTEGER("(object) : object"),
-    IS_S4_OBJECT("(object) : sint32"),
-    SET_S4_OBJECT("(object) : void"),
-    UNSET_S4_OBJECT("(object) : void"),
-    LENGTH("(object) : sint32"),
-    LOGICAL("(object) : object"),
-    NAMED("(object) : sint32"),
-    OBJECT("(object) : sint32"),
-    PRCODE("(object) : object"),
-    PRENV("(object) : object"),
-    PRINTNAME("(object) : object"),
-    PRSEEN("(object) : sint32"),
-    PRVALUE("(object) : object"),
-    PutRNGstate("() : void"),
-    RAW("(object) : object"),
-    RDEBUG("(object) : sint32"),
-    REAL("(object) : object"),
-    RSTEP("(object) : sint32"),
-    R_BaseEnv("() : object"),
-    R_BaseNamespace("() : object"),
-    R_BindingIsLocked("(object, object) : sint32"),
-    R_CHAR("(object) : object"),
-    R_CleanUp("(sint32, sint32, sint32) : void"),
-    R_ExternalPtrAddr("(object) : object"),
-    R_ExternalPtrProtected("(object) : object"),
-    R_ExternalPtrTag("(object) : object"),
-    R_FindNamespace("(object) : object"),
-    R_GetConnection("(sint32) : object"),
-    R_GlobalContext("() : object"),
-    R_GlobalEnv("() : object"),
-    R_HomeDir("() : object"),
-    R_Interactive("() : sint32"),
-    R_MakeExternalPtr("(object, object, object) : object"),
-    R_MethodsNamespace("() : object"),
-    R_NamespaceRegistry("() : object"),
-    R_NewHashedEnv("(object, object) : object"),
-    R_ParseVector("(object, sint32, object) : object"),
-    R_PromiseExpr("(object) : object"),
-    R_ReadConnection("(sint32, object) : sint32"),
-    R_SetExternalPtrAddr("(object, object) : void"),
-    R_SetExternalPtrProtected("(object, object) : void"),
-    R_SetExternalPtrTag("(object, object) : void"),
-    R_ToplevelExec("() : object"),
-    R_WriteConnection("(sint32, object) : sint32"),
-    R_compute_identical("(object, object, sint32) : sint32"),
-    R_do_MAKE_CLASS("(string) : object"),
-    R_do_new_object("(object) : object"),
-    R_do_slot("(object, object) : object"),
-    R_do_slot_assign("(object, object, object) : object"),
-    R_getContextCall("(object) : object"),
-    R_getContextEnv("(object) : object"),
-    R_getContextFun("(object) : object"),
-    R_getContextSrcRef("(object) : object"),
-    R_getGlobalFunctionContext("() : object"),
-    R_getParentFunctionContext("(object) : object"),
-    R_insideBrowser("() : sint32"),
-    R_isEqual("(object, object) : sint32"),
-    R_isGlobal("(object) : sint32"),
-    R_lsInternal3("(object, sint32, sint32) : object"),
-    R_new_custom_connection("(string, string, string, object) : object"),
-    R_tryEval("(object, object, object) : object"),
-    Rf_GetOption1("(object) : object"),
-    Rf_PairToVectorList("(object) : object"),
-    Rf_ScalarDouble("(double) : object"),
-    Rf_ScalarInteger("(sint32) : object"),
-    Rf_ScalarLogical("(sint32) : object"),
-    Rf_ScalarString("(object) : object"),
-    Rf_allocArray("(sint32, object) : object"),
-    Rf_allocMatrix("(sint32, sint32, sint32) : object"),
-    Rf_allocVector("(sint32, sint32) : object"),
-    Rf_any_duplicated("(object, sint32) : sint32"),
-    Rf_asChar("(object) : object"),
-    Rf_asInteger("(object) : sint32"),
-    Rf_asLogical("(object) : sint32"),
-    Rf_asReal("(object) : double"),
-    Rf_classgets("(object, object) : object"),
-    Rf_coerceVector("(object, sint32) : object"),
-    Rf_cons("(object, object) : object"),
-    Rf_copyListMatrix("(object, object, sint32) : void"),
-    Rf_copyMatrix("(object, object, sint32) : void"),
-    Rf_defineVar("(object, object, object) : void"),
-    Rf_duplicate("(object, sint32) : object"),
-    Rf_error("(string) : void"),
-    Rf_eval("(object, object) : object"),
-    Rf_findVar("(object, object) : object"),
-    Rf_findVarInFrame("(object, object) : object"),
-    Rf_findVarInFrame3("(object, object, sint32) : object"),
-    Rf_findFun("(object, object) : object"),
-    Rf_getAttrib("(object, object) : object"),
-    Rf_gsetVar("(object, object, object) : void"),
-    Rf_inherits("(string, object) : sint32"),
-    Rf_install("(string) : object"),
-    Rf_installChar("(object) : object"),
-    Rf_isNull("(object) : sint32"),
-    Rf_isString("(object) : sint32"),
-    Rf_lengthgets("(object, sint32) : object"),
-    Rf_mkCharLenCE("(pointer, sint32, sint32) : object"),
-    Rf_ncols("(object) : sint32"),
-    Rf_nrows("(object) : sint32"),
-    Rf_setAttrib("(object, object, object) : void"),
-    Rf_warning("(string) : void"),
-    Rf_warningcall("(object, string) : void"),
-    Rprintf("(string) : void"),
-    SETCADR("(object, object) : object"),
-    SETCAR("(object, object) : object"),
-    SETCDR("(object, object) : object"),
-    SET_RDEBUG("(object, sint32) : void"),
-    SET_RSTEP("(object, sint32) : void"),
-    SET_STRING_ELT("(object, sint32, object) : void"),
-    SET_SYMVALUE("(object, object) : void"),
-    SET_TAG("(object, object) : object"),
-    SET_TYPEOF_FASTR("(object, sint32) : object"),
-    SET_VECTOR_ELT("(object, sint32, object) : void"),
-    STRING_ELT("(object, sint32) : object"),
-    SYMVALUE("(object) : object"),
-    TAG("(object) : object"),
-    TYPEOF("(object) : sint32"),
-    VECTOR_ELT("(object, sint32) : object"),
-    getConnectionClassString("(object) : object"),
-    getOpenModeString("(object) : object"),
-    getSummaryDescription("(object) : object"),
-    isSeekable("(object) : object"),
-    unif_rand("() : double");
-
-    /**
-     * The signature used for the upcall in Truffle NFI.
-     */
-    public final String nfiSignature;
-
-    RFFIUpCallMethod(String signature) {
-        this.nfiSignature = signature;
-    }
-
-    public static void main(String[] args) {
-        for (RFFIUpCallMethod f : RFFIUpCallMethod.values()) {
-            System.out.printf("#define %s_x %d\n", f.name(), f.ordinal());
-        }
-        System.out.printf("\n#define CALLBACK_TABLE_SIZE %d\n", RFFIUpCallMethod.values().length);
-    }
-
-}
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 db25097a00b0d4d46095db9db9ec3ee1fc72274c..0cfd341cb4122e7f245011a2c808aa5eb66b000a 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
@@ -38,6 +38,7 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.RRootNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.PromiseNode.VarArgNode;
 import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
@@ -47,6 +48,7 @@ import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.FastPathFactory;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
@@ -60,8 +62,11 @@ import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
 import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.nodes.EvaluatedArgumentsVisitor;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * <p>
@@ -351,6 +356,17 @@ public class ArgumentMatcher {
         RBuiltinDescriptor builtin = target.getBuiltin();
         FastPathFactory fastPath = target.getFastPath();
 
+        boolean hasAssignment = false;
+        for (int i = 0; !hasAssignment && i < suppliedArgs.length; i++) {
+            if (suppliedArgs[i] != null) {
+                hasAssignment = EvaluatedArgumentsVisitor.hasAssignmentCall(suppliedArgs[i].asRSyntaxNode());
+            }
+        }
+
+        if (hasAssignment) {
+            fastPath = null;
+        }
+
         // int logicalIndex = 0; As our builtin's 'evalsArgs' is meant for FastR arguments (which
         // take "..." as one), we don't need a logicalIndex
         for (int formalIndex = 0; formalIndex < match.resultPermutation.length; formalIndex++) {
@@ -359,6 +375,7 @@ public class ArgumentMatcher {
             // Has varargs? Unfold!
             if (suppliedIndex == MatchPermutation.VARARGS) {
                 int varArgsLen = match.varargsPermutation.length;
+                boolean shouldInline = shouldInlineArgument(builtin, formalIndex, fastPath);
                 String[] newNames = new String[varArgsLen];
                 RNode[] newVarArgs = new RNode[varArgsLen];
                 int index = 0;
@@ -375,7 +392,7 @@ public class ArgumentMatcher {
                         }
                     }
                     newNames[index] = match.varargsSignature.getName(i);
-                    newVarArgs[index] = varArg;
+                    newVarArgs[index] = shouldInline ? updateInlinedArg(varArg) : varArg;
                     index++;
                 }
 
@@ -399,7 +416,7 @@ public class ArgumentMatcher {
                 }
 
                 ArgumentsSignature signature = ArgumentsSignature.get(newNames);
-                if (shouldInlineArgument(builtin, formalIndex, fastPath)) {
+                if (shouldInline) {
                     resArgs[formalIndex] = PromiseNode.createVarArgsInlined(newVarArgs, signature);
                 } else {
                     boolean forcedEager = fastPath != null && fastPath.forcedEagerPromise(formalIndex);
@@ -408,12 +425,12 @@ public class ArgumentMatcher {
             } else if (suppliedIndex == MatchPermutation.UNMATCHED || suppliedArgs[suppliedIndex] == null) {
                 Object defaultValue = getS3DefaultArgumentValue(s3DefaultArguments, formals, formalIndex);
                 if (defaultValue == null) {
-                    resArgs[formalIndex] = wrapUnmatched(formals, builtin, formalIndex, noOpt);
+                    resArgs[formalIndex] = wrapUnmatched(formals, builtin, formalIndex, noOpt && hasAssignment);
                 } else {
                     resArgs[formalIndex] = ConstantNode.create(defaultValue);
                 }
             } else {
-                resArgs[formalIndex] = wrapMatched(formals, builtin, closureCache, suppliedArgs[suppliedIndex], formalIndex, noOpt, fastPath);
+                resArgs[formalIndex] = wrapMatched(formals, builtin, closureCache, suppliedArgs[suppliedIndex], formalIndex, noOpt || hasAssignment, fastPath);
             }
         }
         return Arguments.create(resArgs, match.resultSignature);
@@ -447,6 +464,27 @@ public class ArgumentMatcher {
         return builtin != null && builtin.evaluatesArg(formalIndex);
     }
 
+    /**
+     * Reads of the {@link RMissing} values must not be reported as error in inlined varargs. This
+     * method updates any wrapped ReadVariableNode to just return missing values without raising an
+     * error.
+     *
+     * see {@code com.oracle.truffle.r.nodes.function.PromiseNode.InlineVarArgsNode}
+     */
+    private static RNode updateInlinedArg(RNode node) {
+        if (!(node instanceof WrapArgumentNode)) {
+            return node;
+        }
+        WrapArgumentNode wrapper = (WrapArgumentNode) node;
+        RSyntaxNode syntaxNode = wrapper.getOperand().asRSyntaxNode();
+        if (!(syntaxNode instanceof RSyntaxLookup)) {
+            return node;
+        }
+        RSyntaxLookup lookup = (RSyntaxLookup) syntaxNode;
+        ReadVariableNode newRvn = ReadVariableNode.createSilentMissing(lookup.getIdentifier(), lookup.isFunctionLookup() ? RType.Function : RType.Any);
+        return WrapArgumentNode.create(ReadVariableNode.wrap(lookup.getLazySourceSection(), newRvn).asRNode(), wrapper.getIndex());
+    }
+
     private static RNode wrapUnmatched(FormalArguments formals, RBuiltinDescriptor builtin, int formalIndex, boolean noOpt) {
         if (builtin != null && !builtin.evaluatesArg(formalIndex) && formals.getDefaultArgument(formalIndex) != null) {
             /*
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java
index 53096fef441f0c9f0002d01b9a29ecf8909f290a..91b95219b651e391900dd7ffbe8cc4d633cb6eeb 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyScalarNode.java
@@ -45,9 +45,9 @@ public abstract class ClassHierarchyScalarNode extends UnaryNode {
     public static String get(Object arg) {
         CompilerAsserts.neverPartOfCompilation();
 
-        Object v = RRuntime.asAbstractVector(arg);
+        Object v = RRuntime.convertScalarVectors(arg);
         if (v instanceof RAttributable) {
-            RStringVector classHierarchy = ClassHierarchyNode.getClassHierarchy((RAttributable) v);
+            RStringVector classHierarchy = ClassHierarchyNode.getClassHierarchy(v);
             return classHierarchy.getLength() == 0 ? "" : classHierarchy.getDataAt(0);
         } else if (arg == RNull.instance) {
             return "NULL";
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 8548f638ce166b419e5e26152f297b8e3685c486..cb218d54517a09533e0370ebe6099d4caac134fe 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -68,6 +68,7 @@ import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.Utils.DebugExitException;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -133,14 +134,16 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
      */
     private final ConditionProfile returnTopLevelProfile = ConditionProfile.createBinaryProfile();
 
-    public static FunctionDefinitionNode create(SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, SaveArgumentsNode saveArguments, RSyntaxNode body,
+    public static FunctionDefinitionNode create(TruffleRLanguage language, SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, SaveArgumentsNode saveArguments,
+                    RSyntaxNode body,
                     FormalArguments formals, String name, PostProcessArgumentsNode argPostProcess) {
-        return new FunctionDefinitionNode(src, frameDesc, argSourceSections, saveArguments, body, formals, name, argPostProcess);
+        return new FunctionDefinitionNode(language, src, frameDesc, argSourceSections, saveArguments, body, formals, name, argPostProcess);
     }
 
-    private FunctionDefinitionNode(SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, RNode saveArguments, RSyntaxNode body, FormalArguments formals,
+    private FunctionDefinitionNode(TruffleRLanguage language, SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, RNode saveArguments, RSyntaxNode body,
+                    FormalArguments formals,
                     String name, PostProcessArgumentsNode argPostProcess) {
-        super(frameDesc, RASTBuilder.createFunctionFastPath(body, formals.getSignature()));
+        super(language, frameDesc, RASTBuilder.createFunctionFastPath(body, formals.getSignature()));
         this.formalArguments = formals;
         this.argSourceSections = argSourceSections;
         assert FrameSlotChangeMonitor.isValidFrameDescriptor(frameDesc);
@@ -155,6 +158,11 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         this.argPostProcess = argPostProcess;
     }
 
+    @Override
+    public boolean isInternal() {
+        return RSyntaxNode.isInternal(sourceSectionR);
+    }
+
     @Override
     public FormalArguments getFormalArguments() {
         return formalArguments;
@@ -172,13 +180,17 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         List<RCodeBuilder.Argument<RSyntaxNode>> args = new ArrayList<>();
         for (int i = 0; i < getFormalArguments().getLength(); i++) {
             RNode value = getFormalArguments().getArgument(i);
-            SourceSection source = argSourceSections == null ? getSourceSection() : argSourceSections[i];
+            SourceSection source = argSourceSections == null ? getLazySourceSection() : argSourceSections[i];
             args.add(RCodeBuilder.argument(source, getFormalArguments().getSignature().getName(i), value == null ? null : builder.process(value.asRSyntaxNode())));
         }
-        RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(getSourceSection(), args, builder.process(getBody()), name);
+        RootCallTarget callTarget = builder.rootFunction(getRLanguage(), getLazySourceSection(), args, builder.process(getBody()), name);
         return callTarget;
     }
 
+    public TruffleRLanguage getRLanguage() {
+        return getLanguage(RContext.getTruffleRLanguage());
+    }
+
     private static boolean containsAnyDispatch(RSyntaxNode body) {
         NodeCountFilter dispatchingMethodsFilter = node -> {
             if (node instanceof ReadVariableNode) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PeekLocalVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PeekLocalVariableNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..6ee9ad6abffc088c26d921c5b8a0c0d3f768992e
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PeekLocalVariableNode.java
@@ -0,0 +1,94 @@
+/*
+ * 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.nodes.function;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
+import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
+import com.oracle.truffle.r.runtime.Utils;
+import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
+
+public final class PeekLocalVariableNode extends RNode implements RSyntaxNode, RSyntaxLookup {
+
+    @Child private LocalReadVariableNode read;
+    @Child private SetVisibilityNode visibility;
+
+    private final ValueProfile valueProfile = ValueProfile.createClassProfile();
+
+    public PeekLocalVariableNode(String name) {
+        this.read = LocalReadVariableNode.create(Utils.intern(name), true);
+    }
+
+    @Override
+    public Object execute(VirtualFrame frame) {
+        Object value = read.execute(frame);
+        if (value == null) {
+            throw RSpecialFactory.throwFullCallNeeded();
+        }
+        return valueProfile.profile(value);
+    }
+
+    @Override
+    public Object visibleExecute(VirtualFrame frame) {
+        try {
+            return execute(frame);
+        } finally {
+            if (visibility == null) {
+                CompilerDirectives.transferToInterpreter();
+                visibility = insert(SetVisibilityNode.create());
+            }
+            visibility.execute(frame, true);
+        }
+    }
+
+    @Override
+    public void setSourceSection(SourceSection source) {
+        // nothing to do
+    }
+
+    @Override
+    public String getIdentifier() {
+        return (String) read.getIdentifier();
+    }
+
+    @Override
+    public boolean isFunctionLookup() {
+        return false;
+    }
+
+    @Override
+    public SourceSection getSourceSection() {
+        return null;
+    }
+
+    @Override
+    public SourceSection getLazySourceSection() {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
index a954484576061db50e18ce78152450a2b5c67c36..b2d5ebe471e2af85b928e377576af4bf6ee3c6d8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseNode.java
@@ -120,7 +120,7 @@ public abstract class PromiseNode extends RNode {
                 if (isVararg(expr)) {
                     return expr;
                 } else if (!noOpt && isOptimizableVariable(expr)) {
-                    return new OptVariableSuppliedPromiseNode(factory, (ReadVariableNode) expr, wrapIndex);
+                    return new OptVariableSuppliedPromiseNode(factory, (RSyntaxLookup) expr, wrapIndex);
                 }
             }
             return new PromisedNode(factory);
@@ -175,8 +175,8 @@ public abstract class PromiseNode extends RNode {
      */
     private static final class OptVariableSuppliedPromiseNode extends OptVariablePromiseBaseNode {
 
-        OptVariableSuppliedPromiseNode(RPromiseFactory factory, ReadVariableNode rvn, int wrapIndex) {
-            super(factory, rvn, wrapIndex);
+        OptVariableSuppliedPromiseNode(RPromiseFactory factory, RSyntaxLookup lookup, int wrapIndex) {
+            super(factory, lookup, wrapIndex);
         }
 
         @Override
@@ -365,13 +365,19 @@ public abstract class PromiseNode extends RNode {
         private VarArgsPromiseNode(RNode[] nodes, ArgumentsSignature signature, ClosureCache closureCache, boolean forcedEager) {
             this.promised = new RNode[nodes.length];
             this.closures = new Closure[nodes.length];
+            boolean noOpt = false;
+            for (int i = 0; !noOpt && i < nodes.length; i++) {
+                if (nodes[i] != null) {
+                    noOpt = EvaluatedArgumentsVisitor.hasAssignmentCall(nodes[i].asRSyntaxNode());
+                }
+            }
             for (int i = 0; i < nodes.length; i++) {
                 Closure closure = closureCache.getOrCreateClosure(nodes[i]);
                 this.closures[i] = closure;
                 if (RASTUtils.isLookup(nodes[i], ArgumentsSignature.VARARG_NAME)) {
                     this.promised[i] = nodes[i];
                 } else {
-                    this.promised[i] = PromiseNode.create(RPromiseFactory.create(PromiseState.Supplied, closure), false, forcedEager);
+                    this.promised[i] = PromiseNode.create(RPromiseFactory.create(PromiseState.Supplied, closure), noOpt, !noOpt && forcedEager);
                 }
             }
             this.signature = signature;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java
index 70d38d3f2926de903d95478bf63be2b43ed43aae..8bb9c406adcb49b193584313a8100758349bc011 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallBaseNodeWrapperFactory.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.instrumentation.ProbeNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public class RCallBaseNodeWrapperFactory implements InstrumentableFactory<RCallBaseNode> {
@@ -96,6 +97,11 @@ public class RCallBaseNodeWrapperFactory implements InstrumentableFactory<RCallB
         public RSyntaxNode getRSyntaxNode() {
             return delegate.asRSyntaxNode();
         }
+
+        @Override
+        public SourceSection getSourceSection() {
+            return delegate.getSourceSection();
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 8233f4cc27ba2047cc64a0bf5e8ff340351c6144..b1732b1e1c45ed98026d07c5249d1ef1fa8b0e89 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -70,6 +70,8 @@ import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.R2Foreign;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RArguments.S3Args;
 import com.oracle.truffle.r.runtime.RArguments.S3DefaultArguments;
@@ -97,9 +99,10 @@ import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RStringVector;
-import com.oracle.truffle.r.runtime.data.RTypedValue;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.interop.Foreign2RNodeGen;
+import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RFastPathNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -405,6 +408,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                     @Cached("create()") ClassHierarchyNode classHierarchyNodeY,
                     @Cached("createWithException()") S3FunctionLookupNode dispatchLookupY,
                     @Cached("createIdentityProfile()") ValueProfile builtinProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile emptyArgumentsProfile,
                     @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfileX,
                     @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfileY,
                     @Cached("createBinaryProfile()") ConditionProfile mismatchProfile,
@@ -420,6 +424,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         Object[] args = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getArguments() : callArguments.evaluateFlattenObjects(frame, lookupVarArgs(frame));
         ArgumentsSignature argsSignature = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getSignature() : callArguments.flattenNames(lookupVarArgs(frame));
 
+        if (emptyArgumentsProfile.profile(args.length == 0)) {
+            // nothing to dispatch on, this is a valid situation, e.g. prod() == 1
+            return call.execute(frame, function, new RArgsValuesAndNames(args, argsSignature), null, null);
+        }
+
         RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin());
         RDispatch dispatch = builtin.getDispatch();
 
@@ -537,7 +546,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
             this.arguments = arguments;
         }
 
-        public Object execute(VirtualFrame frame, TruffleObject function) {
+        public Object execute(VirtualFrame frame, TruffleObject function, Foreign2R foreign2R, R2Foreign r2Foreign) {
             Object[] argumentsArray = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getArguments() : arguments.evaluateFlattenObjects(frame, lookupVarArgs(frame));
             if (foreignCall == null || foreignCallArgCount != argumentsArray.length) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -545,7 +554,10 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                 foreignCallArgCount = argumentsArray.length;
             }
             try {
-                Object result = ForeignAccess.sendExecute(foreignCall, function, RRuntime.r2Java(argumentsArray));
+                for (int i = 0; i < argumentsArray.length; i++) {
+                    argumentsArray[i] = r2Foreign.execute(argumentsArray[i]);
+                }
+                Object result = ForeignAccess.sendExecute(foreignCall, function, argumentsArray);
                 if (RRuntime.isForeignObject(result)) {
                     if (isNullCall == null) {
                         CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -555,7 +567,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                         return RNull.instance;
                     }
                 }
-                return RRuntime.java2R(result);
+                return foreign2R.execute(result);
             } catch (ArityException | UnsupportedMessageException | UnsupportedTypeException e) {
                 CompilerDirectives.transferToInterpreter();
                 RInternalError.reportError(e);
@@ -568,14 +580,24 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         return new ForeignCall(createArguments(null, true, true));
     }
 
-    protected static boolean isRTypedValue(Object value) {
-        return value instanceof RTypedValue;
+    protected static boolean isForeignObject(Object value) {
+        return RRuntime.isForeignObject(value);
+    }
+
+    protected static Foreign2R createR2ForeignNode() {
+        return Foreign2RNodeGen.create();
+    }
+
+    protected R2Foreign createR2Foreign() {
+        return R2ForeignNodeGen.create();
     }
 
-    @Specialization(guards = "!isRTypedValue(function)")
+    @Specialization(guards = "isForeignObject(function)")
     public Object call(VirtualFrame frame, TruffleObject function,
-                    @Cached("createForeignCall()") ForeignCall foreignCall) {
-        return foreignCall.execute(frame, function);
+                    @Cached("createForeignCall()") ForeignCall foreignCall,
+                    @Cached("createR2ForeignNode()") Foreign2R foreign2RNode,
+                    @Cached("createR2Foreign()") R2Foreign r2Foreign) {
+        return foreignCall.execute(frame, function, foreign2RNode, r2Foreign);
     }
 
     @TruffleBoundary
@@ -632,7 +654,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
         return root.containsDispatch() || root.needsSplitting();
     }
 
-    private static final class GetTempNode extends RNode {
+    public static final class GetTempNode extends RNode {
 
         private final FrameSlot slot;
         private final RSyntaxNode arg;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
index eec4759c7483a6ecb073fa41f1a5acf07024c4a2..0783ed2799b0a6a1876cd6e0d6b87b6488f2b123 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallSpecialNode.java
@@ -25,27 +25,27 @@ package com.oracle.truffle.r.nodes.function;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.NodeChild;
+import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.api.source.SourceSection;
-import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RDispatch;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RVisibility;
-import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
@@ -54,66 +54,43 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-final class PeekLocalVariableNode extends RNode implements RSyntaxLookup {
+@NodeChild(value = "delegate", type = RNode.class)
+abstract class ClassCheckNode extends RNode {
 
-    @Child private LocalReadVariableNode read;
-
-    private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile();
-    private final ValueProfile valueProfile = ValueProfile.createClassProfile();
-
-    @Child private SetVisibilityNode visibility;
-
-    PeekLocalVariableNode(String name) {
-        this.read = LocalReadVariableNode.create(Utils.intern(name), false);
-    }
+    public abstract RNode getDelegate();
 
     @Override
-    public Object execute(VirtualFrame frame) {
-        Object value = read.execute(frame);
-        if (value == null) {
-            throw RSpecialFactory.throwFullCallNeeded();
-        }
-        if (isPromiseProfile.profile(value instanceof RPromise)) {
-            RPromise promise = (RPromise) value;
-            if (!promise.isEvaluated()) {
-                throw RSpecialFactory.throwFullCallNeeded();
-            }
-            return valueProfile.profile(promise.getValue());
-        }
-        return valueProfile.profile(value);
+    protected RSyntaxNode getRSyntaxNode() {
+        return getDelegate().asRSyntaxNode();
     }
 
-    @Override
-    public Object visibleExecute(VirtualFrame frame) {
-        try {
-            return execute(frame);
-        } finally {
-            if (visibility == null) {
-                CompilerDirectives.transferToInterpreter();
-                visibility = insert(SetVisibilityNode.create());
-            }
-            visibility.execute(frame, true);
-        }
+    @Specialization
+    protected static int doInt(int value) {
+        return value;
     }
 
-    @Override
-    public void setSourceSection(SourceSection source) {
-        // nothing to do
+    @Specialization
+    protected static double doDouble(double value) {
+        return value;
     }
 
-    @Override
-    public String getIdentifier() {
-        return (String) read.getIdentifier();
+    @Specialization
+    protected static byte doLogical(byte value) {
+        return value;
     }
 
-    @Override
-    public boolean isFunctionLookup() {
-        return false;
+    @Specialization
+    protected static String doString(String value) {
+        return value;
     }
 
-    @Override
-    public SourceSection getLazySourceSection() {
-        return null;
+    @Specialization
+    public Object doGeneric(Object value,
+                    @Cached("create()") ClassHierarchyNode classHierarchy) {
+        if (classHierarchy.execute(value) != null) {
+            throw RSpecialFactory.throwFullCallNeeded();
+        }
+        return value;
     }
 }
 
@@ -153,7 +130,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
 
     private final RSyntaxNode[] arguments;
     private final ArgumentsSignature signature;
-    public final RFunction expectedFunction;
+    public final RBuiltinDescriptor expectedFunction;
     private final RVisibility visible;
 
     /**
@@ -170,15 +147,15 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
     private final boolean inReplace;
     private final int[] ignoredArguments;
 
-    private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RFunction expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special, boolean inReplace,
-                    int[] ignoredArguments) {
+    private RCallSpecialNode(SourceSection sourceSection, RNode functionNode, RBuiltinDescriptor expectedFunction, RSyntaxNode[] arguments, ArgumentsSignature signature, RNode special,
+                    boolean inReplace, int[] ignoredArguments) {
         this.sourceSection = sourceSection;
         this.expectedFunction = expectedFunction;
         this.special = special;
         this.functionNode = functionNode;
         this.arguments = arguments;
         this.signature = signature;
-        this.visible = expectedFunction.getRBuiltin().getVisibility();
+        this.visible = expectedFunction.getVisibility();
         this.inReplace = inReplace;
         this.ignoredArguments = ignoredArguments;
     }
@@ -188,7 +165,8 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
      * i.e., does not modify them in any way before passing it to
      * {@link RSpecialFactory#create(ArgumentsSignature, RNode[], boolean)}.
      */
-    public static RSyntaxNode createCallInReplace(SourceSection sourceSection, RNode functionNode, ArgumentsSignature signature, RSyntaxNode[] arguments, int... ignoredArguments) {
+    public static RSyntaxNode createCallInReplace(SourceSection sourceSection, RNode functionNode, ArgumentsSignature signature, RSyntaxNode[] arguments,
+                    int... ignoredArguments) {
         return createCall(sourceSection, functionNode, signature, arguments, true, ignoredArguments);
     }
 
@@ -208,7 +186,8 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
         }
     }
 
-    private static RCallSpecialNode tryCreate(SourceSection sourceSection, RNode functionNode, ArgumentsSignature signature, RSyntaxNode[] arguments, boolean inReplace, int[] ignoredArguments) {
+    private static RCallSpecialNode tryCreate(SourceSection sourceSection, RNode functionNode, ArgumentsSignature signature, RSyntaxNode[] arguments,
+                    boolean inReplace, int[] ignoredArguments) {
         RSyntaxNode syntaxFunction = functionNode.asRSyntaxNode();
         if (!(syntaxFunction instanceof RSyntaxLookup)) {
             // LHS is not a simple lookup -> bail out
@@ -246,12 +225,10 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
                 if (arg instanceof RSyntaxLookup) {
                     String lookup = ((RSyntaxLookup) arg).getIdentifier();
                     if (ArgumentsSignature.VARARG_NAME.equals(lookup)) {
+                        // cannot map varargs
                         return null;
                     }
                     if (i < evaluatedArgs) {
-                        // not quite correct:
-                        // || (dispatch == RDispatch.DEFAULT
-                        // && builtinDescriptor.evaluatesArg(i))
                         localArguments[i] = arg.asRNode();
                     } else {
                         localArguments[i] = new PeekLocalVariableNode(lookup);
@@ -262,6 +239,16 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
                     assert arg instanceof RCallSpecialNode;
                     localArguments[i] = arg.asRNode();
                 }
+                if (dispatch.isGroupGeneric() || dispatch == RDispatch.INTERNAL_GENERIC && i == 0) {
+                    if (localArguments[i] instanceof RSyntaxConstant) {
+                        Object value = ((RSyntaxConstant) localArguments[i]).getValue();
+                        if (value instanceof RAttributable && ((RAttributable) value).getAttr(RRuntime.CLASS_ATTR_KEY) != null) {
+                            return null;
+                        }
+                    } else {
+                        localArguments[i] = ClassCheckNodeGen.create(localArguments[i]);
+                    }
+                }
             }
         }
         RNode special = specialCall.create(signature, localArguments, inReplace);
@@ -269,7 +256,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
             // the factory refused to create a special call -> bail out
             return null;
         }
-        RFunction expectedFunction = RContext.lookupBuiltin(name);
+        RBuiltinDescriptor expectedFunction = RContext.lookupBuiltinDescriptor(name);
         RInternalError.guarantee(expectedFunction != null);
 
         RCallSpecialNode callSpecial = new RCallSpecialNode(sourceSection, functionNode, expectedFunction, arguments, signature, special, inReplace, ignoredArguments);
@@ -295,7 +282,7 @@ public final class RCallSpecialNode extends RCallBaseNode implements RSyntaxNode
     @Override
     public Object execute(VirtualFrame frame, Object function) {
         try {
-            if (function != expectedFunction) {
+            if (!(function instanceof RFunction) || ((RFunction) function).getRBuiltin() != expectedFunction) {
                 // the actual function differs from the expected function
                 throw RSpecialFactory.throwFullCallNeeded();
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java
index 8fb51170f9cad3819b28b72e310e239459cd4e99..4b1a0f0af8a824d2e17135a6688db029ba97ef4d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -102,7 +102,7 @@ public final class RCallerHelper {
                             index++;
                         }
                     }
-                    Object replacedFunction = function instanceof String ? ReadVariableNode.createFunctionLookup(RSyntaxNode.LAZY_DEPARSE, (String) function) : function;
+                    Object replacedFunction = function instanceof String ? ReadVariableNode.wrap(RSyntaxNode.LAZY_DEPARSE, ReadVariableNode.createFunctionLookup((String) function)) : function;
                     syntaxNode = RASTUtils.createCall(replacedFunction, true, ArgumentsSignature.get(signature), syntaxArguments);
                 }
                 return syntaxNode;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
index 065db4b08840904abb2649c1178a72998df720cb..d3d4f63a891ec5abdf9dd44471145856edbaec8e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RMissingHelper.java
@@ -27,13 +27,14 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.REmpty;
 import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * This class implements the behavior for {@link RMissing} which is needed inside this module, as it
@@ -113,19 +114,11 @@ public class RMissingHelper {
             return false;
         }
         boolean result = false;
-        Object exprObj = promise.getRep();
-
-        // Unfold WrapArgumentNode
-        if (exprObj instanceof WrapArgumentNode) {
-            exprObj = ((WrapArgumentNode) exprObj).getOperand();
-        }
-        if (exprObj instanceof WrapDefaultArgumentNode) {
-            exprObj = ((WrapDefaultArgumentNode) exprObj).getOperand();
-        }
+        RSyntaxNode syntaxNode = promise.getRep().asRSyntaxNode();
 
         // Check for ReadVariableNode
-        if (exprObj instanceof ReadVariableNode) {
-            ReadVariableNode rvn = (ReadVariableNode) exprObj;
+        if (syntaxNode instanceof RSyntaxLookup) {
+            RSyntaxLookup lookup = (RSyntaxLookup) syntaxNode;
 
             // Check: If there is a cycle, return true. (This is done like in GNU R)
             if (promise.isUnderEvaluation()) {
@@ -150,7 +143,7 @@ public class RMissingHelper {
                     }
                 }
                 // promise.materialize(globalMissingPromiseProfile);
-                result = isMissingArgument(promise.getFrame(), rvn.getIdentifier());
+                result = isMissingArgument(promise.getFrame(), lookup.getIdentifier());
             } finally {
                 promise.resetUnderEvaluation();
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java
index 7447a2e1f7dddae8c2cc3d7d3a3ae2e60ff97515..62a9cba7c6bf912bc59c8a61e5c4c5c4e0abb916 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java
@@ -247,7 +247,7 @@ public abstract class S3FunctionLookupNode extends RBaseNode {
             cachedNode = new UseMethodFunctionLookupCachedNode(next.throwsError, next.nextMethod, genericName, type, group, null, unsuccessfulReadsCaller, unsuccessfulReadsTable,
                             reads.methodsTableRead, reads.successfulRead, reads.successfulReadTable, result.function, result.clazz, result.targetFunctionName, result.groupMatch, next);
         } else {
-            RFunction builtin = next.throwsError ? builtin = RContext.lookupBuiltin(genericName) : null;
+            RFunction builtin = next.throwsError ? builtin = RContext.getInstance().lookupBuiltin(genericName) : null;
             cachedNode = new UseMethodFunctionLookupCachedNode(next.throwsError, next.nextMethod, genericName, type, group, builtin, unsuccessfulReadsCaller, unsuccessfulReadsTable,
                             reads.methodsTableRead, null, null, null, null, null, false, next);
         }
@@ -448,7 +448,7 @@ public abstract class S3FunctionLookupNode extends RBaseNode {
 
             if (result == null) {
                 if (throwsError) {
-                    RFunction function = RContext.lookupBuiltin(genericName);
+                    RFunction function = RContext.getInstance().lookupBuiltin(genericName);
                     if (function != null) {
                         return new Result(genericName, function, RNull.instance, genericName, false);
                     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java
index a86dd95a42ace8bde644958eb8ce6ae1289d1681..6822dd5e8a72b9c0f29adaf4f1bdb9e0adc94dae 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.nodes.function;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.nodes.RNode;
@@ -42,7 +43,7 @@ public abstract class WrapArgumentBaseNode extends RNode {
         this.operand = operand;
     }
 
-    public RNode getOperand() {
+    public final RNode getOperand() {
         return operand;
     }
 
@@ -76,6 +77,11 @@ public abstract class WrapArgumentBaseNode extends RNode {
 
     @Override
     public RSyntaxNode getRSyntaxNode() {
-        return getOperand().asRSyntaxNode();
+        return operand == null ? null : operand.asRSyntaxNode();
+    }
+
+    @Override
+    public SourceSection getSourceSection() {
+        return operand == null ? null : operand.getSourceSection();
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java
index 554d2b2b0e16ba18889f4639f3bedf04492ec9e5..62c6f044fb95cda2d7c6063b6c7fda748e579bca 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java
@@ -27,6 +27,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.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
@@ -38,11 +39,13 @@ import com.oracle.truffle.r.nodes.function.FormalArguments;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.nodes.function.call.PrepareArgumentsFactory.PrepareArgumentsDefaultNodeGen;
 import com.oracle.truffle.r.nodes.function.call.PrepareArgumentsFactory.PrepareArgumentsExplicitNodeGen;
+import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
 import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments.S3DefaultArguments;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.SubstituteVirtualFrame;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 
@@ -111,12 +114,48 @@ public abstract class PrepareArguments extends Node {
             return executeArgs(arguments.matchedArguments, arguments.matchedSuppliedSignature, frame);
         }
 
-        @Fallback
-        public RArgsValuesAndNames prepareGeneric(VirtualFrame frame, RArgsValuesAndNames varArgs, S3DefaultArguments s3DefaultArguments, @SuppressWarnings("unused") RCallNode call) {
-            CompilerDirectives.transferToInterpreter();
+        private static final class GenericCallEntry extends Node {
+            private final ArgumentsSignature cachedVarArgSignature;
+            private final S3DefaultArguments cachedS3DefaultArguments;
+
+            @Child private ArgumentsAndSignature arguments;
+
+            GenericCallEntry(ArgumentsSignature cachedVarArgSignature, S3DefaultArguments cachedS3DefaultArguments, ArgumentsAndSignature arguments) {
+                this.cachedVarArgSignature = cachedVarArgSignature;
+                this.cachedS3DefaultArguments = cachedS3DefaultArguments;
+                this.arguments = arguments;
+            }
+        }
+
+        /*
+         * Use a TruffleBoundaryNode to be able to switch child nodes without invalidating the whole
+         * method.
+         */
+        protected final class GenericCall extends TruffleBoundaryNode {
+
+            @Child private GenericCallEntry entry;
+
+            @TruffleBoundary
+            public RArgsValuesAndNames execute(MaterializedFrame materializedFrame, S3DefaultArguments s3DefaultArguments, ArgumentsSignature varArgSignature, RCallNode call) {
+                GenericCallEntry e = entry;
+                if (e == null || e.cachedVarArgSignature != varArgSignature || e.cachedS3DefaultArguments != s3DefaultArguments) {
+                    ArgumentsAndSignature arguments = createArguments(call, varArgSignature, s3DefaultArguments);
+                    entry = e = insert(new GenericCallEntry(varArgSignature, s3DefaultArguments, arguments));
+                }
+                VirtualFrame frame = SubstituteVirtualFrame.create(materializedFrame);
+                return executeArgs(e.arguments.matchedArguments, e.arguments.matchedSuppliedSignature, frame);
+            }
+        }
+
+        protected GenericCall createGenericCall() {
+            return new GenericCall();
+        }
+
+        @Specialization
+        public RArgsValuesAndNames prepareGeneric(VirtualFrame frame, RArgsValuesAndNames varArgs, S3DefaultArguments s3DefaultArguments, RCallNode call,
+                        @Cached("createGenericCall()") GenericCall generic) {
             ArgumentsSignature varArgSignature = varArgs == null ? null : varArgs.getSignature();
-            Arguments<RNode> matchedArgs = ArgumentMatcher.matchArguments(target, sourceArguments, varArgSignature, s3DefaultArguments, RError.ROOTNODE, true);
-            return executeArgs(matchedArgs.getArguments(), matchedArgs.getSignature(), frame);
+            return generic.execute(frame.materialize(), s3DefaultArguments, varArgSignature, call);
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java
index b856c58620a7b6e111ee35ca431ca0c57779f4a5..3a4af7be70543373b97334da11591ad97ba1b7ec 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/RExplicitCallNode.java
@@ -59,7 +59,6 @@ public abstract class RExplicitCallNode extends Node {
             argsFrameSlot = FrameSlotChangeMonitor.findOrAddFrameSlot(frame.getFrameDescriptor(), argsIdentifier, FrameSlotKind.Object);
         }
         try {
-            frame.setObject(argsFrameSlot, args);
             FrameSlotChangeMonitor.setObject(frame, argsFrameSlot, args);
             return call.execute(frame, function);
         } finally {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java
index 099473eb05df4d30f7a9b8da425f901d290e21eb..78f7cc119ef578547f945439ed0490200339bad1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.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
@@ -26,6 +26,7 @@ import com.oracle.truffle.r.nodes.access.AccessArgumentNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.PromiseNode;
+import com.oracle.truffle.r.nodes.function.RCallNode.GetTempNode;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
@@ -34,6 +35,7 @@ import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * Provides small helper function for eager evaluation of arguments for the use in
@@ -81,8 +83,9 @@ public class EagerEvalHelper {
         if (!optConsts()) {
             return null;
         }
-        if (expr instanceof RSyntaxCall) {
-            RSyntaxCall call = (RSyntaxCall) expr;
+        RSyntaxNode syntax = expr.asRSyntaxNode();
+        if (syntax instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) syntax;
             if (call.getSyntaxLHS() instanceof RSyntaxLookup) {
                 String functionName = ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier();
                 switch (functionName) {
@@ -99,8 +102,8 @@ public class EagerEvalHelper {
                         break;
                 }
             }
-        } else if (expr instanceof RSyntaxConstant) {
-            return ((RSyntaxConstant) expr).getValue();
+        } else if (syntax instanceof RSyntaxConstant) {
+            return ((RSyntaxConstant) syntax).getValue();
         }
         return null;
     }
@@ -124,7 +127,7 @@ public class EagerEvalHelper {
     private static boolean isVariableArgument(RBaseNode expr) {
         // Do NOT try to optimize anything that might force a Promise, as this might be arbitrary
         // complex (time and space)!
-        return expr instanceof ReadVariableNode && !((ReadVariableNode) expr).isForceForTypeCheck();
+        return !(expr instanceof GetTempNode) && expr.asRSyntaxNode() instanceof RSyntaxLookup && !((RSyntaxLookup) expr.asRSyntaxNode()).isFunctionLookup();
     }
 
     private static boolean isCheapExpressionArgument(@SuppressWarnings("unused") RNode expr) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java
index 4ee9992eb12985114fe8ddfc4d84b0cf20883ea5..ef9229e20adc23db8633d5d5e3a12fc87dab69be 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.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
@@ -30,39 +30,38 @@ import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.access.FrameSlotNode;
 import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
 import com.oracle.truffle.r.nodes.function.PromiseNode;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RCaller;
-import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerFeedback;
 import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 public abstract class OptVariablePromiseBaseNode extends PromiseNode implements EagerFeedback {
     private final BranchProfile promiseCallerProfile = BranchProfile.create();
-    private final ReadVariableNode originalRvn;
+    private final RSyntaxLookup originalRvn;
     @Child private FrameSlotNode frameSlotNode;
     @Child private RNode fallback = null;
     @Child private LocalReadVariableNode readNode;
     private final int wrapIndex;
 
-    public OptVariablePromiseBaseNode(RPromiseFactory factory, ReadVariableNode rvn, int wrapIndex) {
+    public OptVariablePromiseBaseNode(RPromiseFactory factory, RSyntaxLookup lookup, int wrapIndex) {
         super(factory);
         // Should be caught by optimization check
-        assert !rvn.isForceForTypeCheck() && rvn.getMode() == RType.Any;
-        this.originalRvn = rvn;
-        this.frameSlotNode = FrameSlotNode.create(rvn.getIdentifier(), false);
-        this.readNode = LocalReadVariableNode.create(rvn.getIdentifier(), false);
+        assert !lookup.isFunctionLookup();
+        this.originalRvn = lookup;
+        this.frameSlotNode = FrameSlotNode.create(lookup.getIdentifier(), false);
+        this.readNode = LocalReadVariableNode.create(lookup.getIdentifier(), false);
         this.wrapIndex = wrapIndex;
     }
 
     @Override
     public RSyntaxNode getPromiseExpr() {
-        return originalRvn;
+        return (RSyntaxNode) originalRvn;
     }
 
     @Override
@@ -133,6 +132,6 @@ public abstract class OptVariablePromiseBaseNode extends PromiseNode implements
 
     @Override
     public RSyntaxNode getRSyntaxNode() {
-        return originalRvn;
+        return (RSyntaxNode) originalRvn;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java
index fb71c60e5ea88f609c93cbbde820c487e3d28a60..3fe5fcddda088bd95264832c0d49bd6603cb7c7a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/UpdateShareableChildValueNode.java
@@ -29,6 +29,9 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.data.RSharingAttributeStorage;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
+/**
+ * Implements a fast-path version of {@code UpdateShareableChildValue}.
+ */
 public abstract class UpdateShareableChildValueNode extends RBaseNode {
 
     public abstract void execute(Object owner, Object attrValue);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java
index 9e2edd953ca0c0f1454310c8564c8e2db52fb53c..56581f056d86f41181c127609c525a11ae84f6b4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/instrumentation/RInstrumentation.java
@@ -25,10 +25,13 @@ package com.oracle.truffle.r.nodes.instrumentation;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
 import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
+import com.oracle.truffle.api.instrumentation.SourceSectionFilter.IndexRange;
 import com.oracle.truffle.api.instrumentation.StandardTags;
+import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode;
 import com.oracle.truffle.r.runtime.FastROptions;
+import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RFunction;
 
@@ -51,7 +54,7 @@ public class RInstrumentation {
     }
 
     public static SourceSection getSourceSection(RFunction func) {
-        return getFunctionDefinitionNode(func).getSourceSection();
+        return func.getRootNode().getSourceSection();
     }
 
     /**
@@ -76,7 +79,20 @@ public class RInstrumentation {
         builder.tagIs(tag);
         SourceSection fdns = fdn.getSourceSection();
         builder.indexIn(fdns.getCharIndex(), fdns.getCharLength());
-        builder.sourceIs(fdns.getSource());
+        Source source = fdns.getSource();
+        builder.sourceIs(s -> source.equals(s));
+        return builder;
+    }
+
+    public static SourceSectionFilter.Builder createLineFilter(Source src, int line, Class<?> tag) {
+        /* Filter needs to check for statement tags in the range of the function in the Source */
+        SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder();
+        builder.tagIs(tag);
+        SourceSection lineSourceSection = src.createSection(line);
+        builder.indexIn(lineSourceSection.getCharIndex(), lineSourceSection.getCharLength());
+        builder.lineIn(lineSourceSection.getStartLine(), 1);
+        builder.lineEndsIn(IndexRange.between(lineSourceSection.getEndLine(), lineSourceSection.getEndLine() + 1));
+        builder.sourceIs(visitinSrc -> RSource.getPathInternal(src).equals(RSource.getPathInternal(visitinSrc)));
         return builder;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
index 3780418d1675fe83fe3101d4ad6bdc6a021b14fd..a9912feba90ea092a00e3a2f725d2b12e3ab4aaf 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/LoadMethod.java
@@ -38,7 +38,6 @@ import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 // transcribed from /src/library/methods/src/methods_list_dispatch.c (R_loadMethod function)
 abstract class LoadMethod extends RBaseNode {
@@ -119,7 +118,7 @@ abstract class LoadMethod extends RBaseNode {
             REnvironment methodsEnv = (REnvironment) methodsEnvRead.execute(frame, REnvironment.getNamespaceRegistry().getFrame(regFrameAccessProfile));
             if (loadMethodFind == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                loadMethodFind = insert(ReadVariableNode.createFunctionLookup(RSyntaxNode.INTERNAL, RRuntime.R_LOAD_METHOD_NAME));
+                loadMethodFind = insert(ReadVariableNode.createFunctionLookup(RRuntime.R_LOAD_METHOD_NAME));
                 currentFunction = (RFunction) loadMethodFind.execute(frame, methodsEnv.getFrame());
                 loadMethodFunction = currentFunction;
                 loadMethodCall = insert(CallRFunctionNode.create(loadMethodFunction.getTarget()));
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/qirinterface/QIRInterface.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/qirinterface/QIRInterface.java
index 9f9bf3485d13442d5ef0e167520c7cdc6395d5c1..6fd0d62c930a85e958fad1abc7009419ffcbfece 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/qirinterface/QIRInterface.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/qirinterface/QIRInterface.java
@@ -107,7 +107,7 @@ public final class QIRInterface {
                                                                                                                                                               // Remove
                                                                                                                                                               // this
                                                                                                                                                               // hack
-                                                : RToQIRType(fv.sourceSection, varSlot != null ? frame.getValue(varSlot) : RContext.lookupBuiltin(varName)));
+                                                : RToQIRType(fv.sourceSection, varSlot != null ? frame.getValue(varSlot) : RContext.getInstance().lookupBuiltin(varName)));
             }
         return query;
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/qirinterface/QIRTranslateVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/qirinterface/QIRTranslateVisitor.java
index 764c96ccaaba4e1a02441d53ffce7ccf2ac7769a..a6489faed824cb0818310beed0767d43aab0dcbd 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/qirinterface/QIRTranslateVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/qirinterface/QIRTranslateVisitor.java
@@ -11,7 +11,7 @@ import com.oracle.truffle.r.nodes.RSyntaxNodeVisitor;
 import com.oracle.truffle.r.nodes.access.AccessArgumentNode;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.access.variables.LookupNode;
 import com.oracle.truffle.r.nodes.builtin.InternalNode;
 import com.oracle.truffle.r.nodes.control.*;
 import com.oracle.truffle.r.nodes.function.FunctionExpressionNode;
@@ -94,11 +94,11 @@ public final class QIRTranslateVisitor implements RSyntaxNodeVisitor<QIRNode> {
                 // Else we apply STRAD-ASSIGN-ID normally
                 if (!(value instanceof AccessArgumentNode))
                     result = new QIRApply(dummy, result, value.asRSyntaxNode().accept(this));
-            } else if (child instanceof ReplacementDispatchNode && ((ReplacementDispatchNode) child).lhs instanceof ReadVariableNode) {
+            } else if (child instanceof ReplacementDispatchNode && ((ReplacementDispatchNode) child).lhs instanceof LookupNode) {
                 final RNode value = ((ReplacementDispatchNode) child).rhs;
 
                 // If the assignment value reads an argument, then we translate to a lambda.
-                result = new QIRLambda(dummy, null, new QIRVariable(dummy, ((ReadVariableNode) ((ReplacementDispatchNode) child).lhs).getIdentifier(), null), result, new FrameDescriptor());
+                result = new QIRLambda(dummy, null, new QIRVariable(dummy, ((LookupNode) ((ReplacementDispatchNode) child).lhs).getIdentifier(), null), result, new FrameDescriptor());
                 // Else we apply STRAD-ASSIGN-ID normally
                 if (!(value instanceof AccessArgumentNode))
                     result = new QIRApply(dummy, result, value.asRSyntaxNode().accept(this));
@@ -108,7 +108,7 @@ public final class QIRTranslateVisitor implements RSyntaxNodeVisitor<QIRNode> {
                 // TODO: RCallSpecialNode is not necessarily a write
                 final ReplacementDispatchNode repl = (ReplacementDispatchNode) child;
                 final RCallSpecialNode lhs = (RCallSpecialNode) repl.lhs;
-                final ReadVariableNode receiver = (ReadVariableNode) lhs.getSyntaxArguments()[0];
+                final LookupNode receiver = (LookupNode) lhs.getSyntaxArguments()[0];
                 final ConstantNode eid = (ConstantNode) lhs.getSyntaxArguments()[1];
                 final RNode value = repl.rhs;
                 result = new QIRApply(dummy, new QIRLambda(dummy, null, new QIRVariable(dummy, receiver.getIdentifier(), null), result, new FrameDescriptor()),
@@ -120,7 +120,7 @@ public final class QIRTranslateVisitor implements RSyntaxNodeVisitor<QIRNode> {
     }
 
     @Override
-    public final QIRNode visit(final ReadVariableNode var) {
+    public final QIRNode visit(final LookupNode var) {
         return new QIRVariable(var.getSourceSection(), var.getIdentifier(), null);
     }
 
@@ -143,7 +143,7 @@ public final class QIRTranslateVisitor implements RSyntaxNodeVisitor<QIRNode> {
     @Override
     public final QIRNode visit(final RCallNode call) {
         try {
-            return visitBuiltin(call.getSourceSection(), ((ReadVariableNode) call.getFunction()).getIdentifier(),
+            return visitBuiltin(call.getSourceSection(), ((LookupNode) call.getFunction()).getIdentifier(),
                             Arrays.stream(call.getArguments().getArguments()).map(arg -> arg.accept(this)).collect(Collectors.toList()));
         } catch (final RuntimeException e) {
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/query/RQueryVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/query/RQueryVisitor.java
index 204c6b4c5dc3c2643ee13e969c41159900be3183..a5ad4ad8221bdc329520373d53e9e67ab8215002 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/query/RQueryVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/query/RQueryVisitor.java
@@ -5,7 +5,7 @@ import java.util.Arrays;
 import com.oracle.truffle.r.nodes.RSyntaxNodeVisitor;
 import com.oracle.truffle.r.nodes.access.ConstantNode;
 import com.oracle.truffle.r.nodes.access.WriteLocalFrameVariableNode;
-import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.access.variables.LookupNode;
 import com.oracle.truffle.r.nodes.builtin.InternalNode;
 import com.oracle.truffle.r.nodes.control.*;
 import com.oracle.truffle.r.nodes.function.FunctionExpressionNode;
@@ -60,7 +60,7 @@ public final class RQueryVisitor implements RSyntaxNodeVisitor<RSyntaxNode> {
     }
 
     @Override
-    public final RSyntaxNode visit(final ReadVariableNode var) {
+    public final RSyntaxNode visit(final LookupNode var) {
         return var;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
index 381bd14e90fbfdc5f491bcfad838e066c463adde..f0e17bb98d59f24aaf75f02466000cf858f55606 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastDoubleNode.java
@@ -26,7 +26,9 @@ import java.util.function.IntToDoubleFunction;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
@@ -44,7 +46,10 @@ 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.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 
+@ImportStatic(RRuntime.class)
 public abstract class CastDoubleNode extends CastDoubleBaseNode {
 
     protected CastDoubleNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
@@ -207,6 +212,22 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
         return ret;
     }
 
+    @Specialization(guards = "isForeignObject(obj)")
+    protected RDoubleVector doForeignObject(TruffleObject obj,
+                    @Cached("createForeignArray2RNode()") ForeignArray2R foreignArray2R) {
+        Object o = foreignArray2R.execute(obj, true);
+        if (!RRuntime.isForeignObject(o)) {
+            if (o instanceof RDoubleVector) {
+                return (RDoubleVector) o;
+            }
+            o = castDoubleRecursive(o);
+            if (o instanceof RDoubleVector) {
+                return (RDoubleVector) o;
+            }
+        }
+        throw error(RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "vector");
+    }
+
     public static CastDoubleNode create() {
         return CastDoubleNodeGen.create(true, true, true);
     }
@@ -218,4 +239,8 @@ public abstract class CastDoubleNode extends CastDoubleBaseNode {
     public static CastDoubleNode createNonPreserving() {
         return CastDoubleNodeGen.create(false, false, false);
     }
+
+    protected ForeignArray2R createForeignArray2RNode() {
+        return ForeignArray2RNodeGen.create();
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
index 7d46d80f99c8e1fd2db9a48b9a008a468348e836..aff2149c234a85ef32c501a5c04ebbd60f18964f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java
@@ -23,7 +23,9 @@
 package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.runtime.RError;
@@ -43,8 +45,11 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
+@ImportStatic(RRuntime.class)
 public abstract class CastIntegerNode extends CastIntegerBaseNode {
 
     private final NAProfile naProfile = NAProfile.create();
@@ -68,13 +73,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
     public abstract Object executeInt(Object o);
 
     @Specialization
-    protected RIntVector doIntVector(RIntVector operand) {
-        return operand;
-    }
-
-    @Specialization
-    protected RIntSequence doIntVector(RIntSequence operand) {
-        // sequence does not have attributes - nothing to copy or drop
+    protected RAbstractIntVector doIntVector(RAbstractIntVector operand) {
         return operand;
     }
 
@@ -216,6 +215,22 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
         return ret;
     }
 
+    @Specialization(guards = "isForeignObject(obj)")
+    protected RIntVector doForeignObject(TruffleObject obj,
+                    @Cached("createForeignArray2RNode()") ForeignArray2R foreignArray2R) {
+        Object o = foreignArray2R.execute(obj, true);
+        if (!RRuntime.isForeignObject(o)) {
+            if (o instanceof RIntVector) {
+                return (RIntVector) o;
+            }
+            o = castIntegerRecursive(o);
+            if (o instanceof RIntVector) {
+                return (RIntVector) o;
+            }
+        }
+        throw error(RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "vector");
+    }
+
     // TODO Should be type-variable and moved to CastNode
     @Specialization(guards = {"args.getLength() == 1", "isIntVector(args.getArgument(0))"})
     protected RIntVector doRArgsValuesAndNames(RArgsValuesAndNames args) {
@@ -237,4 +252,8 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
     public static CastIntegerNode createNonPreserving() {
         return CastIntegerNodeGen.create(false, false, false);
     }
+
+    protected ForeignArray2R createForeignArray2RNode() {
+        return ForeignArray2RNodeGen.create();
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
index 9a868b06d2ba24581bfec447e8c02de0076bfddc..a569b25f638246f6848612d73d5f7a973779927e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.unary;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.object.DynamicObject;
@@ -47,7 +48,10 @@ import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 
+@ImportStatic(RRuntime.class)
 public abstract class CastListNode extends CastBaseNode {
 
     @Child private SetClassAttributeNode setClassAttrNode;
@@ -154,9 +158,18 @@ public abstract class CastListNode extends CastBaseNode {
         return RDataFactory.createList(new Object[]{ri});
     }
 
-    @Specialization(guards = {"isForeignObject(to)"})
-    protected RList doForeignObject(TruffleObject to) {
-        return RDataFactory.createList(new Object[]{to});
+    @Specialization(guards = {"isForeignObject(obj)"})
+    protected RList doForeignObject(TruffleObject obj,
+                    @Cached("createForeignArray2RNode()") ForeignArray2R foreignArray2R) {
+
+        Object o = foreignArray2R.execute(obj, true);
+        if (!RRuntime.isForeignObject(o)) {
+            if (o instanceof RList) {
+                return (RList) o;
+            }
+            return (RList) execute(o);
+        }
+        return RDataFactory.createList(new Object[]{obj});
     }
 
     public static CastListNode create() {
@@ -170,4 +183,8 @@ public abstract class CastListNode extends CastBaseNode {
     protected boolean isForeignObject(TruffleObject to) {
         return RRuntime.isForeignObject(to);
     }
+
+    protected ForeignArray2R createForeignArray2RNode() {
+        return ForeignArray2RNodeGen.create();
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
index 4cd7f7ffc2041169795b2b0774b60aae2eb094b3..9080f05e09a9f6421d18f00831fee0b042d63316 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java
@@ -25,8 +25,12 @@ package com.oracle.truffle.r.nodes.unary;
 import java.util.Arrays;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplexVector;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -40,8 +44,11 @@ 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.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
+@ImportStatic(RRuntime.class)
 public abstract class CastLogicalNode extends CastLogicalBaseNode {
 
     private final NAProfile naProfile = NAProfile.create();
@@ -186,6 +193,22 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode {
         return missing;
     }
 
+    @Specialization(guards = "isForeignObject(obj)")
+    protected RLogicalVector doForeignObject(TruffleObject obj,
+                    @Cached("createForeignArray2RNode()") ForeignArray2R foreignArray2R) {
+        Object o = foreignArray2R.execute(obj, true);
+        if (!RRuntime.isForeignObject(o)) {
+            if (o instanceof RLogicalVector) {
+                return (RLogicalVector) o;
+            }
+            o = castLogicalRecursive(o);
+            if (o instanceof RLogicalVector) {
+                return (RLogicalVector) o;
+            }
+        }
+        throw error(RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "vector");
+    }
+
     public static CastLogicalNode create() {
         return CastLogicalNodeGen.create(true, true, true);
     }
@@ -197,4 +220,8 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode {
     public static CastLogicalNode createNonPreserving() {
         return CastLogicalNodeGen.create(false, false, false);
     }
+
+    protected ForeignArray2R createForeignArray2RNode() {
+        return ForeignArray2RNodeGen.create();
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
index 66cc1de16106911653b8e49691134ee0778d02fb..1f413ee259640ac3c92cebc25bf33a3190a21733 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastStringNode.java
@@ -22,19 +22,29 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
+import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.RDeparse;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 
+@ImportStatic(RRuntime.class)
 public abstract class CastStringNode extends CastStringBaseNode {
 
+    @Child private CastStringNode recursiveCastString;
+
     protected CastStringNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
         this(preserveNames, preserveDimensions, preserveAttributes, false);
     }
@@ -83,6 +93,22 @@ public abstract class CastStringNode extends CastStringBaseNode {
         return vectorCopy(operand, sdata);
     }
 
+    @Specialization(guards = "isForeignObject(obj)")
+    protected RStringVector doForeignObject(TruffleObject obj,
+                    @Cached("createForeignArray2RNode()") ForeignArray2R foreignArray2R) {
+        Object o = foreignArray2R.execute(obj, true);
+        if (!RRuntime.isForeignObject(o)) {
+            if (o instanceof RStringVector) {
+                return (RStringVector) o;
+            }
+            o = castStringRecursive(o);
+            if (o instanceof RStringVector) {
+                return (RStringVector) o;
+            }
+        }
+        throw error(RError.Message.CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR, "vector");
+    }
+
     @Specialization
     protected String doRSymbol(RSymbol s) {
         return s.getName();
@@ -99,4 +125,16 @@ public abstract class CastStringNode extends CastStringBaseNode {
     public static CastStringNode createNonPreserving() {
         return CastStringNodeGen.create(false, false, false);
     }
+
+    protected ForeignArray2R createForeignArray2RNode() {
+        return ForeignArray2RNodeGen.create();
+    }
+
+    private Object castStringRecursive(Object o) {
+        if (recursiveCastString == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            recursiveCastString = insert(CastStringNodeGen.create(preserveNames(), preserveDimensions(), preserveAttributes()));
+        }
+        return recursiveCastString.executeString(o);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java
deleted file mode 100644
index 383e4adb83981d2687459d79f18864669741aa4e..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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
- * 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.unary;
-
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RFunction;
-import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RPairList;
-import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
-import com.oracle.truffle.r.runtime.env.REnvironment;
-
-public abstract class CastToContainerNode extends CastBaseNode {
-
-    public abstract Object executeObject(Object value);
-
-    protected CastToContainerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) {
-        this(preserveNames, preserveDimensions, preserveAttributes, false);
-    }
-
-    protected CastToContainerNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes, boolean forRFFI) {
-        super(preserveNames, preserveDimensions, preserveAttributes, forRFFI);
-    }
-
-    @Override
-    protected final RType getTargetType() {
-        return RType.Any;
-    }
-
-    @Specialization
-    @SuppressWarnings("unused")
-    protected RNull castNull(RNull rnull) {
-        return RNull.instance;
-    }
-
-    @Specialization
-    protected RFunction castFunction(RFunction f) {
-        return f;
-    }
-
-    @Specialization
-    protected RAbstractVector cast(RAbstractVector vector) {
-        return vector;
-    }
-
-    @Specialization
-    protected RLanguage cast(RLanguage lang) {
-        return lang;
-    }
-
-    @Specialization
-    protected RPairList cast(RPairList pairlist) {
-        return pairlist;
-    }
-
-    @Specialization
-    protected REnvironment cast(REnvironment env) {
-        return env;
-    }
-}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
index 42edcbb3ac9b8481281e8f7f631dbf241da2c6dd..9fc48e238af3b92c8c436b8ac2f1ea8df9ddc596 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ConvertBooleanNode.java
@@ -22,9 +22,13 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.NodeChild;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -39,15 +43,19 @@ 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.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2RNodeGen;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
 @NodeChild("operand")
+@ImportStatic(RRuntime.class)
 public abstract class ConvertBooleanNode extends RNode {
 
     private final NAProfile naProfile = NAProfile.create();
     private final BranchProfile invalidElementCountBranch = BranchProfile.create();
+    @Child private ConvertBooleanNode recursiveConvertBoolean;
 
     @Override
     public final Object execute(VirtualFrame frame) {
@@ -165,6 +173,16 @@ public abstract class ConvertBooleanNode extends RNode {
         throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
     }
 
+    @Specialization(guards = "isForeignObject(obj)")
+    protected byte doForeignObject(VirtualFrame frame, TruffleObject obj,
+                    @Cached("createForeignArray2RNode()") ForeignArray2R foreignArray2R) {
+        Object o = foreignArray2R.execute(obj, true);
+        if (!RRuntime.isForeignObject(o)) {
+            return convertBooleanRecursive(frame, o);
+        }
+        throw error(RError.Message.ARGUMENT_NOT_INTERPRETABLE_LOGICAL);
+    }
+
     public static ConvertBooleanNode create(RSyntaxNode node) {
         if (node instanceof ConvertBooleanNode) {
             return (ConvertBooleanNode) node;
@@ -177,4 +195,16 @@ public abstract class ConvertBooleanNode extends RNode {
     public RSyntaxNode getRSyntaxNode() {
         return getOperand().asRSyntaxNode();
     }
+
+    protected ForeignArray2R createForeignArray2RNode() {
+        return ForeignArray2RNodeGen.create();
+    }
+
+    protected byte convertBooleanRecursive(VirtualFrame frame, Object o) {
+        if (recursiveConvertBoolean == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            recursiveConvertBoolean = insert(ConvertBooleanNode.create(getRSyntaxNode()));
+        }
+        return recursiveConvertBoolean.executeByte(frame, o);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
index 52c861931e2d24a3b67b5c957da3e29cda2bd900..4b8964a8834e3e73e9d8f2bf510c0b36efca0797 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java
@@ -22,10 +22,20 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ArityException;
+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.interop.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -48,10 +58,14 @@ import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.interop.Foreign2R;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
+import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.isForeignArray;
+import static com.oracle.truffle.r.runtime.interop.ForeignArray2R.isJavaIterable;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 @SuppressWarnings("unused")
-@ImportStatic(RRuntime.class)
+@ImportStatic({Message.class, RRuntime.class, ForeignArray2R.class, Foreign2R.class})
 public abstract class PrecedenceNode extends RBaseNode {
 
     public static final int NO_PRECEDENCE = -1;
@@ -194,7 +208,7 @@ public abstract class PrecedenceNode extends RBaseNode {
 
     @Specialization
     protected int doExpression(RLanguage val, boolean recursive) {
-        return EXPRESSION_PRECEDENCE;
+        return LIST_PRECEDENCE;
     }
 
     @Specialization
@@ -212,18 +226,98 @@ public abstract class PrecedenceNode extends RBaseNode {
         return LIST_PRECEDENCE;
     }
 
-    @Specialization(guards = {"isForeignObject(to)"})
-    protected int doForeignObject(TruffleObject to, boolean recursive) {
-        return LIST_PRECEDENCE;
-    }
-
     @Specialization(guards = {"!recursive", "args.getLength() == 1"})
     protected int doArgsValuesAndNames(RArgsValuesAndNames args, boolean recursive,
                     @Cached("createRecursive()") PrecedenceNode precedenceNode) {
         return precedenceNode.executeInteger(args.getArgument(0), recursive);
     }
 
-    protected boolean isForeignObject(TruffleObject to) {
-        return RRuntime.isForeignObject(to);
+    @Specialization(guards = {"isForeignObject(to)", "!isJavaIterable(to)", "!isForeignArray(to, hasSize)"})
+    protected int doForeignObject(TruffleObject to, boolean recursive,
+                    @Cached("HAS_SIZE.createNode()") Node hasSize) {
+        return LIST_PRECEDENCE;
+    }
+
+    @Specialization(guards = {"isJavaIterable(obj)"})
+    protected int doJavaIterable(TruffleObject obj, boolean recursive,
+                    @Cached("HAS_SIZE.createNode()") Node hasSize,
+                    @Cached("READ.createNode()") Node read,
+                    @Cached("createExecute(0).createNode()") Node execute,
+                    @Cached("createRecursive()") PrecedenceNode precedenceNode,
+                    @Cached("createForeign2R()") Foreign2R foreign2R) {
+        int precedence = -1;
+        try {
+            TruffleObject itFunction = (TruffleObject) ForeignAccess.sendRead(read, obj, "iterator");
+            TruffleObject it = (TruffleObject) ForeignAccess.sendExecute(execute, itFunction);
+            TruffleObject hasNextFunction = (TruffleObject) ForeignAccess.sendRead(read, it, "hasNext");
+
+            while ((boolean) ForeignAccess.sendExecute(execute, hasNextFunction)) {
+                TruffleObject nextFunction = (TruffleObject) ForeignAccess.sendRead(read, it, "next");
+                Object element = ForeignAccess.sendExecute(execute, nextFunction);
+                element = foreign2R.execute(element);
+                if (!recursive && (isJavaIterable(element) || isForeignArray(element, hasSize))) {
+                    return LIST_PRECEDENCE;
+                } else {
+                    precedence = Math.max(precedence, precedenceNode.executeInteger(element, recursive));
+                }
+            }
+        } catch (ArityException | UnsupportedTypeException | UnsupportedMessageException | UnknownIdentifierException ex) {
+            throw error(RError.Message.GENERIC, "error while accessing java iterable: " + ex.getMessage());
+        }
+        return precedence;
+    }
+
+    @Specialization(guards = {"isForeignArray(obj, hasSize)"})
+    protected int doForeignArray(TruffleObject obj, boolean recursive,
+                    @Cached("HAS_SIZE.createNode()") Node hasSize,
+                    @Cached("GET_SIZE.createNode()") Node getSize,
+                    @Cached("READ.createNode()") Node read,
+                    @Cached("createRecursive()") PrecedenceNode precedenceNode,
+                    @Cached("createForeign2R()") Foreign2R foreign2R) {
+        int precedence = -1;
+        try {
+            if (JavaInterop.isJavaObject(obj)) {
+                Object o = JavaInterop.asJavaObject(Object.class, obj);
+                Class<?> ct = o.getClass().getComponentType();
+                int prc = getPrecedence(ct, recursive);
+                if (prc != -1) {
+                    return prc;
+                }
+            }
+            int size = (int) ForeignAccess.sendGetSize(getSize, obj);
+            for (int i = 0; i < size; i++) {
+                Object element = ForeignAccess.sendRead(read, obj, i);
+                element = foreign2R.execute(element);
+                if (!recursive && (isForeignArray(element, hasSize) || isJavaIterable(element))) {
+                    return LIST_PRECEDENCE;
+                } else {
+                    precedence = Math.max(precedence, precedenceNode.executeInteger(element, recursive));
+                }
+            }
+        } catch (UnknownIdentifierException | UnsupportedMessageException ex) {
+            throw error(RError.Message.GENERIC, "error while accessing array: " + ex.getMessage());
+        }
+        return precedence;
+    }
+
+    @TruffleBoundary
+    private int getPrecedence(Class<?> ct, boolean recursive) {
+        if (recursive && ct.isArray()) {
+            return getPrecedence(ct.getComponentType(), recursive);
+        }
+        return getPrecedence(ct);
+    }
+
+    private static int getPrecedence(Class<?> ct) {
+        if (ct == Integer.class || ct == Byte.class || ct == Short.class || ct == int.class || ct == byte.class || ct == short.class) {
+            return INT_PRECEDENCE;
+        } else if (ct == Double.class || ct == Float.class || ct == Long.class || ct == double.class || ct == float.class || ct == long.class) {
+            return DOUBLE_PRECEDENCE;
+        } else if (ct == String.class || ct == Character.class || ct == char.class) {
+            return STRING_PRECEDENCE;
+        } else if (ct == Boolean.class || ct == boolean.class) {
+            return LOGICAL_PRECEDENCE;
+        }
+        return NO_PRECEDENCE;
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
index ba6bf5714fabbcb7f76cb23751ebbd3ccd328cf7..a1c1be8b9cc5536b6745ef7bc14201e0d5c8f37e 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/ToStringNode.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
+import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
@@ -157,8 +158,8 @@ public abstract class ToStringNode extends RBaseNode {
         String apply(int index, boolean quotes, String separator);
     }
 
-    @TruffleBoundary
     private static String createResultForVector(RAbstractVector vector, boolean quotes, String separator, String empty, ElementFunction elementFunction) {
+        CompilerAsserts.neverPartOfCompilation();
         int length = vector.getLength();
         if (length == 0) {
             return empty;
@@ -174,40 +175,43 @@ public abstract class ToStringNode extends RBaseNode {
     }
 
     @Specialization
+    @TruffleBoundary
     protected String toString(RAbstractIntVector vector, boolean quotes, String separator) {
         return createResultForVector(vector, quotes, separator, "integer(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s));
     }
 
     @Specialization
     @TruffleBoundary
-    // boundary because of complex numerical string formatting
     protected String toString(RAbstractDoubleVector vector, boolean quotes, String separator) {
         return createResultForVector(vector, quotes, separator, "numeric(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s));
     }
 
     @Specialization
     @TruffleBoundary
-    // boundary because of string quoting
     protected String toString(RAbstractStringVector vector, boolean quotes, String separator) {
         return createResultForVector(vector, quotes, separator, "character(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s));
     }
 
     @Specialization
+    @TruffleBoundary
     protected String toString(RAbstractLogicalVector vector, boolean quotes, String separator) {
         return createResultForVector(vector, quotes, separator, "logical(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s));
     }
 
     @Specialization
+    @TruffleBoundary
     protected String toString(RAbstractRawVector vector, boolean quotes, String separator) {
         return createResultForVector(vector, quotes, separator, "raw(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s));
     }
 
     @Specialization
+    @TruffleBoundary
     protected String toString(RAbstractComplexVector vector, boolean quotes, String separator) {
         return createResultForVector(vector, quotes, separator, "complex(0)", (index, q, s) -> toString(vector.getDataAt(index), q, s));
     }
 
     @Specialization
+    @TruffleBoundary
     protected String toString(RList vector, boolean quotes, String separator) {
         return createResultForVector(vector, quotes, separator, "list()", (index, q, s) -> {
             Object value = vector.getDataAt(index);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
index c2e606b1f73a542fce854d221e417ee5848b8d36..b41f76c5bbe2f89b07c633ee5caf81455e58faf5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/TypeofNode.java
@@ -93,7 +93,7 @@ public abstract class TypeofNode extends UnaryNode {
 
     public static RType getTypeof(Object operand) {
         CompilerAsserts.neverPartOfCompilation();
-        return ((RTypedValue) RRuntime.asAbstractVector(operand)).getRType();
+        return ((RTypedValue) RRuntime.convertScalarVectors(operand)).getRType();
     }
 
     public static TypeofNode create() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java
index b251f47a8409c50103beae9c99b8ebc40e918665..43a61ee7c7fcaca0e166ddbe1d2d365ec94d7c1b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticBuiltinNode.java
@@ -22,96 +22,25 @@
  */
 package com.oracle.truffle.r.nodes.unary;
 
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
-import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNodeGen;
+import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RType;
-import com.oracle.truffle.r.runtime.data.RComplex;
-import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
-public abstract class UnaryArithmeticBuiltinNode extends RBuiltinNode.Arg1 implements UnaryArithmeticFactory {
+public final class UnaryArithmeticBuiltinNode extends RBuiltinNode.Arg1 {
 
-    @Child private BoxPrimitiveNode boxPrimitive = BoxPrimitiveNodeGen.create();
-    @Child private UnaryArithmeticNode unaryNode;
-
-    protected UnaryArithmeticBuiltinNode(RType minPrecedence, RError.Message error, Object[] errorArgs) {
-        unaryNode = UnaryArithmeticNodeGen.create(this, minPrecedence, error, errorArgs);
+    {
+        Casts casts = new Casts(UnaryArithmeticBuiltinNode.class);
+        casts.arg(0).boxPrimitive();
     }
 
-    protected UnaryArithmeticBuiltinNode(RType minPrecedence) {
-        unaryNode = UnaryArithmeticNodeGen.create(this, minPrecedence, RError.Message.ARGUMENTS_PASSED, new Object[]{0, "'" + getRBuiltin().name() + "'", 1});
-    }
+    @Child private UnaryArithmeticNode unaryNode;
 
-    @Specialization
-    public Object calculateUnboxed(Object value) {
-        return unaryNode.execute(boxPrimitive.execute(value));
+    public UnaryArithmeticBuiltinNode(UnaryArithmeticFactory factory) {
+        unaryNode = UnaryArithmeticNodeGen.create(factory);
     }
 
     @Override
-    public UnaryArithmetic createOperation() {
-        return new UnaryArithmetic() {
-
-            @Override
-            public RType calculateResultType(RType argumentType) {
-                return UnaryArithmeticBuiltinNode.this.calculateResultType(argumentType);
-            }
-
-            @Override
-            public double opd(double re, double im) {
-                return UnaryArithmeticBuiltinNode.this.opd(re, im);
-            }
-
-            @Override
-            public int op(byte op) {
-                return UnaryArithmeticBuiltinNode.this.op(op);
-            }
-
-            @Override
-            public int op(int op) {
-                return UnaryArithmeticBuiltinNode.this.op(op);
-            }
-
-            @Override
-            public double op(double op) {
-                return UnaryArithmeticBuiltinNode.this.op(op);
-            }
-
-            @Override
-            public RComplex op(double re, double im) {
-                return UnaryArithmeticBuiltinNode.this.op(re, im);
-            }
-        };
-    }
-
-    protected RType calculateResultType(RType argumentType) {
-        return argumentType;
-    }
-
-    @SuppressWarnings("unused")
-    protected int op(byte op) {
-        throw new UnsupportedOperationException();
-    }
-
-    @SuppressWarnings("unused")
-    protected int op(int op) {
-        throw new UnsupportedOperationException();
-    }
-
-    @SuppressWarnings("unused")
-    protected double op(double op) {
-        throw new UnsupportedOperationException();
-    }
-
-    @SuppressWarnings("unused")
-    protected RComplex op(double re, double im) {
-        throw new UnsupportedOperationException();
-    }
-
-    @SuppressWarnings("unused")
-    protected double opd(double re, double im) {
-        throw new UnsupportedOperationException();
+    public Object execute(VirtualFrame frame, Object value) {
+        return unaryNode.execute(value);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
index 2e4061d8fe6cf3a61dcbd7d29f35a37d41ecded6..1f0892d7285603e2bf2950d8ba38a5b7df910ed3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticNode.java
@@ -29,40 +29,24 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.r.nodes.primitive.UnaryMapNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
-import com.oracle.truffle.r.runtime.RError.Message;
-import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RMissing;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 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.RAbstractLogicalVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
 
 public abstract class UnaryArithmeticNode extends UnaryNode {
 
     protected final UnaryArithmeticFactory unary;
-    private final Message error;
-    private final Object[] errorArgs;
-    protected final RType minPrecedence;
 
-    public UnaryArithmeticNode(UnaryArithmeticFactory factory, RType minPrecedence, Message error, Object... errorArgs) {
+    public UnaryArithmeticNode(UnaryArithmeticFactory factory) {
         this.unary = factory;
-        this.error = error;
-        this.errorArgs = errorArgs;
-        this.minPrecedence = minPrecedence;
-    }
-
-    public UnaryArithmeticNode(UnaryArithmeticFactory factory, Message error, RType minPrecedence) {
-        this.unary = factory;
-        this.error = error;
-        this.minPrecedence = minPrecedence;
-        this.errorArgs = null;
-    }
-
-    public UnaryArithmeticNode(UnaryArithmeticFactory factory, Message error) {
-        this(factory, error, RType.Integer);
     }
 
     public abstract Object execute(Object value);
@@ -75,17 +59,17 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
 
     protected UnaryMapNode createCachedFast(Object operand) {
         if (isNumericVector(operand)) {
-            return createCached(unary.createOperation(), operand, minPrecedence);
+            return createCached(unary.createOperation(), operand);
         }
         return null;
     }
 
-    protected static UnaryMapNode createCached(UnaryArithmetic arithmetic, Object operand, RType minPrecedence) {
+    protected static UnaryMapNode createCached(UnaryArithmetic arithmetic, Object operand) {
         if (operand instanceof RAbstractVector) {
             RAbstractVector castOperand = (RAbstractVector) operand;
             RType operandType = castOperand.getRType();
             if (operandType.isNumeric()) {
-                RType type = RType.maxPrecedence(operandType, minPrecedence);
+                RType type = RType.maxPrecedence(operandType, arithmetic.getMinPrecedence());
                 RType resultType = arithmetic.calculateResultType(type);
                 return UnaryMapNode.create(new ScalarUnaryArithmeticNode(arithmetic), castOperand, type, resultType);
             }
@@ -101,24 +85,24 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
     @TruffleBoundary
     protected Object doGeneric(Object operand,
                     @Cached("unary.createOperation()") UnaryArithmetic arithmetic,
-                    @Cached("new(createCached(arithmetic, operand, minPrecedence), minPrecedence)") GenericNumericVectorNode generic) {
+                    @Cached("new(createCached(arithmetic, operand))") GenericNumericVectorNode generic) {
         RAbstractVector operandVector = (RAbstractVector) operand;
         return generic.get(arithmetic, operandVector).apply(operandVector);
     }
 
+    @Override
+    public RBaseNode getErrorContext() {
+        return this;
+    }
+
     @Fallback
-    protected Object invalidArgType(@SuppressWarnings("unused") Object operand) {
+    protected Object invalidArgType(Object operand) {
         CompilerDirectives.transferToInterpreter();
-        if (errorArgs == null || errorArgs.length == 0) {
-            throw error(error);
-        } else if (errorArgs.length == 1) {
-            throw error(error, errorArgs[0]);
-        } else if (errorArgs.length == 2) {
-            throw error(error, errorArgs[0], errorArgs[1]);
-        } else if (errorArgs.length == 3) {
-            throw error(error, errorArgs[0], errorArgs[1], errorArgs[2]);
+        UnaryArithmetic op = unary.createOperation();
+        if (operand instanceof RMissing) {
+            throw error(RError.Message.ARGUMENTS_PASSED, 0, "'" + op.getClass().getSimpleName().toLowerCase() + "'", 1);
         } else {
-            throw RInternalError.shouldNotReachHere("too many error arguments in UnaryArithmeticNode");
+            throw error(op.getArgumentError());
         }
     }
 
@@ -126,17 +110,14 @@ public abstract class UnaryArithmeticNode extends UnaryNode {
 
         @Child private UnaryMapNode cached;
 
-        private final RType minPrecedence;
-
-        public GenericNumericVectorNode(UnaryMapNode cachedOperation, RType minPrecedence) {
+        public GenericNumericVectorNode(UnaryMapNode cachedOperation) {
             this.cached = cachedOperation;
-            this.minPrecedence = minPrecedence;
         }
 
         public UnaryMapNode get(UnaryArithmetic arithmetic, RAbstractVector operand) {
             UnaryMapNode next = cached;
             if (!next.isSupported(operand)) {
-                next = cached.replace(createCached(arithmetic, operand, minPrecedence));
+                next = cached.replace(createCached(arithmetic, operand));
             }
             return next;
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
index 5b66205f4b5eba5ae1d23b4bdbe465f8452f383c..369ea71c7184823354b34bb077956e5a4d42d99a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java
@@ -24,9 +24,15 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.dsl.TypeSystemReference;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -37,10 +43,9 @@ import com.oracle.truffle.r.runtime.data.RIntSequence;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
-import com.oracle.truffle.r.runtime.data.RRaw;
-import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTypes;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmetic;
 import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory;
@@ -54,6 +59,7 @@ import com.oracle.truffle.r.runtime.ops.na.NACheck;
  * (e.g. logical). The only situation where semantics of finite is different to na.rm is double
  * values: na.rm removes NA and NaN, but not -/+Inf.
  */
+@ImportStatic({ForeignArray2R.class, Message.class, RRuntime.class})
 @TypeSystemReference(RTypes.class)
 public abstract class UnaryArithmeticReduceNode extends RBaseNode {
 
@@ -64,6 +70,8 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
 
     private final BinaryArithmeticFactory factory;
     protected final ReduceSemantics semantics;
+    protected final boolean supportString;
+    protected final boolean supportComplex;
 
     private final NACheck na = NACheck.create();
     private final ConditionProfile naRmProfile = ConditionProfile.createBinaryProfile();
@@ -72,6 +80,8 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         this.factory = factory;
         this.semantics = semantics;
         this.arithmetic = factory.createOperation();
+        this.supportString = semantics.supportString;
+        this.supportComplex = semantics.supportComplex;
     }
 
     private String handleString(RStringVector operand, boolean naRm, boolean finite, int offset) {
@@ -158,54 +168,40 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         }
     }
 
-    @Specialization
+    @Specialization(guards = "supportComplex")
     protected RComplex doComplex(RComplex operand, boolean naRm, @SuppressWarnings("unused") boolean finite) {
-        if (semantics.supportComplex) {
-            na.enable(operand);
-            if (naRmProfile.profile(naRm)) {
-                if (na.check(operand)) {
-                    emptyWarning();
-                    return RRuntime.double2complex(semantics.getDoubleStart());
-                } else {
-                    return operand;
-                }
+        na.enable(operand);
+        if (naRmProfile.profile(naRm)) {
+            if (na.check(operand)) {
+                emptyWarning();
+                return RRuntime.double2complex(semantics.getDoubleStart());
             } else {
-                return na.check(operand) ? RComplex.createNA() : operand;
+                return operand;
             }
         } else {
-            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex");
+            return na.check(operand) ? RComplex.createNA() : operand;
         }
     }
 
-    @Specialization
+    @Specialization(guards = "supportString")
     protected String doString(String operand, boolean naRm, @SuppressWarnings("unused") boolean finite) {
-        if (semantics.supportString) {
-            na.enable(operand);
-            if (naRmProfile.profile(naRm)) {
-                if (na.check(operand)) {
-                    if (semantics.getEmptyWarning() != null) {
-                        RError.warning(this, semantics.emptyWarningCharacter);
-                    }
-                    return semantics.getStringStart();
-                } else {
-                    return operand;
+        na.enable(operand);
+        if (naRmProfile.profile(naRm)) {
+            if (na.check(operand)) {
+                if (semantics.getEmptyWarning() != null) {
+                    RError.warning(this, semantics.emptyWarningCharacter);
                 }
+                return semantics.getStringStart();
             } else {
-                return na.check(operand) ? RRuntime.STRING_NA : operand;
+                return operand;
             }
         } else {
-            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
+            return na.check(operand) ? RRuntime.STRING_NA : operand;
         }
     }
 
-    @SuppressWarnings("unused")
-    @Specialization
-    protected RRaw doString(RRaw operand, boolean naRm, boolean finite) {
-        throw error(RError.Message.INVALID_TYPE_ARGUMENT, "raw");
-    }
-
     @Specialization
-    protected int doIntVector(RIntVector operand, boolean naRm, boolean finite) {
+    protected Object doIntVector(RIntVector operand, boolean naRm, boolean finite) {
         RBaseNode.reportWork(this, operand.getLength());
         boolean profiledNaRm = naRmProfile.profile(naRm || finite);
         int result = semantics.getIntStart();
@@ -231,6 +227,9 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         }
         if (opCount == 0) {
             emptyWarning();
+            if (semantics.isUseDoubleStartForEmptyVector()) {
+                return semantics.getDoubleStart();
+            }
         }
         return result;
     }
@@ -272,7 +271,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
     }
 
     @Specialization
-    protected int doLogicalVector(RLogicalVector operand, boolean naRm, @SuppressWarnings("unused") boolean finite) {
+    protected Object doLogicalVector(RLogicalVector operand, boolean naRm, @SuppressWarnings("unused") boolean finite) {
         RBaseNode.reportWork(this, operand.getLength());
         boolean profiledNaRm = naRmProfile.profile(naRm);
         int result = semantics.getIntStart();
@@ -298,12 +297,15 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         }
         if (opCount == 0) {
             emptyWarning();
+            if (semantics.isUseDoubleStartForEmptyVector()) {
+                return semantics.getDoubleStart();
+            }
         }
         return result;
     }
 
     @Specialization
-    protected int doIntSequence(RIntSequence operand, @SuppressWarnings("unused") boolean naRm, @SuppressWarnings("unused") boolean finite) {
+    protected Object doIntSequence(RIntSequence operand, @SuppressWarnings("unused") boolean naRm, @SuppressWarnings("unused") boolean finite) {
         RBaseNode.reportWork(this, operand.getLength());
         int result = semantics.getIntStart();
         int current = operand.getStart();
@@ -317,6 +319,9 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         }
         if (operand.getLength() == 0) {
             emptyWarning();
+            if (semantics.isUseDoubleStartForEmptyVector()) {
+                return semantics.getDoubleStart();
+            }
         }
         return result;
     }
@@ -336,88 +341,82 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         return result;
     }
 
-    @Specialization
+    @Specialization(guards = "supportComplex")
     protected RComplex doComplexVector(RComplexVector operand, boolean naRm, boolean finite) {
         RBaseNode.reportWork(this, operand.getLength());
-        if (semantics.supportComplex) {
-            boolean profiledNaRm = naRmProfile.profile(naRm || finite);
-            RComplex result = RRuntime.double2complex(semantics.getDoubleStart());
-            int opCount = 0;
-            na.enable(operand);
-            for (int i = 0; i < operand.getLength(); i++) {
-                RComplex current = operand.getDataAt(i);
-                if (na.check(current)) {
-                    if (profiledNaRm) {
-                        continue;
-                    } else {
-                        return RComplex.createNA();
-                    }
+        boolean profiledNaRm = naRmProfile.profile(naRm || finite);
+        RComplex result = RRuntime.double2complex(semantics.getDoubleStart());
+        int opCount = 0;
+        na.enable(operand);
+        for (int i = 0; i < operand.getLength(); i++) {
+            RComplex current = operand.getDataAt(i);
+            if (na.check(current)) {
+                if (profiledNaRm) {
+                    continue;
                 } else {
-                    result = arithmetic.op(result.getRealPart(), result.getImaginaryPart(), current.getRealPart(), current.getImaginaryPart());
+                    return RComplex.createNA();
                 }
-                opCount++;
-            }
-            if (opCount == 0) {
-                emptyWarning();
+            } else {
+                result = arithmetic.op(result.getRealPart(), result.getImaginaryPart(), current.getRealPart(), current.getImaginaryPart());
             }
-            return result;
-        } else {
-            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "complex");
-
+            opCount++;
+        }
+        if (opCount == 0) {
+            emptyWarning();
         }
+        return result;
     }
 
     // the algorithm that works for other types (reducing a vector starting with the "start value")
     // does not work for String-s as, in particular, we cannot supply the (lexicographically)
     // "largest" String for the implementation of max function
 
-    @SuppressWarnings("unused")
-    private static String doStringVectorEmptyInternal(RStringVector operand, boolean naRm, boolean finite, ReduceSemantics semantics, RBaseNode invokingNode) {
-        if (semantics.supportString) {
-            if (semantics.getEmptyWarning() != null) {
-                RError.warning(invokingNode, semantics.emptyWarningCharacter);
-            }
-            return semantics.getStringStart();
-        } else {
-            throw invokingNode.error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
+    private static String doStringVectorEmptyInternal(ReduceSemantics semantics, RBaseNode invokingNode) {
+        if (semantics.getEmptyWarning() != null) {
+            RError.warning(invokingNode, semantics.emptyWarningCharacter);
         }
+        return semantics.getStringStart();
     }
 
-    @Specialization(guards = "operand.getLength() == 0")
-    protected String doStringVectorEmpty(RStringVector operand, boolean naRm, boolean finite) {
-        return doStringVectorEmptyInternal(operand, naRm, finite, semantics, this);
+    @Specialization(guards = {"supportString", "operand.getLength() == 0"})
+    protected String doStringVectorEmpty(@SuppressWarnings("unused") RStringVector operand, @SuppressWarnings("unused") boolean naRm, @SuppressWarnings("unused") boolean finite) {
+        return doStringVectorEmptyInternal(semantics, this);
     }
 
-    @Specialization(guards = "operand.getLength() == 1")
+    @Specialization(guards = {"supportString", "operand.getLength() == 1"})
     protected String doStringVectorOneElem(RStringVector operand, boolean naRm, boolean finite) {
-        if (semantics.supportString) {
-            boolean profiledNaRm = naRmProfile.profile(naRm);
-            String result = operand.getDataAt(0);
-            if (profiledNaRm) {
-                na.enable(result);
-                if (na.check(result)) {
-                    return doStringVectorEmpty(operand, naRm, finite);
-                }
+        boolean profiledNaRm = naRmProfile.profile(naRm);
+        String result = operand.getDataAt(0);
+        if (profiledNaRm) {
+            na.enable(result);
+            if (na.check(result)) {
+                return doStringVectorEmpty(operand, naRm, finite);
             }
-            return result;
-        } else {
-            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
         }
+        return result;
     }
 
-    @Specialization(guards = "operand.getLength() > 1")
+    @Specialization(guards = {"supportString", "operand.getLength() > 1"})
     protected String doStringVector(RStringVector operand, boolean naRm, boolean finite) {
-        if (semantics.supportString) {
-            return handleString(operand, naRm, finite, 0);
-        } else {
-            throw error(RError.Message.INVALID_TYPE_ARGUMENT, "character");
-        }
+        return handleString(operand, naRm, finite, 0);
     }
 
-    @SuppressWarnings("unused")
-    @Specialization
-    protected RRaw doString(RRawVector operand, boolean naRm, boolean finite) {
-        throw error(RError.Message.INVALID_TYPE_ARGUMENT, "raw");
+    @Specialization(guards = {"isForeignVector(obj, hasSize)"})
+    protected Object doForeignVector(TruffleObject obj, boolean naRm, boolean finite,
+                    @SuppressWarnings("unused") @Cached("HAS_SIZE.createNode()") Node hasSize,
+                    @Cached("createForeignArray2R()") ForeignArray2R foreignArray2R,
+                    @Cached("createRecursive()") UnaryArithmeticReduceNode recursive) {
+        Object vec = foreignArray2R.execute(obj, true);
+        return recursive.executeReduce(vec, naRm, finite);
+    }
+
+    @Fallback
+    protected Object doFallback(Object obj, @SuppressWarnings("unused") boolean naRm, @SuppressWarnings("unused") boolean infinite) {
+        throw error(RError.Message.INVALID_TYPE_ARGUMENT, Predef.typeName().apply(obj));
+    }
+
+    protected UnaryArithmeticReduceNode createRecursive() {
+        return UnaryArithmeticReduceNodeGen.create(semantics, factory);
     }
 
     public static final class ReduceSemantics {
@@ -431,9 +430,10 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         private final RError.Message naResultWarning;
         private final boolean supportComplex;
         private final boolean supportString;
+        private final boolean useDoubleStartForEmptyVector;
 
         public ReduceSemantics(int intStart, double doubleStart, boolean nullInt, RError.Message emptyWarning, RError.Message emptyWarningCharacter, RError.Message naResultWarning,
-                        boolean supportComplex, boolean supportString) {
+                        boolean supportComplex, boolean supportString, boolean useDoubleStartForEmptyVector) {
             this.intStart = intStart;
             this.doubleStart = doubleStart;
             this.nullInt = nullInt;
@@ -442,10 +442,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
             this.naResultWarning = naResultWarning;
             this.supportComplex = supportComplex;
             this.supportString = supportString;
-        }
-
-        public ReduceSemantics(int intStart, double doubleStart, boolean nullInt, RError.Message emptyWarning, RError.Message emptyWarningCharacter, boolean supportComplex, boolean supportString) {
-            this(intStart, doubleStart, nullInt, emptyWarning, emptyWarningCharacter, null, supportComplex, supportString);
+            this.useDoubleStartForEmptyVector = useDoubleStartForEmptyVector;
         }
 
         public int getIntStart() {
@@ -475,6 +472,10 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
         public RError.Message getNAResultWarning() {
             return naResultWarning;
         }
+
+        public boolean isUseDoubleStartForEmptyVector() {
+            return useDoubleStartForEmptyVector;
+        }
     }
 
     private static final class MultiElemStringHandlerNode extends RBaseNode {
@@ -511,7 +512,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode {
                     // the following is meant to eliminate leading NA-s
                     if (offset == operand.getLength() - 1) {
                         // last element - all other are NAs
-                        return doStringVectorEmptyInternal(operand, naRm, finite, semantics, this);
+                        return doStringVectorEmptyInternal(semantics, this);
                     } else {
                         return handleString(operand, naRm, finite, offset + 1);
                     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticSpecial.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticSpecial.java
new file mode 100644
index 0000000000000000000000000000000000000000..1b42ac2e6224cb603a925c75a80c4e48506108f7
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticSpecial.java
@@ -0,0 +1,101 @@
+/*
+ * 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.nodes.unary;
+
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.ImportStatic;
+import com.oracle.truffle.api.dsl.NodeChild;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.binary.BoxPrimitiveNode;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.builtins.RSpecialFactory;
+import com.oracle.truffle.r.runtime.nodes.RNode;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmetic;
+import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory;
+
+/**
+ * Fast-path for scalar values: these cannot have any class attribute. Note: we intentionally use
+ * empty type system to avoid conversions to vector types.
+ */
+@ImportStatic(RType.class)
+@NodeChild(value = "operand", type = RNode.class)
+public abstract class UnaryArithmeticSpecial extends RNode {
+
+    private final UnaryArithmeticFactory unaryFactory;
+
+    @Child protected UnaryArithmetic operation;
+
+    protected UnaryArithmeticSpecial(UnaryArithmeticFactory unaryFactory) {
+        this.unaryFactory = unaryFactory;
+        this.operation = unaryFactory.createOperation();
+    }
+
+    public static RSpecialFactory createSpecialFactory(UnaryArithmeticFactory unaryFactory) {
+        return (signature, arguments, inReplacement) -> signature.getNonNullCount() == 0 && arguments.length == 1
+                        ? UnaryArithmeticSpecialNodeGen.create(unaryFactory, arguments[0]) : null;
+    }
+
+    @Specialization
+    protected double doDoubles(double operand,
+                    @Cached("createBinaryProfile()") ConditionProfile naProfile) {
+        if (naProfile.profile(RRuntime.isNA(operand))) {
+            return operand;
+        }
+        return getOperation().op(operand);
+    }
+
+    protected UnaryArithmeticNode createFull() {
+        return UnaryArithmeticNodeGen.create(unaryFactory);
+    }
+
+    @Specialization(guards = "operation.getMinPrecedence() == Integer")
+    public int doIntegers(int operand,
+                    @Cached("createBinaryProfile()") ConditionProfile naProfile) {
+        if (naProfile.profile(RRuntime.isNA(operand))) {
+            return RRuntime.INT_NA;
+        }
+        return getOperation().op(operand);
+    }
+
+    @Specialization(guards = "operation.getMinPrecedence() == Double")
+    public double doIntegersDouble(int operand,
+                    @Cached("createBinaryProfile()") ConditionProfile naProfile) {
+        if (naProfile.profile(RRuntime.isNA(operand))) {
+            return RRuntime.INT_NA;
+        }
+        return getOperation().op((double) operand);
+    }
+
+    @Specialization
+    protected Object doFallback(Object operand,
+                    @Cached("create()") BoxPrimitiveNode boxPrimitive,
+                    @Cached("createFull()") UnaryArithmeticNode unary) {
+        return unary.execute(boxPrimitive.execute(operand));
+    }
+
+    protected UnaryArithmetic getOperation() {
+        return operation;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
index 29484784d21defcb7b3e791c940e8b4c77ca75ad..a6f079c76d74c2b219bfff5d7cb0b9b60868e621 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNotNode.java
@@ -23,12 +23,18 @@
 package com.oracle.truffle.r.nodes.unary;
 
 import static com.oracle.truffle.r.runtime.RDispatch.OPS_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 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.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -45,10 +51,12 @@ 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.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.interop.ForeignArray2R;
 import com.oracle.truffle.r.runtime.ops.na.NACheck;
 import com.oracle.truffle.r.runtime.ops.na.NAProfile;
 
-@RBuiltin(name = "!", kind = PRIMITIVE, parameterNames = {""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+@ImportStatic({ForeignArray2R.class, Message.class})
+@RBuiltin(name = "!", kind = PRIMITIVE, parameterNames = {""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
 public abstract class UnaryNotNode extends RBuiltinNode.Arg1 {
 
     private final NACheck na = NACheck.create();
@@ -207,6 +215,19 @@ public abstract class UnaryNotNode extends RBuiltinNode.Arg1 {
         return RDataFactory.createEmptyLogicalVector();
     }
 
+    @Specialization(guards = {"isForeignVector(obj, hasSize)"})
+    protected Object doForeign(VirtualFrame frame, TruffleObject obj,
+                    @SuppressWarnings("unused") @Cached("HAS_SIZE.createNode()") Node hasSize,
+                    @Cached("createForeignArray2R()") ForeignArray2R foreignArray2R,
+                    @Cached("createRecursive()") UnaryNotNode recursive) {
+        Object vec = foreignArray2R.execute(obj, true);
+        return recursive.execute(frame, vec);
+    }
+
+    protected UnaryNotNode createRecursive() {
+        return UnaryNotNodeGen.create();
+    }
+
     @Fallback
     protected Object invalidArgType(@SuppressWarnings("unused") Object operand) {
         throw error(RError.Message.INVALID_ARG_TYPE);
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java
index a058b86051debe14e79acfd5306b94d49ad5916b..b9cbcdb5646fd53dadd8c4de017941b878062982 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/DefaultRParserFactory.java
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.runtime.RParserFactory;
 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.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 
 public class DefaultRParserFactory extends RParserFactory {
@@ -41,10 +42,10 @@ public class DefaultRParserFactory extends RParserFactory {
     private static class DefaultParser<T> implements Parser<T> {
 
         @Override
-        public List<T> script(Source source, RCodeBuilder<T> builder) throws ParseException {
+        public List<T> script(Source source, RCodeBuilder<T> builder, TruffleRLanguage language) throws ParseException {
             try {
                 try {
-                    RParser<T> parser = new RParser<>(source, builder);
+                    RParser<T> parser = new RParser<>(source, builder, language);
                     return parser.script();
                 } catch (IllegalArgumentException e) {
                     // the lexer will wrap exceptions in IllegalArgumentExceptions
@@ -60,8 +61,8 @@ public class DefaultRParserFactory extends RParserFactory {
         }
 
         @Override
-        public RootCallTarget rootFunction(Source source, String name, RCodeBuilder<T> builder) throws ParseException {
-            RParser<T> parser = new RParser<>(source, builder);
+        public RootCallTarget rootFunction(Source source, String name, RCodeBuilder<T> builder, TruffleRLanguage language) throws ParseException {
+            RParser<T> parser = new RParser<>(source, builder, language);
             try {
                 return parser.root_function(name);
             } catch (RecognitionException e) {
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
index 1af7872f3177f094f90ad57e44d6637f0b6e7f76..2e3a8e7bc7c0b8520d56344bc060b18852f27bdf 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParserGeneration.java
@@ -90,6 +90,10 @@ public class ParserGeneration {
         "support for hex float literals without decimal point: 0x0p0",
         "different warning for hex and dec integer literals",
         "raise ZERO_LENGTH_VARIABLE errors in parser",
-        "support for file delimiter"
+        "support for file delimiter",
+        "pass along TruffleRLanguage",
+        "convert line endings",
+        "handle four and more dots as identifier",
+        "allow greek characters in identifiers"
     };
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
index e7162c65d7f0dea88277c9859e8cb769411dbf38..bc57060031bc6add8132bd7f40634db89dd35536 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g
@@ -29,6 +29,10 @@ package com.oracle.truffle.r.parser;
 import java.util.ArrayList;
 import java.util.List;
 import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.net.URISyntaxException;
 
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.frame.MaterializedFrame;
@@ -41,6 +45,7 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.RSource;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
@@ -64,17 +69,19 @@ import com.oracle.truffle.r.runtime.RError;
     private Source source;
     private Source initialSource;
     private RCodeBuilder<T> builder;
+    private TruffleRLanguage language;
     private int fileStartOffset = 0;
     
     /**
      * Always use this constructor to initialize the R specific fields.
      */
-    public RParser(Source source, RCodeBuilder<T> builder) {
+    public RParser(Source source, RCodeBuilder<T> builder, TruffleRLanguage language) {
         super(new CommonTokenStream(new RLexer(new ANTLRStringStream(source.getCode()))));
         assert source != null && builder != null;
         this.source = source;
         this.initialSource = source;
         this.builder = builder;
+        this.language = language;
     }
     
     /**
@@ -146,9 +153,15 @@ import com.oracle.truffle.r.runtime.RError;
 	    		if(q0 != -1 && q1 != -1) {
 	    			String path = commentLine.substring(q0+1, q1);
 	    			try {
-                        source = RSource.fromFileName(path, false);
+	    			    String content = new String(Files.readAllBytes(Paths.get(path)), StandardCharsets.UTF_8);
+	    			    String lineEnding = detectLineEnding(initialSource.getCode());
+	    			    content = convertToLineEnding(content, lineEnding);
+                        source = RSource.fromFileName(content, path, false);
                         fileStartOffset = commentToken.getStopIndex() + 1;
                     } catch (IOException e) {
+                    	resetSource();
+                    } catch (URISyntaxException e) {
+                    	resetSource();
                     }
 	    		} else {
 	    			// fall back and use the initial source (the file being parsed)
@@ -162,6 +175,25 @@ import com.oracle.truffle.r.runtime.RError;
 		fileStartOffset = 0;
 	}
 
+	private String detectLineEnding(String code) {
+		int lf = code.indexOf("\n");
+		int crlf = code.indexOf("\r\n");
+		
+		if(crlf != -1 && crlf < lf) {
+			return "\r\n";
+		}
+		return "\n";
+	}
+	
+	private String convertToLineEnding(String content, String lineEnding) {
+		if("\n".equals(lineEnding)) {
+			return content.replaceAll("\\r\\n", "\n");
+		} else if("\r\n".equals(lineEnding)) {
+			return content.replaceAll("\\n", "\r\n");
+		}
+		return content;
+	}
+
 	// without this override, the parser will not throw exceptions if it can recover    
     @Override
     protected Object recoverFromMismatchedToken(IntStream input, int expected, BitSet follow) throws RecognitionException {
@@ -243,7 +275,7 @@ root_function [String name] returns [RootCallTarget v]
         	throw RInternalError.shouldNotReachHere("not at EOF after parsing deserialized function"); 
         }
     }
-    : n_ op=FUNCTION n_ LPAR  n_ (par_decl[params] (n_ COMMA n_ par_decl[params])* n_)? RPAR n_ body=expr_or_assign { $v = builder.rootFunction(src($op, last()), params, builder.handleQueries($body.v), name); }
+    : n_ op=FUNCTION n_ LPAR  n_ (par_decl[params] (n_ COMMA n_ par_decl[params])* n_)? RPAR n_ body=expr_or_assign { $v = builder.rootFunction(language, src($op, last()), params, builder.handleQueries($body.v), name); }
     ;
 
 statement returns [T v]
@@ -324,7 +356,7 @@ repeat_expr returns [T v]
 
 function [T assignedTo] returns [T v]
     @init { List<Argument<T>> params = new ArrayList<>(); }
-    : op=FUNCTION n_ LPAR  n_ (par_decl[params] (n_ COMMA n_ par_decl[params])* n_)? RPAR n_ body=expr_or_assign { $v = builder.function(src($op, last()), params, builder.handleQueries($body.v), assignedTo); }
+    : op=FUNCTION n_ LPAR  n_ (par_decl[params] (n_ COMMA n_ par_decl[params])* n_)? RPAR n_ body=expr_or_assign { $v = builder.function(language, src($op, last()), params, builder.handleQueries($body.v), assignedTo); }
     ;
 
 par_decl [List<Argument<T>> l]
@@ -673,6 +705,7 @@ ID
     | '.' '.'+ ('0'..'9')* ID_NAME
     | '.'
     | '.' '.'
+    | '.' '.' '.' '.' '.'*
     | '`' BACKTICK_NAME
     ;
 
@@ -754,7 +787,7 @@ fragment OP_NAME
     | ('*'|'/'|'+'|'-'|'>'|'<'|'='|'|'|'&'|':'|'^'|'.'|'~'|','|'?')
     ;
 
-fragment ID_NAME : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'.')* ;
+fragment ID_NAME : ('a'..'z'|'A'..'Z'|'α'..'ω'|'Α'..'Ω'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'α'..'ω'|'Α'..'Ω'|'_'|'.')* ;
 
 fragment ESC_SEQ
     : '\\' ('b'|'t'|'n'|'f'|'r'|'"'|'\''|'`'|'\\'|' '|'a'|'v')
diff --git a/com.oracle.truffle.r.pkgs/graalvm/R/g.R b/com.oracle.truffle.r.pkgs/graalvm/R/g.R
index a39bb05199fd0a4c31a0846d32d718849cca4537..6be25c8445ae89aac701b3d6efc633e5dc4bc18f 100644
--- a/com.oracle.truffle.r.pkgs/graalvm/R/g.R
+++ b/com.oracle.truffle.r.pkgs/graalvm/R/g.R
@@ -337,7 +337,9 @@ sendAttempt <- function(code, echo, mimetype) {
 	
 	if (resp$status_code >= 400) {
 		stop(respObj)
-	} else {
+	} else if (echo) {
 		respObj
+	} else {
+		invisible(NULL)
 	}
 }
diff --git a/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R b/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R
index 2c6c4b66e7195f7e6c09c8bb991b06269e8a5044..74bcf413033c89b656bc37935fc79dfa33e4f80e 100644
--- a/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R
+++ b/com.oracle.truffle.r.pkgs/graalvm/R/graalvm.R
@@ -6,21 +6,20 @@
 #' # Loading and setting up
 #' 
 #' library(graalvm)
-#' graalvm.setup("~/work/graalvm-0.21")
+#' graalvm.setup("~/work/graalvm-0.25")
 #' 
 #' # Code execution
-#' g(v <- runif(1e8))
+#' g(v <- runif(1e3))
 #' g(f <- function(x) { s <- 0; for (i in seq_along(x)) s <- s + x[[i]]; s })
 #' g(system.time(f(v)))
-#' g(system.time(f(v)))
 #' 
 #' g.js("1 < 2")
 #' g.rb("$a = 2")
 #' 
 #' 
-#' # Paired variables
+#' # Coupled variables
 #' 
-#' # Create and initialize paired variables:
+#' # Create and initialize coupled variables:
 #' gset.r(a1, TRUE) 
 #' gset.js(a2, c(1,2))
 #' gset.rb(a3, list(a=1,b="2")) 
@@ -32,17 +31,18 @@
 #' g.rb("$a3")
 #' 
 #' g(a1 <- FALSE)
+#' # Sync the local a1 with the remote a1
 #' gget(a1)
 #' a1
 #' 
-#' # Paired functions
+#' # Coupled functions
 #' 
-#' # Create a paired function
+#' # Create a coupled function
 #' gset.r(measure, function(n) { system.time(runif(n)) })
-#' # Execute the local version of the paired function
+#' # Execute the local version of the coupled function
 #' measure(1e8)
-#' # Execute the remote version of the paired function
-#' g(measure(1e8))
+#' # Execute the remote version of the coupled function
+#' g(measure(1e8)) # Try a couple of times
 #' 
 #' # Executing a script file
 #' 
diff --git a/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr b/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr
index d45d981de98a86d042f881a5e5d44ca06a9572e2..47b07e63afce5c33f8f0bd80747d57e2e66d5057 100644
--- a/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr
+++ b/com.oracle.truffle.r.pkgs/graalvm/data/handler.fr
@@ -38,7 +38,7 @@ result <- function() deparseObject(out)
 
 isError <- function() err
 
-.fastr.interop.export('parser', parser)
-.fastr.interop.export('deparseObject', deparseObject)
-.fastr.interop.export('result', result)
-.fastr.interop.export('isError', isError)
+export('parser', parser)
+export('deparseObject', deparseObject)
+export('result', result)
+export('isError', isError)
diff --git a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd
index 96c0d86c24f63bc09feff2103b15a36d0111a6cb..b37a22e7112cb28b6f85221c38e54abe9433e908 100644
--- a/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd
+++ b/com.oracle.truffle.r.pkgs/graalvm/man/graalvm.Rd
@@ -12,21 +12,20 @@ of GraalVM to GNUR users.
 # Loading and setting up
 
 library(graalvm)
-graalvm.setup("~/work/graalvm-0.21")
+graalvm.setup("~/work/graalvm-0.25")
 
 # Code execution
-g(v <- runif(1e8))
+g(v <- runif(1e3))
 g(f <- function(x) { s <- 0; for (i in seq_along(x)) s <- s + x[[i]]; s })
 g(system.time(f(v)))
-g(system.time(f(v)))
 
 g.js("1 < 2")
 g.rb("$a = 2")
 
 
-# Paired variables
+# Coupled variables
 
-# Create and initialize paired variables:
+# Create and initialize coupled variables:
 gset.r(a1, TRUE) 
 gset.js(a2, c(1,2))
 gset.rb(a3, list(a=1,b="2")) 
@@ -38,17 +37,18 @@ g.js("a2")
 g.rb("$a3")
 
 g(a1 <- FALSE)
+# Sync the local a1 with the remote a1
 gget(a1)
 a1
 
-# Paired functions
+# Coupled functions
 
-# Create a paired function
+# Create a coupled function
 gset.r(measure, function(n) { system.time(runif(n)) })
-# Execute the local version of the paired function
+# Execute the local version of the coupled function
 measure(1e8)
-# Execute the remote version of the paired function
-g(measure(1e8))
+# Execute the remote version of the coupled function
+g(measure(1e8)) # Try a couple of times
 
 # Executing a script file
 
diff --git a/com.oracle.truffle.r.pkgs/rJava/NAMESPACE b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
index 1e1eb30c84f13ea28d8ff269af6bff007c690969..3309c37d9811366c58263450eb3ca1dbb18d2d5e 100644
--- a/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
+++ b/com.oracle.truffle.r.pkgs/rJava/NAMESPACE
@@ -1,6 +1,7 @@
 # Generated by roxygen2: do not edit by hand
 
 export(.jaddClassPath)
+export(.jaddLibrary)
 export(.jarray)
 export(.jbyte)
 export(.jcall)
diff --git a/com.oracle.truffle.r.pkgs/rJava/R/rj.R b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
index 3d3b8a59d271ed2576bceda40d2541cfa2b66490..bef0b2281f1b0ef5101509cda934d8e2917e6452 100644
--- a/com.oracle.truffle.r.pkgs/rJava/R/rj.R
+++ b/com.oracle.truffle.r.pkgs/rJava/R/rj.R
@@ -13,8 +13,8 @@
 .jnew <- function (class, ..., check = TRUE, silent = !check) 
 {
     class <- gsub("/", ".", as.character(class))
-    co <- .fastr.java.class(class)
-    o <- .fastr.interop.new(co, ...)
+    co <- new.java.class(class)
+    o <- new.external(co, ...)
     invisible(o)
 }
 
@@ -25,7 +25,7 @@
 {
     if(is.character(obj)) {
         obj <- gsub("/", ".", as.character(obj))
-        co <- .fastr.java.class(obj)
+        co <- new.java.class(obj)
         r <- co[method](...)
     } else {
         r <- obj[method](...)
@@ -37,7 +37,7 @@
 .jfield <- function (obj, sig = NULL, name, true.class = is.null(sig), convert = TRUE) 
 {
     if(is.character(obj)) {
-        co <- .fastr.java.class(obj)
+        co <- new.java.class(obj)
         r <- co[name]
     } else {
         r <- obj[name]
@@ -48,47 +48,47 @@
 #' @export
 .jarray <- function (x, contents.class = NULL, dispatch = FALSE) 
 {
-    .fastr.java.toArray(x, ,TRUE)
+    as.java.array(x, ,TRUE)
 }
 
 #' @export
 .jevalArray <- function (x, contents.class = NULL, dispatch = FALSE) 
 {
-    .fastr.java.fromArray(x)
+    .fastr.interop.fromArray(x)
 }
 
 #' @export
 .jbyte <- function (x) 
 {
-    x <- .fastr.interop.toByte(x)
+    x <- as.external.byte(x)
     invisible(x)
 }
 
 #' @export
 .jchar <- function (x) 
 {
-    x <- .fastr.interop.toChar(x)
+    x <- as.external.char(x)
     invisible(x)
 }
 
 #' @export
 .jshort <- function (x) 
 {
-    x <- .fastr.interop.toShort(x)
+    x <- as.external.short(x)
     invisible(x)
 }
 
 #' @export
 .jlong <- function (x) 
 {
-    x <- .fastr.interop.toLong(x)
+    x <- as.external.long(x)
     invisible(x)
 }
 
 #' @export
 .jfloat <- function (x) 
 {    
-    x <- .fastr.interop.toFloat(x)
+    x <- as.external.float(x)
     invisible(x)
 }
 
@@ -96,7 +96,7 @@
 J <- function (class, method, ...) 
 {    
     class <- gsub("/", ".", as.character(class))
-    javaClass <- .fastr.java.class(class)
+    javaClass <- new.java.class(class)
     if (nargs() == 1L && missing(method)) {
         javaClass
     } else {
@@ -104,6 +104,51 @@ J <- function (class, method, ...)
     }    
 }
 
+#' @export
+.jpackage <- function (name, jars='*', morePaths='', nativeLibrary=FALSE, lib.loc=NULL)
+{    
+    classes <- system.file("java", package = name, lib.loc = lib.loc)
+    if (nchar(classes)) {
+        .jaddClassPath(classes)
+        if (length(jars)) {
+            if (length(jars) == 1 && jars == "*") {
+                jars <- grep(".*\\.jar", list.files(classes, 
+                  full.names = TRUE), TRUE, value = TRUE)
+                if (length(jars)) 
+                  .jaddClassPath(jars)
+            }
+            else .jaddClassPath(paste(classes, jars, sep = .Platform$file.sep))
+        }
+    }
+    if (any(nchar(morePaths))) {
+        cl <- as.character(morePaths)
+        cl <- cl[nchar(cl) > 0]
+        .jaddClassPath(cl)
+    }
+    if (is.logical(nativeLibrary)) {
+        if (nativeLibrary) {
+            libs <- "libs"
+            if (nchar(.Platform$r_arch)) 
+                lib <- file.path("libs", .Platform$r_arch)
+            lib <- system.file(libs, paste(name, .Platform$dynlib.ext, 
+                sep = ""), package = name, lib.loc = lib.loc)
+            if (nchar(lib)) 
+                .jaddLibrary(name, lib)
+            else warning("Native library for `", name, "' could not be found.")
+        }
+    }
+    else {
+        .jaddLibrary(name, nativeLibrary)
+    }
+    invisible(TRUE)
+}
+
+#' @export
+.jaddClassPath <- function (path)
+{
+    java.addToClasspath(path)
+}
+
 #
 # noop stubs
 #
@@ -132,29 +177,13 @@ J <- function (class, method, ...)
 }
 
 #' @export
-.jpackage <- function (name, jars='*', morePaths='', nativeLibrary=FALSE, lib.loc=NULL)
-{    
-    javalibs <- system.file("java", package = name, lib.loc = lib.loc)
-    if(javalibs == "") {
-        javalibs = paste0("library/", name, "/java")
-    }
-    cat(paste0("********************************************************\n",
-               "*** WARNING!!!\n",
-               "*** .jpackage is not yet implemented.\n",
-               "*** Please ensure that all java libraries from:\n",
-               "*** ", javalibs, "\n",
-               "*** are on FastR classpath\n",
-               "********************************************************\n"))
-}
-
-#' @export
-.jaddClassPath <- function (path)
+.jaddLibrary <- function (name, path) 
 {
     cat(paste0("********************************************************\n",
-               "*** WARNING!!!\n",
-               "*** .jaddClasPath is not yet implemented.\n",
-               "*** Please ensure that \n",
-               "*** ", path, "\n",
-               "*** is on FastR classpath\n",
-               "********************************************************\n"))
+           "*** WARNING!!!\n",
+           "*** .jaddLibrary is not yet implemented.\n",
+           "*** Please ensure that all native libraries from:\n",
+           "*** ", path, "\n",
+           "*** are set on LD_LIBRARY_PATH or java.library.path\n",
+           "********************************************************\n"))
 }
\ 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
index d0581b43c8330e550bca70c78820096bfb5ad1ff..07b9f0e184d9ff5b7d016b40328ff141bb189bc2 100644
--- a/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R
+++ b/com.oracle.truffle.r.pkgs/rJava/tests/testthat/testArrays.R
@@ -11,27 +11,27 @@ test_that(testName, {
     cat(paste0(testName, "\n"))
 	
     a <- .jarray(c(1.1, 2.1, 3.1))
-    expect_true(.fastr.java.isArray(a))
+    expect_true(is.external.array(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_true(is.external.array(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_true(is.external.array(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_true(is.external.array(a))
     expect_equal(length(a), 5)
     expect_equal(a[1], 1)
     expect_equal(a[2], "a")
@@ -41,21 +41,20 @@ test_that(testName, {
 
     to <- .jnew('java.util.ArrayList')
     a <- .jarray(to)
-    expect_true(.fastr.java.isArray(a))
+    expect_true(is.external.array(a))
     expect_equal(length(a), 1)
-    # fails at the moment
-    # expect_equal(a[1], to)
+    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)
+    expect_true(is.external.array(a))
     # fails at the moment    
+    # expect_equal(length(a), 2)
     # expect_equal(a[1], to)
     # expect_equal(a[2], to)
 
     a <- .jarray(list(1, 2, 3))
-    expect_true(.fastr.java.isArray(a))
+    expect_true(is.external.array(a))
     expect_equal(length(a), 3)
     expect_equal(a[1], 1)
     expect_equal(a[2], 2)
@@ -72,7 +71,7 @@ test_that(testName, {
         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), 
+        Integer=list("integer",1,2,3), 
         Long=list("double", 1,2,3), 
         Short=list("integer",1,2,3), 
         String=list("character", "a", "b", "c"))
@@ -85,7 +84,7 @@ test_that(testName, {
         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")
+        expect_true(is.external.array(a), info=paste0("the array was returned for ", fieldName), label="is.external.array")
         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")
diff --git a/com.oracle.truffle.r.release/src/R_launcher b/com.oracle.truffle.r.release/src/R_launcher
index d72f738599c9164737c3bd8dbbbcaa0c74320847..4e9262f84d7dadf274ad763083e713807f4a56ce 100644
--- a/com.oracle.truffle.r.release/src/R_launcher
+++ b/com.oracle.truffle.r.release/src/R_launcher
@@ -12,4 +12,4 @@ do
   esac
 done
 
-exec java "${JAVA_ARGS[@]}" -cp %%CLASSPATH com.oracle.truffle.r.engine.shell.RCommand "${PROGRAM_ARGS[@]}"
+exec java "${JAVA_ARGS[@]}" -cp %%CLASSPATH com.oracle.truffle.r.launchers.RCommand "${PROGRAM_ARGS[@]}"
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java
deleted file mode 100644
index 0ec293f8b14f4418dada70b7b8d28912b033fb39..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jni/JNI_RFFIFactory.java
+++ /dev/null
@@ -1,230 +0,0 @@
-/*
- * 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
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.ffi.jni;
-
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.ContextState;
-import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
-import com.oracle.truffle.r.runtime.ffi.CRFFI;
-import com.oracle.truffle.r.runtime.ffi.CallRFFI;
-import com.oracle.truffle.r.runtime.ffi.DLL;
-import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
-import com.oracle.truffle.r.runtime.ffi.LibPaths;
-import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
-import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
-import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
-import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
-import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
-import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
-import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
-import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
-import com.oracle.truffle.r.runtime.ffi.generic.Generic_Tools;
-
-/**
- * JNI-based factory. The majority of the FFI instances are instantiated on demand.
- */
-public class JNI_RFFIFactory extends RFFIFactory implements RFFI {
-
-    public JNI_RFFIFactory() {
-    }
-
-    private static class ContextStateImpl implements RContext.ContextState {
-        @Override
-        /**
-         * For the initial context, load the {@code libR} library. N.B. this library defines some
-         * non-JNI global symbols that are referenced by C code in R packages. Unfortunately,
-         * {@link System#load(String)} uses {@code RTLD_LOCAL} with {@code dlopen}, so we have to
-         * load the library manually and set {@code RTLD_GLOBAL}. However, a {@code dlopen} does not
-         * hook the JNI functions into the JVM, so we have to do an additional {@code System.load}
-         * to achieve that.
-         *
-         * Before we do that we must load {@code libjniboot} because the implementation of
-         * {@link DLLRFFI.DLLRFFINode#dlopen} is called by {@link DLL#loadLibR} which uses JNI!
-         */
-        public ContextState initialize(RContext context) {
-            if (context.isInitial()) {
-                String libjnibootPath = LibPaths.getBuiltinLibPath("jniboot");
-                System.load(libjnibootPath);
-
-                String librffiPath = LibPaths.getBuiltinLibPath("R");
-                DLL.loadLibR(librffiPath);
-                System.load(librffiPath);
-            }
-            return this;
-        }
-    }
-
-    @Override
-    public ContextState newContextState() {
-        return new ContextStateImpl();
-    }
-
-    @Override
-    protected RFFI createRFFI() {
-        return this;
-    }
-
-    @CompilationFinal private BaseRFFI baseRFFI;
-
-    @Override
-    public BaseRFFI getBaseRFFI() {
-        if (baseRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            baseRFFI = new JNI_Base();
-        }
-        return baseRFFI;
-    }
-
-    @CompilationFinal private LapackRFFI lapackRFFI;
-
-    @Override
-    public LapackRFFI getLapackRFFI() {
-        if (lapackRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            lapackRFFI = new JNI_Lapack();
-        }
-        return lapackRFFI;
-    }
-
-    @CompilationFinal private RApplRFFI rApplRFFI;
-
-    @Override
-    public RApplRFFI getRApplRFFI() {
-        if (rApplRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            rApplRFFI = new JNI_RAppl();
-        }
-        return rApplRFFI;
-    }
-
-    @CompilationFinal private StatsRFFI statsRFFI;
-
-    @Override
-    public StatsRFFI getStatsRFFI() {
-        if (statsRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            statsRFFI = new JNI_Stats();
-        }
-        return statsRFFI;
-    }
-
-    @CompilationFinal private ToolsRFFI toolsRFFI;
-
-    @Override
-    public ToolsRFFI getToolsRFFI() {
-        if (toolsRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            toolsRFFI = new Generic_Tools();
-        }
-        return toolsRFFI;
-    }
-
-    @CompilationFinal private UserRngRFFI userRngRFFI;
-
-    @Override
-    public UserRngRFFI getUserRngRFFI() {
-        if (userRngRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            userRngRFFI = new JNI_UserRng();
-        }
-        return userRngRFFI;
-    }
-
-    @CompilationFinal private CRFFI cRFFI;
-
-    @Override
-    public CRFFI getCRFFI() {
-        if (cRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            cRFFI = new JNI_C();
-        }
-        return cRFFI;
-    }
-
-    @CompilationFinal private CallRFFI callRFFI;
-
-    @Override
-    public CallRFFI getCallRFFI() {
-        if (callRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            callRFFI = new JNI_Call();
-        }
-        return callRFFI;
-    }
-
-    @CompilationFinal private ZipRFFI zipRFFI;
-
-    @Override
-    public ZipRFFI getZipRFFI() {
-        if (zipRFFI == null) {
-            CompilerDirectives.transferToInterpreterAndInvalidate();
-            zipRFFI = new JNI_Zip();
-        }
-        return zipRFFI;
-    }
-
-    @CompilationFinal private PCRERFFI pcreRFFI;
-
-    @Override
-    public PCRERFFI getPCRERFFI() {
-        if (pcreRFFI == null) {
-            pcreRFFI = new JNI_PCRE();
-        }
-        return pcreRFFI;
-    }
-
-    private DLLRFFI dllRFFI;
-
-    @Override
-    public DLLRFFI getDLLRFFI() {
-        if (dllRFFI == null) {
-            dllRFFI = new JNI_DLL();
-        }
-        return dllRFFI;
-    }
-
-    private REmbedRFFI rEmbedRFFI;
-
-    @Override
-    public REmbedRFFI getREmbedRFFI() {
-        if (rEmbedRFFI == null) {
-            rEmbedRFFI = new JNI_REmbed();
-        }
-        return rEmbedRFFI;
-    }
-
-    private MiscRFFI miscRFFI;
-
-    @Override
-    public MiscRFFI getMiscRFFI() {
-        if (miscRFFI == null) {
-            miscRFFI = new JNI_Misc();
-        }
-        return miscRFFI;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/truffle/MachOAccess.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/truffle/MachOAccess.java
deleted file mode 100644
index cbc7fe7691ba9f45936619c40e2668ec98feb516..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/truffle/MachOAccess.java
+++ /dev/null
@@ -1,449 +0,0 @@
-/*
- * 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.runtime.ffi.truffle;
-
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.ArrayList;
-
-import com.oracle.truffle.r.runtime.RInternalError;
-
-/**
- * (Limited) Access to Mach_O 64-bit format files. See /usr/include/mach-o/*.h for source. Note that
- * a file may (unusually) contain multiple binaries for different architectures, see
- * /usr/include/mach-o/fat.h. Such a file is called a universal binary file, (cf an archive file).
- *
- */
-@SuppressWarnings("unused")
-final class MachOAccess implements AutoCloseable {
-    private final RandomAccessFile raf;
-    private final Header header;
-    private final LoadCommand[] loadCommands;
-
-    private MachOAccess(RandomAccessFile raf) throws IOException {
-        this.raf = raf;
-        this.header = new Header();
-        this.loadCommands = getLoadCommands();
-    }
-
-    static LLVM_IR[] getLLVMIR(String path) throws IOException {
-        try (MachOAccess ma = new MachOAccess(new RandomAccessFile(path, "r"))) {
-            return ma.getLLVMIR();
-        }
-    }
-
-    /**
-     * Return an array of {@link LLVM_IR} instances corresponding to the "modules" in the library,
-     * or {@code null} of there none.
-     */
-    private LLVM_IR[] getLLVMIR() throws IOException {
-        SymTabLoadCommand symtab = null;
-        for (LoadCommand lc : loadCommands) {
-            if (lc.cmd == LC_TYPE.LC_SYMTAB) {
-                symtab = (SymTabLoadCommand) lc;
-                break;
-            }
-        }
-        assert symtab != null;
-        ArrayList<LLVM_IR> list = new ArrayList<>();
-        NList64[] syms = symtab.getSymbolTable();
-        for (NList64 sym : syms) {
-            String name = symtab.getSymbolName(sym);
-            if (name.startsWith("__llvm_")) {
-                String module = name.substring(7);
-                getSection(loadCommands, sym.sect);
-                raf.seek(sym.value);
-                int type = raf.read();
-                int len = readInt();
-                byte[] buf = new byte[len];
-                // exported symbols
-                String[] exports = readXXPorts();
-                // imported symbols
-                String[] imports = readXXPorts();
-                raf.read(buf);
-                LLVM_IR ir;
-                if (type == LLVM_IR.TEXT_CODE) {
-                    ir = new LLVM_IR.Text(module, new String(buf), exports, imports);
-                } else if (type == LLVM_IR.BINARY_CODE) {
-                    ir = new LLVM_IR.Binary(module, buf, exports, imports);
-                } else {
-                    throw RInternalError.shouldNotReachHere();
-                }
-                list.add(ir);
-            }
-        }
-        if (list.size() == 0) {
-            return null;
-        } else {
-            LLVM_IR[] result = new LLVM_IR[list.size()];
-            list.toArray(result);
-            return result;
-        }
-    }
-
-    String[] readXXPorts() throws IOException {
-        int numxxports = readInt();
-        String[] xxports = new String[numxxports];
-        for (int i = 0; i < numxxports; i++) {
-            int xxportLen = raf.read();
-            byte[] xxportBuf = new byte[xxportLen];
-            for (int j = 0; j < xxportLen; j++) {
-                xxportBuf[j] = (byte) raf.read();
-            }
-            xxports[i] = new String(xxportBuf);
-        }
-        return xxports;
-    }
-
-    @Override
-    public void close() throws IOException {
-        raf.close();
-    }
-
-    private final class Header implements Cloneable {
-        private static final int FAT_MAGIC = 0xcafebabe;
-        private final int magic;
-        private final int cputype;
-        private final int cpusubtype;
-        private final int filetype;
-        private final int ncmds;
-        private final int sizeofcmds;
-        private final int flags;
-        private final int reserved;
-
-        private Header() throws IOException {
-            this.magic = raf.readInt();
-            assert magic != FAT_MAGIC;
-            cputype = readInt();
-            cpusubtype = readInt();
-            filetype = readInt();
-            ncmds = readInt();
-            sizeofcmds = readInt();
-            flags = readInt();
-            reserved = readInt();
-        }
-    }
-
-    private enum LC_TYPE {
-        LC_SYMTAB(0x2),
-        LC_THREAD(0x4),
-        LC_DYSYMTAB(0xb),
-        LC_LOAD_DYLIB(0xc),
-        LC_ID_DYLIB(0xd),
-        LC_SUB_FRAMEWORK(0x12),
-        LC_SEGMENT_64(0x19),
-        LC_UUID(0x1b),
-        LC_RPATH(0x1C),
-        LC_DYLD_INFO(0x22),
-        LC_VERSION_MIN_MACOSX(0x24),
-        LC_FUNCTION_STARTS(0x26),
-        LC_DATA_IN_CODE(0x29),
-        LC_SOURCE_VERSION(0x2A),
-        LC_USER(0x32);
-
-        private int code;
-
-        LC_TYPE(int code) {
-            this.code = code;
-        }
-
-        static int getCode(int codeIn) {
-            return codeIn & ~LoadCommand.LC_REQ_DYLD;
-        }
-
-        static LC_TYPE getType(int code) {
-            for (LC_TYPE lct : LC_TYPE.values()) {
-                if (code == lct.code) {
-                    return lct;
-                }
-            }
-            assert false : "unknown load cmd: " + code;
-            return null;
-        }
-    }
-
-    /**
-     * Common base class for all Mach-O load command types.
-     */
-    private class LoadCommand {
-        private static final int LC_REQ_DYLD = 0x80000000;
-
-        private long cmdFileOffset;
-        private final int code;
-        private final LC_TYPE cmd;
-        private final int cmdsize;
-
-        protected LoadCommand(int index) throws IOException {
-            cmdFileOffset = raf.getFilePointer();
-            this.code = readInt();
-            this.cmd = LC_TYPE.getType(LC_TYPE.getCode(this.code));
-            this.cmdsize = readInt();
-        }
-
-        protected LoadCommand(int index, LC_TYPE cmd, int cmdsize) {
-            this.cmd = cmd;
-            this.code = cmd.code;
-            this.cmdsize = cmdsize;
-        }
-
-        private String typeName() {
-            return cmd.name();
-        }
-    }
-
-    /**
-     * Reads a load command structure starting at the current file position, invoking the
-     * appropriate subclass {@code read} command, based on the {@code cmd} field. Leaves the file
-     * pointer at the next load command (if any).
-     *
-     * @return instance of the appropriate subclass for discovered command type
-     * @throws IOException
-     */
-    private LoadCommand readNextLoadCommand(int index) throws IOException {
-        LoadCommand result = null;
-        final long ptr = raf.getFilePointer();
-        final LC_TYPE cmd = LC_TYPE.getType(LC_TYPE.getCode(readInt()));
-        final int cmdsize = readInt();
-        /* The LoadCommand class reads the two prior fields again. */
-        raf.seek(ptr);
-        switch (cmd) {
-            case LC_SEGMENT_64:
-                result = new Segment64LoadCommand(index);
-                break;
-            case LC_SYMTAB:
-                result = new SymTabLoadCommand(index);
-                break;
-            default:
-                result = new LoadCommand(index);
-                break;
-        }
-        // skip over entire command
-        raf.seek(ptr + cmdsize);
-        return result;
-    }
-
-    private LoadCommand[] getLoadCommands() throws IOException {
-        LoadCommand[] result = new LoadCommand[header.ncmds];
-        for (int i = 0; i < header.ncmds; i++) {
-            result[i] = readNextLoadCommand(i);
-        }
-        return result;
-    }
-
-    private final class Segment64LoadCommand extends LoadCommand {
-        private final String segName;
-        private final long vmaddr;
-        private final long vmsize;
-        private final long fileoff;
-        private final long filesize;
-        private final int maxprot;
-        private final int initprot;
-        private final int nsects;
-        private final int flags;
-        private final Section64[] sections;
-
-        private Segment64LoadCommand(int index) throws IOException {
-            super(index);
-            final byte[] segname = new byte[16];
-            for (int i = 0; i < 16; i++) {
-                segname[i] = raf.readByte();
-            }
-            segName = new String(segname);
-            vmaddr = readLong();
-            vmsize = readLong();
-            fileoff = readLong();
-            filesize = readLong();
-            maxprot = readInt();
-            initprot = readInt();
-            nsects = readInt();
-            flags = readInt();
-            sections = new Section64[nsects];
-            for (int i = 0; i < nsects; i++) {
-                sections[i] = new Section64(this);
-            }
-        }
-    }
-
-    private final class Section64 {
-        private final String sectname;
-        private final String segname;
-        private final long addr;
-        private final long size;
-        private final int offset;
-        private final int align;
-        private final int reloff;
-        private final int nreloc;
-        private final int flags;
-        private final int reserved1;
-        private final int reserved2;
-        private final int reserved3;
-
-        private Section64(Segment64LoadCommand segment64) throws IOException {
-            sectname = readName();
-            segname = readName();
-            addr = readLong();
-            size = readLong();
-            offset = readInt();
-            align = readInt();
-            reloff = readInt();
-            nreloc = readInt();
-            flags = readInt();
-            reserved1 = readInt();
-            reserved2 = readInt();
-            reserved3 = readInt();
-        }
-
-        private String readName() throws IOException {
-            byte[] nameBytes = new byte[16];
-            int length = 0;
-            for (int i = 0; i < nameBytes.length; i++) {
-                nameBytes[i] = raf.readByte();
-                if (nameBytes[i] != 0) {
-                    length++;
-                }
-            }
-            return new String(nameBytes, 0, length);
-        }
-
-        private boolean isText() {
-            return segname.equals("__TEXT");
-        }
-    }
-
-    private class SymTabLoadCommand extends LoadCommand {
-        private final int symoff;
-        private final int nsyms;
-        private final int stroff;
-        private final int strsize;
-        /**
-         * Lazily created string table.
-         */
-        private byte[] stringTable;
-        /**
-         * Lazily created symbol table.
-         */
-        private NList64[] symbolTable;
-
-        SymTabLoadCommand(int index) throws IOException {
-            super(index);
-            symoff = readInt();
-            nsyms = readInt();
-            stroff = readInt();
-            strsize = readInt();
-        }
-
-        private NList64[] getSymbolTable() throws IOException {
-            if (symbolTable != null) {
-                return symbolTable;
-            }
-            stringTable = new byte[strsize];
-            raf.seek(stroff);
-            for (int i = 0; i < strsize; i++) {
-                stringTable[i] = raf.readByte();
-            }
-            symbolTable = new NList64[nsyms];
-            raf.seek(symoff);
-            for (int i = 0; i < nsyms; i++) {
-                symbolTable[i] = new NList64();
-            }
-            return symbolTable;
-        }
-
-        private String getSymbolName(NList64 nlist64) {
-            String symbol = "";
-            if (nlist64.strx != 0) {
-                byte sb = stringTable[nlist64.strx];
-                int sl = 0;
-                while (sb != 0) {
-                    sb = stringTable[nlist64.strx + sl];
-                    sl++;
-                }
-                if (sl > 0) {
-                    symbol = new String(stringTable, nlist64.strx, sl - 1);
-                }
-            }
-            return symbol;
-        }
-    }
-
-    private class NList64 {
-        private final int strx;
-        private final byte type;
-        private final byte sect;
-        private final short desc;
-        private final long value;
-
-        NList64() throws IOException {
-            strx = readInt();
-            type = raf.readByte();
-            sect = raf.readByte();
-            desc = readShort();
-            value = readLong();
-        }
-
-        void print() {
-
-        }
-    }
-
-    /**
-     * Locates a given section within a given array of load commands. Sections are numbered from 1
-     * as they occur within SEGMENT_64 commands.
-     *
-     * @param loadCommands
-     * @param sectToFind
-     */
-    private static Section64 getSection(LoadCommand[] loadCommands, int sectToFind) {
-        int sect = 1;
-        for (int i = 0; i < loadCommands.length; i++) {
-            if (loadCommands[i].cmd == LC_TYPE.LC_SEGMENT_64) {
-                Segment64LoadCommand slc = (Segment64LoadCommand) loadCommands[i];
-                if (sectToFind < sect + slc.nsects) {
-                    return slc.sections[sectToFind - sect];
-                }
-                sect += slc.nsects;
-            }
-        }
-        return null;
-    }
-
-    private short readShort() throws IOException {
-        final int b1 = raf.read();
-        final int b2 = raf.read();
-        return (short) (((b2 << 8) | b1) & 0xFFFF);
-    }
-
-    private int readInt() throws IOException {
-        final int b1 = raf.read();
-        final int b2 = raf.read();
-        final int b3 = raf.read();
-        final int b4 = raf.read();
-        return (b4 << 24) | (b3 << 16) | (b2 << 8) | b1;
-    }
-
-    private long readLong() throws IOException {
-        final long lw = readInt();
-        final long hw = readInt();
-        return hw << 32 | (lw & 0xFFFFFFFFL);
-    }
-}
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 ac69a5a14fd5a4ec37a529811733dbe1df51a437..ae22e9d513dfb264e7b2d91fd4d0bbdf6d7afa11 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
@@ -94,17 +94,17 @@ public final class ArgumentsSignature implements Iterable<String> {
 
     private ArgumentsSignature(String[] names, boolean convertEmpty) {
         this.names = new String[names.length];
-        int nonNullCount = 0;
+        int nonNull = 0;
         for (int i = 0; i < names.length; i++) {
             String s = names[i];
             if (s == null || (s.isEmpty() && convertEmpty)) {
                 this.names[i] = null;
                 continue;
             }
-            nonNullCount++;
+            nonNull++;
             this.names[i] = s == UNMATCHED ? s : s.intern();
         }
-        this.nonNullCount = nonNullCount;
+        this.nonNullCount = nonNull;
 
         int index = NO_VARARG;
         int count = 0;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
index ba1179865854fc64615758ca3396de614f36df9a..87bd008ed805cd982c6c1e19de87ea8f9bc4398b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ExitException.java
@@ -22,20 +22,44 @@
  */
 package com.oracle.truffle.r.runtime;
 
+import com.oracle.truffle.api.TruffleException;
+import com.oracle.truffle.api.nodes.Node;
+
 /**
  * This exception is thrown when a Polyglot R engine wants to exit, usually via the {@code quit}
  * builtin. It allows systems using multiple contexts via {@code .fastr.context.op} to handle exits
  * gracefully.
  */
-public class ExitException extends RuntimeException {
+public class ExitException extends RuntimeException implements TruffleException {
     private static final long serialVersionUID = 1L;
     private final int status;
+    private final boolean saveHistory;
 
-    public ExitException(int status) {
+    public ExitException(int status, boolean saveHistory) {
         this.status = status;
+        this.saveHistory = saveHistory;
     }
 
     public int getStatus() {
         return status;
     }
+
+    @Override
+    public Node getLocation() {
+        return null;
+    }
+
+    @Override
+    public boolean isExit() {
+        return true;
+    }
+
+    @Override
+    public int getExitStatus() {
+        return status;
+    }
+
+    public boolean saveHistory() {
+        return saveHistory;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
index 8d6bbf8f1bf32640ec626bed909b96e80c31e37f..96161a3d6afe2fee3012cd7eca8c4adc15a1d863 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastRConfig.java
@@ -31,13 +31,13 @@ public final class FastRConfig {
     /**
      * Umbrella option, which changes default values of other options in a way that FastR will not
      * invoke any native code directly and other potentially security sensitive operations are
-     * restricted. Can be configured via environment variable {@code FASTR_MANAGED}.
+     * restricted. Can be configured via environment variable {@code FASTR_RFFI=managed}.
      */
     public static final boolean ManagedMode;
 
     static {
-        String managedModeVal = System.getenv("FASTR_MANAGED");
-        ManagedMode = managedModeVal != null && managedModeVal.equals("true");
+        String rffiVal = System.getenv("FASTR_RFFI");
+        ManagedMode = rffiVal != null && rffiVal.equals("managed");
         if (ManagedMode) {
             InternalGridAwtSupport = false;
         } else {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
index ad7e272e9177f545a3da27dbd88495501d6d1751..982d68f8efb80f69c549df0d455d1b7be7985137 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java
@@ -60,6 +60,7 @@ public enum FastROptions {
     EmitTmpSource("Write deparsed source code to temporary files for better debugging.", true),
     EmitTmpDir("The directory where to allocate temporary files with deparsed source code.", null, true),
     EmitTmpHashed("Use an SHA-256 hash as file name to reduce temporary file creation.", true),
+    SpawnUsesPolyglot("use PolyglotEngine for .fastr.context.spwan", false),
 
     // Promises optimizations
     EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false),
@@ -67,7 +68,11 @@ public enum FastROptions {
     EagerEvalVariables("Enables optimistic eager evaluation of single variables reads", true),
     EagerEvalDefault("Enables optimistic eager evaluation of single variables reads (for default parameters)", false),
     EagerEvalExpressions("Enables optimistic eager evaluation of trivial expressions", false),
-    PromiseCacheSize("Enables inline caches for promises evaluation", "3", true);
+    PromiseCacheSize("Enables inline caches for promises evaluation", "3", true),
+
+    // Miscellaneous
+
+    StartupTiming("Records and prints various timestamps during initialization", false);
 
     private final String help;
     private final boolean isBoolean;
@@ -138,7 +143,7 @@ public enum FastROptions {
 
     private static FastROptions[] VALUES = values();
 
-    static void setValue(String name, Object value) {
+    public static void setValue(String name, Object value) {
         for (FastROptions option : VALUES) {
             if (name.equals(option.name())) {
                 option.value = value;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java
index c4931e0d04634ebcd72c8b4edbe426fe06f12770..8a4d0411ca3e27e61f7f1f3e537f332a81d0fa3f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyResourceHandlerFactory.java
@@ -35,8 +35,9 @@ import java.security.CodeSource;
 import java.security.Permissions;
 import java.security.ProtectionDomain;
 import java.security.cert.Certificate;
-import java.util.ArrayList;
 import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 import com.oracle.truffle.r.runtime.ResourceHandlerFactory.Handler;
@@ -74,9 +75,9 @@ class LazyResourceHandlerFactory extends ResourceHandlerFactory implements Handl
     }
 
     @Override
-    public String[] getRFiles(Class<?> accessor, String pkgName) {
+    public Map<String, String> getRFiles(Class<?> accessor, String pkgName) {
         CodeSource source = getHack().getCodeSource();
-        ArrayList<String> list = new ArrayList<>();
+        Map<String, String> result = new HashMap<>();
         try {
             URL url = source.getLocation();
             Path sourcePath = Paths.get(url.toURI().getPath());
@@ -89,7 +90,7 @@ class LazyResourceHandlerFactory extends ResourceHandlerFactory implements Handl
                         while ((line = r.readLine()) != null) {
                             if (line.endsWith(".r") || line.endsWith(".R")) {
                                 final String rResource = pkgName + "/R/" + line.trim();
-                                list.add(Utils.getResourceAsString(accessor, rResource, true));
+                                result.put(sourcePath.toString(), Utils.getResourceAsString(accessor, rResource, true));
                             }
                         }
                     }
@@ -113,13 +114,11 @@ class LazyResourceHandlerFactory extends ResourceHandlerFactory implements Handl
                             while ((n = is.read(buf, totalRead, buf.length - totalRead)) > 0) {
                                 totalRead += n;
                             }
-                            list.add(new String(buf));
+                            result.put(p.toString(), new String(buf));
                         }
                     }
                 }
             }
-            String[] result = new String[list.size()];
-            list.toArray(result);
             return result;
         } catch (Exception ex) {
             Utils.rSuicide(ex.getMessage());
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java
index 6771af91b7f7403faed55595e3efe24138cdbb9f..646850b0d719b8394561ccbe10b773bab4f374b1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCaller.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
@@ -35,6 +35,13 @@ public final class RCaller {
 
     public static final RCaller topLevel = RCaller.createInvalid(null);
 
+    /**
+     * Determines the actual position of the corresponding frame on the execution call stack. When
+     * one follows the {@link RCaller#parent} chain, then the depth is not always decreasing by only
+     * one, the reason are promises, which may be evaluated somewhere deep down the call stack, but
+     * their parent call frame from R prespective could be much higher up the actual execution call
+     * stack.
+     */
     private final int depth;
     private boolean visibility;
     private final RCaller parent;
@@ -43,11 +50,20 @@ public final class RCaller {
      * promise evaluation frames).
      */
     private final Object payload;
+    /**
+     * Marks those callers whose parent should not be taken into account when iterating R level
+     * frames using e.g. {@code parent.frame()}. This is the case for function invoked through
+     * {@code do.call} -- R pretends that they were called by the caller of {@code do.call} so that
+     * code like {@code eval(formula, parent.frame(2))} gives the same results regardless of whether
+     * the function was invoked directly or through {@code do.call}.
+     */
+    private final boolean parentIsInternal;
 
-    private RCaller(Frame callingFrame, Object nodeOrSupplier) {
+    private RCaller(Frame callingFrame, Object nodeOrSupplier, boolean parentIsInternal) {
         this.depth = depthFromFrame(callingFrame);
         this.parent = parentFromFrame(callingFrame);
         this.payload = nodeOrSupplier;
+        this.parentIsInternal = parentIsInternal;
     }
 
     private static int depthFromFrame(Frame callingFrame) {
@@ -58,10 +74,15 @@ public final class RCaller {
         return callingFrame == null ? null : RArguments.getCall(callingFrame);
     }
 
-    private RCaller(int depth, RCaller parent, Object nodeOrSupplier) {
+    private RCaller(int depth, RCaller parent, Object nodeOrSupplier, boolean parentIsInternal) {
         this.depth = depth;
         this.parent = parent;
         this.payload = nodeOrSupplier;
+        this.parentIsInternal = parentIsInternal;
+    }
+
+    public RCaller withInternalParent() {
+        return new RCaller(depth, parent, payload, true);
     }
 
     public int getDepth() {
@@ -72,6 +93,10 @@ public final class RCaller {
         return parent;
     }
 
+    public boolean hasInternalParent() {
+        return parentIsInternal;
+    }
+
     public RSyntaxElement getSyntaxNode() {
         assert payload != null && !(payload instanceof RCaller) : payload == null ? "null RCaller" : "promise RCaller";
         return payload instanceof RSyntaxElement ? (RSyntaxElement) payload : (RSyntaxElement) ((Supplier<?>) payload).get();
@@ -90,37 +115,42 @@ public final class RCaller {
     }
 
     public static RCaller createInvalid(Frame callingFrame) {
-        return new RCaller(callingFrame, null);
+        return new RCaller(callingFrame, null, false);
     }
 
     public static RCaller createInvalid(Frame callingFrame, RCaller parent) {
-        return new RCaller(depthFromFrame(callingFrame), parent, null);
+        return new RCaller(depthFromFrame(callingFrame), parent, null, false);
     }
 
     public static RCaller create(Frame callingFrame, RSyntaxElement node) {
         assert node != null;
-        return new RCaller(callingFrame, node);
+        return new RCaller(callingFrame, node, false);
     }
 
     public static RCaller create(Frame callingFrame, RCaller parent, RSyntaxElement node) {
         assert node != null;
-        return new RCaller(depthFromFrame(callingFrame), parent, node);
+        return new RCaller(depthFromFrame(callingFrame), parent, node, false);
+    }
+
+    public static RCaller createWithInternalParent(Frame callingFrame, Supplier<RSyntaxElement> supplier) {
+        assert supplier != null;
+        return new RCaller(callingFrame, supplier, true);
     }
 
     public static RCaller create(Frame callingFrame, Supplier<RSyntaxElement> supplier) {
         assert supplier != null;
-        return new RCaller(callingFrame, supplier);
+        return new RCaller(callingFrame, supplier, false);
     }
 
     public static RCaller create(Frame callingFrame, RCaller parent, Supplier<RSyntaxElement> supplier) {
         assert supplier != null;
-        return new RCaller(depthFromFrame(callingFrame), parent, supplier);
+        return new RCaller(depthFromFrame(callingFrame), parent, supplier, false);
     }
 
     public static RCaller createForPromise(RCaller originalCaller, Frame frame) {
         int newDepth = frame == null ? 0 : RArguments.getDepth(frame);
         RCaller originalCall = frame == null ? null : RArguments.getCall(frame);
-        return new RCaller(newDepth, originalCaller, originalCall);
+        return new RCaller(newDepth, originalCaller, originalCall, false);
     }
 
     public boolean getVisibility() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
index 436e252e5d8d79ff47af6ab934fa9aeffa0e6275..d33648e88f25646b17a93d579f973f4e91c46b12 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java
@@ -13,10 +13,11 @@ package com.oracle.truffle.r.runtime;
 
 import java.util.ArrayList;
 
-import com.oracle.truffle.r.runtime.RStartParams.SA_TYPE;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
+import com.oracle.truffle.r.runtime.gnur.SA_TYPE;
 import com.oracle.truffle.r.runtime.instrument.InstrumentationState;
 
 public class RCleanUp {
@@ -29,48 +30,45 @@ public class RCleanUp {
 
     public static void cleanUp(SA_TYPE saveType, int status, boolean runLast) {
         if (RInterfaceCallbacks.R_CleanUp.isOverridden()) {
-            RFFIFactory.getRFFI().getREmbedRFFI().cleanUp(saveType.ordinal(), status, runLast ? 1 : 0);
+            RFFIFactory.getREmbedRFFI().cleanUp(saveType.ordinal(), status, runLast ? 1 : 0);
         } else {
             stdCleanUp(saveType, status, runLast);
         }
     }
 
-    public static void stdCleanUp(final SA_TYPE saveActionIn, int status, boolean runLast) {
+    public static void stdCleanUp(SA_TYPE saveActionIn, int status, boolean runLast) {
         // Output is not diverted to sink
-        ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
+        ConsoleIO console = RContext.getInstance().getConsole();
         SA_TYPE saveAction = saveActionIn;
-        if (saveAction == SA_TYPE.DEFAULT) {
-            saveAction = RContext.getInstance().getStartParams().getSaveAction();
+        if (saveAction == SA_TYPE.DEFAULT || (saveAction == SA_TYPE.SAVEASK && !RContext.getInstance().isInteractive())) {
+            RStartParams params = RContext.getInstance().getStartParams();
+            saveAction = params.askForSave() ? SA_TYPE.SAVEASK : params.save() ? SA_TYPE.SAVE : SA_TYPE.NOSAVE;
         }
-        if (saveAction == SA_TYPE.SAVEASK) {
-            if (consoleHandler.isInteractive()) {
-                W: while (true) {
-                    consoleHandler.setPrompt("");
-                    consoleHandler.print("Save workspace image? [y/n/c]: ");
-                    String response = consoleHandler.readLine();
-                    if (response == null) {
+        if (saveAction == SA_TYPE.SAVEASK && RContext.getInstance().isInteractive()) {
+            W: while (true) {
+                console.setPrompt("");
+                console.print("Save workspace image? [y/n/c]: ");
+                String response = console.readLine();
+                if (response == null) {
+                    saveAction = SA_TYPE.NOSAVE;
+                    break;
+                }
+                if (response.length() == 0) {
+                    continue;
+                }
+                switch (response.charAt(0)) {
+                    case 'c':
+                        console.setPrompt("> ");
+                        throw new JumpToTopLevelException();
+                    case 'y':
+                        saveAction = SA_TYPE.SAVE;
+                        break W;
+                    case 'n':
                         saveAction = SA_TYPE.NOSAVE;
-                        break;
-                    }
-                    if (response.length() == 0) {
+                        break W;
+                    default:
                         continue;
-                    }
-                    switch (response.charAt(0)) {
-                        case 'c':
-                            consoleHandler.setPrompt("> ");
-                            throw new JumpToTopLevelException();
-                        case 'y':
-                            saveAction = SA_TYPE.SAVE;
-                            break W;
-                        case 'n':
-                            saveAction = SA_TYPE.NOSAVE;
-                            break W;
-                        default:
-                            continue;
-                    }
                 }
-            } else {
-                saveAction = RContext.getInstance().getStartParams().getSaveAction();
             }
         }
 
@@ -84,18 +82,16 @@ public class RCleanUp {
                  * we save always
                  */
                 RContext.getEngine().checkAndRunStartupShutdownFunction("sys.save.image", new String[]{"\".RData\""});
-                RContext.getInstance().getConsoleHandler().flushHistory();
+                String history = RContext.getInstance().getConsole().getHistory();
+                // TODO: write out history
                 break;
-
             case NOSAVE:
                 if (runLast) {
                     runDotLast();
                 }
                 break;
-
-            case SUICIDE:
             default:
-
+                throw RInternalError.shouldNotReachHere();
         }
         for (InstrumentationState.CleanupHandler cleanupHandler : cleanupHandlers) {
             try {
@@ -105,8 +101,17 @@ public class RCleanUp {
             }
         }
         // TODO run exit finalizers (FFI) (this should happen in the FFI context beforeDestroy)
-        throw new ExitException(status);
 
+        // force sub-context threads to stop
+        for (Thread thread : new ArrayList<>(RContext.getInstance().threads.values())) {
+            thread.interrupt();
+            try {
+                thread.join(10);
+            } catch (InterruptedException e) {
+                // nothing to be done
+            }
+        }
+        throw new ExitException(status, false);
     }
 
     private static void runDotLast() {
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 07974eaba2ae7295385f0589408dfd5600eb1375..b9c6f7c7cc63342abfd2cec77495d9da3cb95749 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
@@ -53,12 +53,14 @@ import com.oracle.truffle.r.runtime.data.RS4Object;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
+import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 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.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
-import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
+import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
@@ -379,26 +381,35 @@ public class RDeparse {
 
         public void fixupSources() {
             if (FastROptions.EmitTmpSource.getBooleanValue()) {
-                try {
-                    RootNode rootNode = getRootNode();
-                    String name = rootNode != null ? rootNode.getName() : null;
-                    Path path = emitToFile(name);
-                    Source source = RSource.fromFile(path.toFile());
-                    for (SourceSectionElement s : sources) {
-                        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);
-                } catch (NoSuchAlgorithmException e) {
-                    throw RInternalError.shouldNotReachHere("SHA-256 is an unknown algorithm");
-                }
+                fixupSourcesTempFile();
             } else {
-                Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE);
+                fixupSourcesTextInternal();
+            }
+        }
+
+        private void fixupSourcesTextInternal() {
+            Source source = RSource.fromTextInternal(sb.toString(), RSource.Internal.DEPARSE);
+            for (SourceSectionElement s : sources) {
+                s.element.setSourceSection(source.createSection(s.start, s.length));
+            }
+        }
+
+        private void fixupSourcesTempFile() {
+            try {
+                RootNode rootNode = getRootNode();
+                String name = rootNode != null ? rootNode.getName() : null;
+                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);
+                fixupSourcesTextInternal();
+            } catch (NoSuchAlgorithmException e) {
+                throw RInternalError.shouldNotReachHere("SHA-256 is an unknown algorithm");
             }
         }
 
@@ -707,7 +718,7 @@ public class RDeparse {
 
         @SuppressWarnings("try")
         private DeparseVisitor appendConstant(Object originalValue) {
-            Object value = RRuntime.asAbstractVector(originalValue);
+            Object value = RRuntime.convertScalarVectors(originalValue);
             if (value instanceof RExpression) {
                 append("expression(").appendListContents((RExpression) value).append(')');
             } else if (value instanceof RAbstractListVector) {
@@ -715,10 +726,10 @@ public class RDeparse {
                 try (C c = withAttributes(obj)) {
                     append("list(").appendListContents(obj).append(')');
                 }
-            } else if (value instanceof RAbstractVector) {
-                RAbstractVector obj = (RAbstractVector) value;
+            } else if (value instanceof RAbstractAtomicVector) {
+                RAbstractVector obj = (RAbstractAtomicVector) value;
                 try (C c = withAttributes(obj)) {
-                    appendVector((RAbstractVector) value);
+                    appendVector((RAbstractAtomicVector) value);
                 }
             } else if (value instanceof RNull) {
                 append("NULL");
@@ -735,7 +746,6 @@ public class RDeparse {
                 }
             } else if (value instanceof RPairList) {
                 RPairList arglist = (RPairList) value;
-                assert arglist.getType() == null || arglist.getType() == SEXPTYPE.LISTSXP : arglist.getType();
                 append("pairlist(");
                 int i = 0;
                 boolean lbreak = false;
@@ -751,7 +761,6 @@ public class RDeparse {
                         }
                     }
                     appendValue(arglist.car());
-
                     arglist = next(arglist);
                 }
                 append(')');
@@ -772,7 +781,12 @@ public class RDeparse {
                 }
                 append(')');
             } else if (value instanceof RExternalPtr) {
-                append("<pointer: 0x").append(Long.toHexString(((RExternalPtr) value).getAddr().asAddress())).append('>');
+                SymbolHandle handle = ((RExternalPtr) value).getAddr();
+                if (handle.isLong()) {
+                    append("<pointer: 0x").append(Long.toHexString(handle.asAddress())).append('>');
+                } else {
+                    append("<pointer: external ptr 0x").append(Long.toHexString(System.identityHashCode(handle.asTruffleObject()))).append('>');
+                }
             } else if (value instanceof REnvironment) {
                 append("<environment>");
             } else if (value instanceof REmpty) {
@@ -780,7 +794,7 @@ public class RDeparse {
             } else if (value instanceof TruffleObject) {
                 append("<truffle object>");
             } else {
-                throw RInternalError.shouldNotReachHere("unexpected: " + value);
+                throw RInternalError.shouldNotReachHere("unexpected type while deparsing constant: " + value == null ? "null" : value.getClass().getSimpleName());
             }
             return this;
         }
@@ -842,7 +856,7 @@ public class RDeparse {
             assert v != null;
             assert !(v instanceof RSyntaxElement) : v.getClass();
 
-            Object value = RRuntime.asAbstractVector(v);
+            Object value = RRuntime.convertScalarVectors(v);
             assert value instanceof RTypedValue : v.getClass();
 
             try {
@@ -878,13 +892,21 @@ public class RDeparse {
             }
         }
 
-        private void appendVector(RAbstractVector vec) {
-            SEXPTYPE type = SEXPTYPE.typeForClass(vec.getClass());
+        private void appendVector(RAbstractAtomicVector vec) {
             int len = vec.getLength();
             if (len == 0) {
                 append(vec.getRType().getClazz() + "(0)");
+            } else if (vec instanceof RAbstractRawVector) {
+                append("as.raw(c(");
+                for (int i = 0; i < len; i++) {
+                    if (i > 0) {
+                        append(", ");
+                    }
+                    vecElement2buff(vec.getDataAtAsObject(i), false);
+                }
+                append("))");
             } else if (len == 1) {
-                vecElement2buff(type, vec.getDataAtAsObject(0), true);
+                vecElement2buff(vec.getDataAtAsObject(0), true);
             } else {
                 RIntSequence sequence = asIntSequence(vec);
                 if (sequence != null) {
@@ -892,25 +914,14 @@ public class RDeparse {
                     return;
                 } else {
                     // TODO COMPAT?
-                    if (type == SEXPTYPE.RAWSXP) {
-                        append("as.raw(c(");
-                        for (int i = 0; i < len; i++) {
-                            if (i > 0) {
-                                append(", ");
-                            }
-                            vecElement2buff(type, vec.getDataAtAsObject(i), false);
+                    append("c(");
+                    for (int i = 0; i < len; i++) {
+                        if (i > 0) {
+                            append(", ");
                         }
-                        append("))");
-                    } else {
-                        append("c(");
-                        for (int i = 0; i < len; i++) {
-                            if (i > 0) {
-                                append(", ");
-                            }
-                            vecElement2buff(type, vec.getDataAtAsObject(i), false);
-                        }
-                        append(')');
+                        vecElement2buff(vec.getDataAtAsObject(i), false);
                     }
+                    append(')');
                 }
             }
         }
@@ -937,44 +948,37 @@ public class RDeparse {
             return RDataFactory.createIntSequence(start, 1, intVec.getLength());
         }
 
-        private DeparseVisitor vecElement2buff(SEXPTYPE type, Object element, boolean singleElement) {
-            switch (type) {
-                case STRSXP:
-                    String s = (String) element;
-                    append(RRuntime.isNA(s) ? (singleElement ? "NA_character_" : "NA") : RRuntime.escapeString(s, true, true));
-                    break;
-                case LGLSXP:
-                    append(RRuntime.logicalToString((byte) element));
-                    break;
-                case REALSXP:
-                    double d = (double) element;
-                    append(RRuntime.isNA(d) ? (singleElement ? "NA_real_" : "NA") : RContext.getRRuntimeASTAccess().encodeDouble(d));
-                    break;
-                case INTSXP:
-                    int i = (int) element;
-                    if (RRuntime.isNA(i)) {
-                        append((singleElement ? "NA_integer_" : "NA"));
-                    } else {
-                        append(RRuntime.intToStringNoCheck(i));
-                        if ((opts & KEEPINTEGER) != 0) {
-                            append('L');
-                        }
-                    }
-                    break;
-                case CPLXSXP:
-                    RComplex c = (RComplex) element;
-                    if (RRuntime.isNA(c)) {
-                        append((singleElement ? "NA_complex_" : "NA"));
-                    } else {
-                        append(RContext.getRRuntimeASTAccess().encodeComplex(c));
+        private DeparseVisitor vecElement2buff(Object element, boolean singleElement) {
+            if (element instanceof String) {
+                String s = (String) element;
+                append(RRuntime.isNA(s) ? (singleElement ? "NA_character_" : "NA") : RRuntime.escapeString(s, true, true));
+            } else if (element instanceof Byte) {
+                // simply "NA" is already the logical NA, so no special handling needed
+                append(RRuntime.logicalToString((byte) element));
+            } else if (element instanceof Double) {
+                double d = (double) element;
+                append(RRuntime.isNA(d) ? (singleElement ? "NA_real_" : "NA") : RContext.getRRuntimeASTAccess().encodeDouble(d));
+            } else if (element instanceof Integer) {
+                int i = (int) element;
+                if (RRuntime.isNA(i)) {
+                    append((singleElement ? "NA_integer_" : "NA"));
+                } else {
+                    append(RRuntime.intToStringNoCheck(i));
+                    if ((opts & KEEPINTEGER) != 0) {
+                        append('L');
                     }
-                    break;
-                case RAWSXP:
-                    RRaw r = (RRaw) element;
-                    append(Utils.stringFormat("0x%02x", r.getValue()));
-                    break;
-                default:
-                    throw RInternalError.shouldNotReachHere("unexpected SEXPTYPE: " + type);
+                }
+            } else if (element instanceof RComplex) {
+                RComplex c = (RComplex) element;
+                if (RRuntime.isNA(c)) {
+                    append((singleElement ? "NA_complex_" : "NA"));
+                } else {
+                    append(RContext.getRRuntimeASTAccess().encodeComplex(c));
+                }
+            } else if (element instanceof RRaw) {
+                append(Utils.stringFormat("0x%02x", ((RRaw) element).getValue()));
+            } else {
+                throw RInternalError.shouldNotReachHere("unexpected vector element type during deparsing: " + (element == null ? "null" : element.getClass().getSimpleName()));
             }
             return this;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
index 9818a20c8ce15f016dd668e620f8ee0420aeefe0..53fd56a5b245aa82113014b9995c3d4bab41f45a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.runtime;
 
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.DEFAULT_PACKAGES;
-
 import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileReader;
@@ -40,6 +38,8 @@ import java.util.Map;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RCmdOptions.RCmdOption;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 
@@ -62,9 +62,9 @@ public final class REnvVars implements RContext.ContextState {
     public RContext.ContextState initialize(RContext context) {
         // explicit environment settings in nested contexts must be installed first
         checkExplicitEnvSettings(context);
-        RCmdOptions cmdOptions = context.getStartParams().getRCmdOptions();
+        RCmdOptions cmdOptions = context.getCmdOptions();
         // If running Rscript, R_DEFAULT_PACKAGES may need to be set
-        String defaultPackages = cmdOptions.getString(DEFAULT_PACKAGES);
+        String defaultPackages = cmdOptions.getString(RCmdOption.DEFAULT_PACKAGES);
         if (defaultPackages != null) {
             envVars.put("R_DEFAULT_PACKAGES", defaultPackages);
         }
@@ -87,7 +87,7 @@ public final class REnvVars implements RContext.ContextState {
             // This gets expanded by R code in the system profile
         }
 
-        if (!context.getStartParams().getNoRenviron()) {
+        if (!context.getStartParams().noRenviron()) {
             String siteFile = envVars.get("R_ENVIRON");
             if (siteFile == null) {
                 siteFile = fileSystem.getPath(rHome, "etc", "Renviron.site").toString();
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 d5a95388201ad5c3bc91b398e87617eee8c36532..8e0f4da8cea9e117c665ca60c6e8aaea3b68c409 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
@@ -16,13 +16,16 @@ import java.io.IOException;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.TruffleException;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.env.REnvironment.PutException;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 /**
  * A facade for handling errors. This class extends {@link RuntimeException} so that it can be
@@ -46,9 +49,10 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  * Currently,there are no such cases.
  */
 @SuppressWarnings("serial")
-public final class RError extends RuntimeException {
+public final class RError extends RuntimeException implements TruffleException {
 
     private final String verboseStackTrace;
+    private final Node location;
 
     /**
      * This exception should be subclassed by subsystems that need to throw subsystem-specific
@@ -63,8 +67,8 @@ public final class RError extends RuntimeException {
         @CompilationFinal(dimensions = 1) private final Object[] args;
 
         @TruffleBoundary
-        protected RErrorException(RError.Message msg, Object[] args) {
-            super(RErrorHandling.formatMessage(msg, args), null);
+        protected RErrorException(Throwable cause, RError.Message msg, Object[] args) {
+            super(RErrorHandling.formatMessage(msg, args), cause);
             this.msg = msg;
             this.args = args;
         }
@@ -79,10 +83,19 @@ public final class RError extends RuntimeException {
         protected RBaseNode getErrorContext() {
             return this;
         }
+
+        @Override
+        public SourceSection getEncapsulatingSourceSection() {
+            return RSyntaxNode.INTERNAL;
+        }
+
+        @Override
+        public SourceSection getSourceSection() {
+            return RSyntaxNode.INTERNAL;
+        }
     }
 
     private static final class ErrorContextImpl extends ErrorContext {
-
     }
 
     public static ErrorContext contextForBuiltin(RBuiltin builtin) {
@@ -123,9 +136,10 @@ public final class RError extends RuntimeException {
     /**
      * TODO the string is not really needed as all output is performed prior to the throw.
      */
-    RError(String msg) {
+    RError(String msg, Node location) {
         super(msg);
-        verboseStackTrace = RInternalError.createVerboseStackTrace();
+        this.location = location;
+        this.verboseStackTrace = RInternalError.createVerboseStackTrace();
     }
 
     @Override
@@ -305,7 +319,7 @@ public final class RError extends RuntimeException {
         MORE_SUPPLIED_REPLACE("more elements supplied than there are to replace"),
         NA_SUBSCRIPTED("NAs are not allowed in subscripted assignments"),
         INVALID_ARG_TYPE("invalid argument type"),
-        INVALID_ARG_TYPE_UNARY("invalid argument to unary operator"),
+        INVALID_ARG_UNARY("invalid argument to unary operator"),
         VECTOR_SIZE_NEGATIVE("vector size cannot be negative"),
         VECTOR_SIZE_NA("vector size cannot be NA"),
         VECTOR_SIZE_NA_NAN("vector size cannot be NA/NaN"),
@@ -432,6 +446,7 @@ public final class RError extends RuntimeException {
         LIST_NAMES_SAME_LENGTH("names(x) must be a character vector of the same length as x"),
         DIMS_CONTAIN_NEGATIVE_VALUES("the dims contain negative values"),
         NEGATIVE_LENGTH_VECTORS_NOT_ALLOWED("negative length vectors are not allowed"),
+        LONG_VECTORS_NOT_SUPPORTED("long length vectors are not suppoted"),
         FIRST_ARG_MUST_BE_ARRAY("invalid first argument, must be an array"),
         IMAGINARY_PARTS_DISCARDED_IN_COERCION("imaginary parts discarded in coercion"),
         DIMS_CONTAIN_NA("the dims contain missing values"),
@@ -614,6 +629,7 @@ public final class RError extends RuntimeException {
         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"),
+        CANNOT_COERCE_EXTERNAL_OBJECT_TO_VECTOR("no method for coercing this external object to a %s"),
         // 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"),
@@ -622,6 +638,7 @@ public final class RError extends RuntimeException {
         FIRST_ARGUMENT_MUST_BE_CHARACTER("the first argument must be of mode character"),
         ALL_ATTRIBUTES_NAMES("all attributes must have names [%d does not]"),
         INVALID_REGEXP("invalid regular expression '%s'"),
+        INVALID_REGEXP_REASON("invalid regular expression '%s': %s"),
         COERCING_ARGUMENT("coercing argument of type '%s' to %s"),
         MUST_BE_TRUE_FALSE_ENVIRONMENT("'%s' must be TRUE, FALSE or an environment"),
         UNKNOWN_OBJECT_MODE("object '%s' of mode '%s' was not found"),
@@ -877,7 +894,9 @@ public final class RError extends RuntimeException {
         NO_BINDING_FOR("no binding for \"%s\""),
         INVALID_SUBSTRING_ARGS("invalid substring arguments"),
         OBJECT_SIZE_ESTIMATE("The object size is only estimated."),
-        REPLACING_IN_NON_CHAR_OBJ("replacing substrings in a non-character object");
+        REPLACING_IN_NON_CHAR_OBJ("replacing substrings in a non-character object"),
+        FILE_NOT_FOUND_IN_ZIP("requested file not found in the zip file"),
+        LIST_NO_VALID_NAMES("list argument has no valid names");
 
         public final String message;
         final boolean hasArgs;
@@ -887,4 +906,9 @@ public final class RError extends RuntimeException {
             hasArgs = message.indexOf('%') >= 0;
         }
     }
+
+    @Override
+    public Node getLocation() {
+        return location;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index 6913a4f10243e621613dcd5c67915e5b532eb991..5b78bfd0da8f665ad8d75373985864007a377ff5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -18,6 +18,7 @@ import com.oracle.truffle.api.CompilerDirectives;
 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.nodes.Node;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -353,7 +354,7 @@ public class RErrorHandling {
                 if (isCallingEntry(entry)) {
                     Object h = entry.getDataAt(ENTRY_HANDLER);
                     if (h == RESTART_TOKEN) {
-                        errorcallDfltWithCall(fromCall(call), Message.GENERIC, msg);
+                        errorcallDfltWithCall(null, fromCall(call), Message.GENERIC, msg);
                     } else {
                         RFunction hf = (RFunction) h;
                         RContext.getEngine().evalFunction(hf, null, null, true, null, cond);
@@ -444,7 +445,7 @@ public class RErrorHandling {
 
     @TruffleBoundary
     public static void dfltStop(String msg, Object call) {
-        errorcallDfltWithCall(fromCall(call), Message.GENERIC, msg);
+        errorcallDfltWithCall(null, fromCall(call), Message.GENERIC, msg);
     }
 
     @TruffleBoundary
@@ -470,14 +471,14 @@ public class RErrorHandling {
     }
 
     static RError errorcallDflt(boolean showCall, RBaseNode callObj, Message msg, Object... objects) throws RError {
-        return errorcallDfltWithCall(showCall ? findCaller(callObj) : RNull.instance, msg, objects);
+        return errorcallDfltWithCall(callObj, showCall ? findCaller(callObj) : RNull.instance, msg, objects);
     }
 
     /**
      * The default error handler. This is where all the error message formatting is done and the
      * output.
      */
-    private static RError errorcallDfltWithCall(Object call, Message msg, Object... objects) throws RError {
+    private static RError errorcallDfltWithCall(Node location, Object call, Message msg, Object... objects) throws RError {
         String fmsg = formatMessage(msg, objects);
 
         String errorMessage = createErrorMessage(call, fmsg);
@@ -493,7 +494,7 @@ public class RErrorHandling {
                 errorHandlingState.warnings.clear();
                 Utils.writeStderr("Lost warning messages", true);
             }
-            throw new RError(errorMessage);
+            throw new RError(errorMessage, location);
         }
 
         Utils.writeStderr(errorMessage, true);
@@ -540,7 +541,7 @@ public class RErrorHandling {
             }
         }
 
-        if (RContext.getInstance().getConsoleHandler().isInteractive() || errorExpr != RNull.instance) {
+        if (RContext.getInstance().isInteractive() || errorExpr != RNull.instance) {
             Object trace = Utils.createTraceback(0);
             try {
                 REnvironment env = RContext.getInstance().stateREnvironment.getBaseEnv();
@@ -549,7 +550,7 @@ public class RErrorHandling {
                 throw RInternalError.shouldNotReachHere("cannot write .Traceback");
             }
         }
-        throw new RError(errorMessage);
+        throw new RError(errorMessage, location);
     }
 
     private static MaterializedFrame safeCurrentFrame() {
@@ -584,12 +585,29 @@ public class RErrorHandling {
         warningCallInvoke(call, RDataFactory.createStringVectorFromScalar(message));
     }
 
+    /**
+     * Entry point for Rf_errorCall from RFFI.
+     */
+    public static void errorcallRFFI(Object call, String message) {
+        errorCallInvoke(call, RDataFactory.createStringVectorFromScalar(message));
+    }
+
+    private static void errorCallInvoke(Object call, RStringVector errorMessage) {
+        errorcallDfltWithCall(null, call, Message.GENERIC, errorMessage, new Object[]{errorMessage});
+    }
+
     static void warningcall(boolean showCall, RBaseNode callObj, Message msg, Object... args) {
         Object call = showCall ? findCaller(callObj) : RNull.instance;
         RStringVector warningMessage = RDataFactory.createStringVectorFromScalar(formatMessage(msg, args));
         warningCallInvoke(call, warningMessage);
     }
 
+    static void errorcall(boolean showCall, RBaseNode callObj, Message msg, Object... args) {
+        Object call = showCall ? findCaller(callObj) : RNull.instance;
+        RStringVector warningMessage = RDataFactory.createStringVectorFromScalar(formatMessage(msg, args));
+        warningCallInvoke(call, warningMessage);
+    }
+
     private static void warningCallInvoke(Object call, RStringVector warningMessage) {
         /*
          * Warnings generally do not prevent results being printed. However, this call into R will
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
index a5287eceb233aed86d7ad08ace8a7944c00dd45b..2a29784e9d0ce13e72fedcfe15f6ef086edab9b0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
@@ -44,7 +44,7 @@ public final class RInternalCode {
     private final String basePackage;
     private final Source source;
 
-    private REnvironment evaluatedEnvironment;
+    private volatile REnvironment evaluatedEnvironment;
 
     private RInternalCode(RContext context, String basePackage, Source source) {
         this.context = context;
@@ -57,7 +57,7 @@ public final class RInternalCode {
         return Utils.getResourceAsSource(clazz, fileName);
     }
 
-    private REnvironment evaluate() {
+    private synchronized REnvironment evaluate() {
         try {
             RExpression parsedCode = context.getThisEngine().parse(source);
             REnvironment statsPackage = REnvironment.getRegisteredNamespace(context, basePackage);
@@ -72,13 +72,15 @@ public final class RInternalCode {
         }
     }
 
-    public RFunction lookupFunction(String name) {
+    public synchronized RFunction lookupFunction(String name) {
         REnvironment env = this.evaluatedEnvironment;
         if (env == null) {
             env = evaluate();
             this.evaluatedEnvironment = env;
         }
-        return (RFunction) env.get(name);
+        RFunction fun = (RFunction) env.get(name);
+        assert fun != null;
+        return fun;
     }
 
     public static RInternalCode lookup(RContext context, String basePackage, Source source) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java
index f1a38ffad7ecfc6c156c371b45fa09cddc2031d4..4095b0ad6d57dd0bd46dc0670a6ea6642c3aa34c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalError.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
@@ -36,13 +36,14 @@ import java.util.Date;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
+import com.oracle.truffle.api.TruffleException;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
  * This class is intended to be used for internal errors that do not correspond to R errors.
  */
-public final class RInternalError extends Error {
+public final class RInternalError extends Error implements TruffleException {
 
     private static final long serialVersionUID = 80698622974155216L;
 
@@ -147,55 +148,71 @@ public final class RInternalError extends Error {
     }
 
     @TruffleBoundary
-    public static void reportErrorAndConsoleLog(Throwable throwable, ConsoleHandler consoleHandler, int contextId) {
-        reportError(throwable, consoleHandler, contextId);
+    public static void reportErrorAndConsoleLog(Throwable throwable, int contextId) {
+        reportError(throwable, contextId);
     }
 
     @TruffleBoundary
     public static void reportError(Throwable throwable) {
-        reportError(throwable, null, 0);
+        reportError(throwable, 0);
     }
 
-    private static void reportError(Throwable throwable, ConsoleHandler consoleHandler, int contextId) {
-        Throwable t = throwable;
-        if (FastROptions.PrintErrorStacktracesToFile.getBooleanValue() || FastROptions.PrintErrorStacktraces.getBooleanValue()) {
+    private static void reportError(Throwable throwable, int contextId) {
+        try {
+            Throwable t = throwable;
+            if (FastROptions.PrintErrorStacktracesToFile.getBooleanValue() || FastROptions.PrintErrorStacktraces.getBooleanValue()) {
 
-            ByteArrayOutputStream out = new ByteArrayOutputStream();
-            t.printStackTrace(new PrintStream(out));
-            String verboseStackTrace;
-            if (t instanceof IOException) {
-                t = t.getCause();
-            }
-            if (t instanceof RInternalError) {
-                verboseStackTrace = ((RInternalError) t).getVerboseStackTrace();
-            } else if (t instanceof RError) {
-                verboseStackTrace = ((RError) t).getVerboseStackTrace();
-            } else {
-                verboseStackTrace = "";
-            }
-            if (FastROptions.PrintErrorStacktraces.getBooleanValue()) {
-                System.err.println(out.toString());
-                System.err.println(verboseStackTrace);
-            }
-            if (FastROptions.PrintErrorStacktracesToFile.getBooleanValue()) {
-                String suffix = contextId == 0 ? "" : "-" + Integer.toString(contextId);
-                Path logfile = Utils.getLogPath("fastr_errors.log" + suffix);
-                try (BufferedWriter writer = Files.newBufferedWriter(logfile, StandardCharsets.UTF_8, StandardOpenOption.APPEND,
-                                StandardOpenOption.CREATE)) {
-                    writer.append(new Date().toString()).append('\n');
-                    writer.append(out.toString()).append('\n');
-                    writer.append(verboseStackTrace).append("\n\n");
-                } catch (IOException e) {
-                    e.printStackTrace();
+                ByteArrayOutputStream out = new ByteArrayOutputStream();
+                t.printStackTrace(new PrintStream(out));
+                String verboseStackTrace;
+                if (t.getCause() != null && t instanceof IOException) {
+                    t = t.getCause();
+                }
+                if (t instanceof RInternalError) {
+                    verboseStackTrace = ((RInternalError) t).getVerboseStackTrace();
+                } else if (t instanceof RError) {
+                    verboseStackTrace = ((RError) t).getVerboseStackTrace();
+                } else {
+                    verboseStackTrace = "";
                 }
-                if (RContext.isEmbedded()) {
-                    Utils.rSuicide("FastR internal error");
+                if (FastROptions.PrintErrorStacktraces.getBooleanValue()) {
+                    System.err.println(out.toString());
+                    System.err.println(verboseStackTrace);
                 }
-                if (consoleHandler != null) {
-                    String message = t instanceof RInternalError && t.getMessage() != null && !t.getMessage().isEmpty() ? t.getMessage() : "internal error: " + t.getClass().getSimpleName();
-                    consoleHandler.println(message + " (see fastr_errors.log" + suffix + ")");
+                String message = t instanceof RInternalError && t.getMessage() != null && !t.getMessage().isEmpty() ? t.getMessage() : "internal error: " + t.getClass().getSimpleName();
+                if (FastROptions.PrintErrorStacktracesToFile.getBooleanValue()) {
+                    String suffix = contextId == 0 ? "" : "-" + Integer.toString(contextId);
+                    Path logfile = Utils.getLogPath("fastr_errors.log" + suffix);
+                    try (BufferedWriter writer = Files.newBufferedWriter(logfile, StandardCharsets.UTF_8, StandardOpenOption.APPEND,
+                                    StandardOpenOption.CREATE)) {
+                        writer.append(new Date().toString()).append('\n');
+                        writer.append(out.toString()).append('\n');
+                        writer.append(verboseStackTrace).append("\n\n");
+                    } catch (IOException e) {
+                        e.printStackTrace();
+                    }
+                    System.err.println(message + " (see fastr_errors.log" + suffix + ")");
+                    if (RContext.isEmbedded()) {
+                        Utils.rSuicide("FastR internal error");
+                    }
+                }
+                if (!FastROptions.PrintErrorStacktraces.getBooleanValue() && !FastROptions.PrintErrorStacktracesToFile.getBooleanValue()) {
+                    System.err.println(message);
                 }
             }
+        } catch (Throwable t) {
+            System.err.println("error while reporting internal error:");
+            t.printStackTrace();
         }
     }
+
+    @Override
+    public Node getLocation() {
+        return null;
+    }
+
+    @Override
+    public boolean isInternalError() {
+        return true;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
index 8d5c70e8c0b217218f24bdf35ff30b62e553c64f..57860a82591b1eca7b7c0855efd1a209ce2400a1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
@@ -19,6 +19,7 @@ import java.util.Map.Entry;
 import java.util.Set;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
@@ -31,6 +32,7 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
 import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
@@ -135,7 +137,7 @@ public class ROptions {
     @SuppressWarnings("serial")
     public static final class OptionsException extends RError.RErrorException {
         private OptionsException(RError.Message msg, Object... args) {
-            super(msg, args);
+            super(null, msg, args);
         }
 
         private static OptionsException createInvalid(String name) {
@@ -159,7 +161,7 @@ public class ROptions {
         map.put("continue", RDataFactory.createSharedStringVectorFromScalar("+ "));
         map.put("deparse.cutoff", RDataFactory.createSharedIntVectorFromScalar(60));
         map.put("digits", RDataFactory.createSharedIntVectorFromScalar(7));
-        map.put("echo", RDataFactory.createSharedLogicalVectorFromScalar(startParams.getSlave() ? false : true));
+        map.put("echo", RDataFactory.createSharedLogicalVectorFromScalar(startParams.isSlave() ? false : true));
         map.put("encoding", RDataFactory.createSharedStringVectorFromScalar("native.enc"));
         map.put("expressions", RDataFactory.createSharedIntVectorFromScalar(5000));
         boolean keepPkgSource = optionFromEnvVar("R_KEEP_PKG_SOURCE", envVars);
@@ -376,10 +378,10 @@ public class ROptions {
     }
 
     private static Object coerceStringVector(Object value, String name) throws OptionsException {
-        Object valueAbs = RRuntime.asAbstractVector(value);
+        Object valueAbs = RRuntime.convertScalarVectors(value);
         // TODO supposed to be coerced
-        if (valueAbs instanceof RStringVector) {
-            String p = ((RStringVector) valueAbs).getDataAt(0);
+        if (valueAbs instanceof RAbstractStringVector) {
+            String p = ((RAbstractStringVector) valueAbs).getDataAt(0);
             if (p.length() == 0 || RRuntime.isNA(p)) {
                 throw OptionsException.createInvalid(name);
             } else {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RParserFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RParserFactory.java
index e47b74c6da9e380cae861481abafabfd5d63425e..f42227d82e276a80c92f214e516232225a6cdf2b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RParserFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RParserFactory.java
@@ -26,6 +26,7 @@ import java.util.List;
 
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
 
@@ -34,9 +35,9 @@ import com.oracle.truffle.r.runtime.nodes.RCodeBuilder;
  */
 public abstract class RParserFactory {
     public interface Parser<T> {
-        List<T> script(Source source, RCodeBuilder<T> builder) throws ParseException;
+        List<T> script(Source source, RCodeBuilder<T> builder, TruffleRLanguage language) throws ParseException;
 
-        RootCallTarget rootFunction(Source source, String name, RCodeBuilder<T> builder) throws ParseException;
+        RootCallTarget rootFunction(Source source, String name, RCodeBuilder<T> builder, TruffleRLanguage language) throws ParseException;
 
         boolean isRecognitionException(Throwable t);
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
index 80a9f3cad82eed5af15ce628fe23d50d00074f97..9c7682b52345665cefef553f175f2c8af9285a23 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
@@ -66,7 +66,7 @@ public final class RProfile implements RContext.ContextState {
             }
         }
 
-        if (context.getStartParams().getLoadInitFile()) {
+        if (context.getStartParams().loadInitFile()) {
             String userProfilePath = envVars.get("R_PROFILE_USER");
             if (userProfilePath == null) {
                 String dotRenviron = ".Rprofile";
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
index 28425664c60a0e00e51f826fd6d7fed07ac1ec27..144cb8f2ac25ace0926f56dce84638b94b966c50 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java
@@ -21,31 +21,24 @@ import com.oracle.truffle.api.frame.FrameSlotKind;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDouble;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RInteger;
-import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte;
-import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar;
-import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat;
-import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong;
-import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort;
 import com.oracle.truffle.r.runtime.data.RLogical;
-import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RRaw;
+import com.oracle.truffle.r.runtime.data.RScalar;
 import com.oracle.truffle.r.runtime.data.RString;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTypedValue;
-import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
 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.RAbstractLogicalVector;
-import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -72,13 +65,6 @@ public class RRuntime {
         "\n" +
         "Type 'q()' to quit R.";
 
-    public static final String LICENSE =
-        "This software is distributed under the terms of the GNU General Public License\n" +
-        "Version 2, June 1991. The terms of the license are in a file called COPYING\n" +
-        "which you should have received with this software. A copy of the license can be\n" +
-        "found at http://www.gnu.org/licenses/gpl-2.0.html.\n" +
-        "\n" +
-        "'Share and Enjoy.'";
     //@formatter:on
 
     public static final String R_APP_MIME = "application/x-r";
@@ -798,9 +784,16 @@ public class RRuntime {
     /**
      * Java equivalent of GnuR asLogical for use outside Truffle boundary. TODO support for warnings
      */
-    public static byte asLogicalObject(Object objArg) {
-        Object obj = asAbstractVector(objArg);
-        if (obj instanceof RAbstractIntVector) {
+    public static byte asLogicalObject(Object obj) {
+        if (obj instanceof Integer) {
+            return int2logical((int) obj);
+        } else if (obj instanceof Double) {
+            return double2logical((double) obj);
+        } else if (obj instanceof Byte) {
+            return (byte) obj;
+        } else if (obj instanceof String) {
+            return string2logical((String) obj);
+        } else if (obj instanceof RAbstractIntVector) {
             return int2logical(((RAbstractIntVector) obj).getDataAt(0));
         } else if (obj instanceof RAbstractDoubleVector) {
             return double2logical(((RAbstractDoubleVector) obj).getDataAt(0));
@@ -818,9 +811,16 @@ public class RRuntime {
     /**
      * Java equivalent of GnuR asInteger for use outside Truffle boundary. TODO support for warnings
      */
-    public static int asInteger(Object objArg) {
-        Object obj = asAbstractVector(objArg);
-        if (obj instanceof RAbstractIntVector) {
+    public static int asInteger(Object obj) {
+        if (obj instanceof Integer) {
+            return (int) obj;
+        } else if (obj instanceof Double) {
+            return double2int((double) obj);
+        } else if (obj instanceof Byte) {
+            return logical2int((byte) obj);
+        } else if (obj instanceof String) {
+            return string2int((String) obj);
+        } else if (obj instanceof RAbstractIntVector) {
             return ((RAbstractIntVector) obj).getDataAt(0);
         } else if (obj instanceof RAbstractDoubleVector) {
             return double2int(((RAbstractDoubleVector) obj).getDataAt(0));
@@ -871,6 +871,25 @@ public class RRuntime {
         }
     }
 
+    /**
+     * Convert Java boxing classes to {@link RScalar} subclasses, which implement the proper
+     * {@link RAbstractVector} interfaces. This doesn't go through {@link RDataFactory}, but it
+     * increases polymorphism by not using the normal vector classes.
+     */
+    public static Object convertScalarVectors(Object obj) {
+        if (obj instanceof Integer) {
+            return RInteger.valueOf((int) obj);
+        } else if (obj instanceof Double) {
+            return RDouble.valueOf((double) obj);
+        } else if (obj instanceof Byte) {
+            return RLogical.valueOf((byte) obj);
+        } else if (obj instanceof String) {
+            return RString.valueOf((String) obj);
+        } else {
+            return obj;
+        }
+    }
+
     public static boolean isForeignObject(TruffleObject obj) {
         return !(obj instanceof RTypedValue);
     }
@@ -926,67 +945,4 @@ public class RRuntime {
     private static boolean hasDims(RAbstractContainer xa) {
         return xa.hasDimensions();
     }
-
-    public static Object java2R(Object obj) {
-        if (obj == null) {
-            obj = RNull.instance;
-        } else if (obj instanceof Boolean) {
-            obj = RRuntime.asLogical((boolean) obj);
-        } else if (obj instanceof Byte) {
-            obj = ((Byte) obj).intValue();
-        } else if (obj instanceof Short) {
-            obj = ((Short) obj).intValue();
-        } else if (obj instanceof Long) {
-            obj = (((Long) obj).doubleValue());
-        } else if (obj instanceof Float) {
-            obj = (((Float) obj).doubleValue());
-        } else if (obj instanceof Character) {
-            obj = ((Character) obj).toString();
-        }
-        return obj;
-    }
-
-    public static Object[] r2Java(Object[] objects) {
-        Object[] ret = new Object[objects.length];
-        for (int i = 0; i < objects.length; i++) {
-            ret[i] = RRuntime.r2Java(objects[i]);
-        }
-        return ret;
-    }
-
-    public static Object r2Java(Object obj) {
-        if (obj == RNull.instance) {
-            return JavaInterop.asTruffleObject(null);
-        } else if (obj instanceof Byte) {
-            return RRuntime.fromLogical((byte) obj);
-        } else if (obj instanceof RInteropByte) {
-            return ((RInteropByte) obj).getValue();
-        } else if (obj instanceof RInteropChar) {
-            return ((RInteropChar) obj).getValue();
-        } else if (obj instanceof RInteropFloat) {
-            return ((RInteropFloat) obj).getValue();
-        } else if (obj instanceof RInteropLong) {
-            return ((RInteropLong) obj).getValue();
-        } else if (obj instanceof RInteropShort) {
-            return ((RInteropShort) obj).getValue();
-        } else if (obj instanceof RAbstractAtomicVector && ((RAbstractAtomicVector) obj).getLength() == 1) {
-            if (obj instanceof RAbstractDoubleVector) {
-                RAbstractDoubleVector v = (RAbstractDoubleVector) obj;
-                return v.getDataAt(0);
-            } else if (obj instanceof RAbstractIntVector) {
-                RAbstractIntVector v = (RAbstractIntVector) obj;
-                return v.getDataAt(0);
-            } else if (obj instanceof RAbstractLogicalVector) {
-                RAbstractLogicalVector v = (RAbstractLogicalVector) obj;
-                return v.getDataAt(0) == RRuntime.LOGICAL_TRUE;
-            } else if (obj instanceof RAbstractRawVector) {
-                RAbstractRawVector v = (RAbstractRawVector) obj;
-                return v.getDataAt(0).getValue();
-            } else if (obj instanceof RAbstractStringVector) {
-                RAbstractStringVector v = (RAbstractStringVector) obj;
-                return v.getDataAt(0);
-            }
-        }
-        return obj;
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
index 15c84e15e28fe07d215ca5a9e60a6ff9f1b8d959..fe78327aeb55db9317feefacba162cdefeb53f8e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
@@ -22,11 +22,11 @@
  */
 package com.oracle.truffle.r.runtime;
 
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RFunction;
@@ -96,8 +96,7 @@ public interface RRuntimeASTAccess {
     /**
      * Gets {@code TruffleRLanguage} avoiding project circularity.
      */
-    @SuppressWarnings("rawtypes")
-    Class<? extends TruffleLanguage> getTruffleRLanguage();
+    Class<? extends TruffleRLanguage> getTruffleRLanguage();
 
     /**
      * Returns a string for a call as represented by {@code rl}, returned originally by
@@ -204,4 +203,6 @@ public interface RRuntimeASTAccess {
     void checkDebugRequest(RFunction func);
 
     RAbstractStringVector getClassHierarchy(RAttributable value);
+
+    RContext getCurrentContext();
 }
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 410a9d3b4f89474c1fc5e5f36acfd473257aa4f8..00ed14aecea4faa1e75f344e508768d4e918f48c 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
@@ -20,6 +20,8 @@ import java.io.PrintStream;
 import java.lang.ref.WeakReference;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Deque;
@@ -44,6 +46,7 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
@@ -582,11 +585,16 @@ public class RSerialize {
                                 }
                                 Debug.printClosure(pairList);
                             }
-                            RFunction func = PairlistDeserializer.processFunction(carItem, cdrItem, tagItem, currentFunctionName, packageName);
+                            boolean restore = setupLibPath((REnvironment) tagItem);
+                            RFunction func = PairlistDeserializer.processFunction(carItem, cdrItem, (REnvironment) tagItem, currentFunctionName, packageName);
                             if (attrItem != RNull.instance) {
                                 setAttributes(func, attrItem);
                                 handleFunctionSrcrefAttr(func);
                             }
+                            if (restore) {
+                                RContext.getInstance().libraryPaths.remove(0);
+                            }
+
                             result = func;
                             break;
                         }
@@ -776,7 +784,7 @@ public class RSerialize {
                 case BUILTINSXP: {
                     int len = stream.readInt();
                     String s = stream.readString(len);
-                    result = RContext.lookupBuiltin(s);
+                    result = RContext.getInstance().lookupBuiltin(s);
                     RInternalError.guarantee(result != null, "lookup failed in unserialize for builtin: " + s);
                     break;
                 }
@@ -1060,9 +1068,88 @@ public class RSerialize {
 
         private static final int READ_BUFFER_SIZE = 32 * 1024;
 
-        private final byte[] buf;
-        private int size;
-        private int offset;
+        private final class Buffer {
+            private final byte[] buf;
+            private int size;
+            private int offset;
+
+            Buffer(byte[] buf) {
+                this.buf = buf;
+            }
+
+            int readInt() {
+                return ((buf[offset++] & 0xff) << 24 | (buf[offset++] & 0xff) << 16 | (buf[offset++] & 0xff) << 8 | (buf[offset++] & 0xff));
+            }
+
+            double readDouble() {
+                long val = ((long) (buf[offset++] & 0xff) << 56 | (long) (buf[offset++] & 0xff) << 48 | (long) (buf[offset++] & 0xff) << 40 | (long) (buf[offset++] & 0xff) << 32 |
+                                (long) (buf[offset++] & 0xff) << 24 | (long) (buf[offset++] & 0xff) << 16 | (long) (buf[offset++] & 0xff) << 8 | buf[offset++] & 0xff);
+                return Double.longBitsToDouble(val);
+            }
+
+            @SuppressWarnings("deprecation")
+            String readString(int len) {
+                /*
+                 * This fast path uses a cheaper String constructor if all incoming bytes are in the
+                 * 0-127 range.
+                 */
+                boolean fastEncode = true;
+                for (int i = 0; i < len; i++) {
+                    byte b = buf[offset + i];
+                    if (b < 0) {
+                        fastEncode = false;
+                        break;
+                    }
+                }
+                String result;
+                if (fastEncode) {
+                    result = new String(buf, 0, offset, len);
+                } else {
+                    result = new String(buf, offset, len, StandardCharsets.UTF_8);
+                }
+                offset += len;
+                WeakReference<String> entry;
+                if ((entry = strings.get(result)) != null) {
+                    String string = entry.get();
+                    if (string != null) {
+                        return string;
+                    }
+                }
+                strings.put(result, new WeakReference<>(result));
+                return result;
+            }
+
+            void readRaw(byte[] data) {
+                System.arraycopy(buf, offset, data, 0, data.length);
+                offset += data.length;
+            }
+
+            void readData(int n) throws IOException {
+                if (offset + n > size) {
+                    if (offset != size) {
+                        // copy end piece to beginning
+                        System.arraycopy(buf, offset, buf, 0, size - offset);
+                    }
+                    size -= offset;
+                    offset = 0;
+                    while (size < n) {
+                        // read some more data
+                        int nread = is.read(buf, size, buf.length - size);
+                        if (nread <= 0) {
+                            throw RInternalError.unimplemented("handle unexpected eof");
+                        }
+                        size += nread;
+                    }
+                }
+            }
+        }
+
+        /**
+         * This buffer is used under normal circumstances, i.e. when the read data blocks are
+         * smaller than the initial buffer. The ensureData method creates a special buffer for
+         * reading big chunks of data exceeding the default buffer.
+         */
+        private final Buffer defaultBuffer;
 
         private final WeakHashMap<String, WeakReference<String>> strings = RContext.getInstance().stringMap;
 
@@ -1071,91 +1158,66 @@ public class RSerialize {
             if (is instanceof PByteArrayInputStream) {
                 // we already have the data and we have read the beginning
                 PByteArrayInputStream pbis = (PByteArrayInputStream) is;
-                buf = pbis.getData();
-                size = pbis.getData().length;
-                offset = pbis.pos();
+                defaultBuffer = new Buffer(pbis.getData());
+                defaultBuffer.size = pbis.getData().length;
+                defaultBuffer.offset = pbis.pos();
             } else {
-                buf = new byte[READ_BUFFER_SIZE];
-                size = 0;
-                offset = 0;
+                defaultBuffer = new Buffer(new byte[READ_BUFFER_SIZE]);
+                defaultBuffer.size = 0;
+                defaultBuffer.offset = 0;
             }
         }
 
         @Override
         int readInt() throws IOException {
-            ensureData(4);
-            return ((buf[offset++] & 0xff) << 24 | (buf[offset++] & 0xff) << 16 | (buf[offset++] & 0xff) << 8 | (buf[offset++] & 0xff));
+            return ensureData(4).readInt();
         }
 
         @Override
         double readDouble() throws IOException {
-            ensureData(8);
-            long val = ((long) (buf[offset++] & 0xff) << 56 | (long) (buf[offset++] & 0xff) << 48 | (long) (buf[offset++] & 0xff) << 40 | (long) (buf[offset++] & 0xff) << 32 |
-                            (long) (buf[offset++] & 0xff) << 24 | (long) (buf[offset++] & 0xff) << 16 | (long) (buf[offset++] & 0xff) << 8 | buf[offset++] & 0xff);
-            return Double.longBitsToDouble(val);
+            return ensureData(8).readDouble();
         }
 
-        @SuppressWarnings("deprecation")
         @Override
         String readString(int len) throws IOException {
-            ensureData(len);
-            /*
-             * This fast path uses a cheaper String constructor if all incoming bytes are in the
-             * 0-127 range.
-             */
-            boolean fastEncode = true;
-            for (int i = 0; i < len; i++) {
-                byte b = buf[offset + i];
-                if (b < 0) {
-                    fastEncode = false;
-                    break;
-                }
-            }
-            String result;
-            if (fastEncode) {
-                result = new String(buf, 0, offset, len);
-            } else {
-                result = new String(buf, offset, len, StandardCharsets.UTF_8);
-            }
-            offset += len;
-            WeakReference<String> entry;
-            if ((entry = strings.get(result)) != null) {
-                String string = entry.get();
-                if (string != null) {
-                    return string;
-                }
-            }
-            strings.put(result, new WeakReference<>(result));
-            return result;
-        }
-
-        private void ensureData(int n) throws IOException {
-            if (n > buf.length) {
-                throw RInternalError.unimplemented("dynamically enlarge buffer");
-            }
-            if (offset + n > size) {
-                if (offset != size) {
-                    // copy end piece to beginning
-                    System.arraycopy(buf, offset, buf, 0, size - offset);
-                }
-                size -= offset;
-                offset = 0;
-                while (size < n) {
-                    // read some more data
-                    int nread = is.read(buf, size, buf.length - size);
-                    if (nread <= 0) {
-                        throw RInternalError.unimplemented("handle unexpected eof");
-                    }
-                    size += nread;
-                }
-            }
+            return ensureData(len).readString(len);
         }
 
         @Override
         void readRaw(byte[] data) throws IOException {
-            ensureData(data.length);
-            System.arraycopy(buf, offset, data, 0, data.length);
-            offset += data.length;
+            ensureData(data.length).readRaw(data);
+        }
+
+        private Buffer ensureData(int n) throws IOException {
+            Buffer usedBuffer;
+            if (n > defaultBuffer.buf.length) {
+                if (is instanceof PByteArrayInputStream) {
+                    // If the input stream is instance of PByteArrayInputStream, the buffer is
+                    // preloaded and thus no more data can be read beyond the current buffer.
+                    throw new IOException("Premature EOF");
+                }
+
+                // create an enlarged copy of the default buffer
+                byte[] enlargedBuf = new byte[n];
+                System.arraycopy(defaultBuffer.buf, defaultBuffer.offset, enlargedBuf, defaultBuffer.offset, defaultBuffer.size - defaultBuffer.offset);
+                usedBuffer = new Buffer(enlargedBuf);
+                usedBuffer.offset = defaultBuffer.offset;
+                usedBuffer.size = defaultBuffer.size;
+
+                // reset the default buffer
+                defaultBuffer.offset = defaultBuffer.size = 0;
+
+                usedBuffer.readData(n);
+                // The previous statement should entirely fill the temporary buffer.
+                // It is assumed that the caller will read n bytes, making the temporary buffer
+                // disposable. Next time, the default buffer will be used again, unless
+                // n > defaultBuffer.buf.length.
+                assert usedBuffer.size == n;
+            } else {
+                usedBuffer = defaultBuffer;
+                usedBuffer.readData(n);
+            }
+            return usedBuffer;
         }
     }
 
@@ -1763,10 +1825,14 @@ public class RSerialize {
                 if (ss != null) {
                     String path = RSource.getPathInternal(ss.getSource());
                     if (path != null) {
-                        REnvironment createSrcfile = RSrcref.createSrcfile(path);
-                        Object createLloc = RSrcref.createLloc(ss, createSrcfile);
-                        writePairListEntry(RRuntime.R_SRCREF, createLloc);
-                        writePairListEntry(RRuntime.R_SRCFILE, createSrcfile);
+                        // do this only for packages
+                        Path relPath = relativizeLibPath(Paths.get(path));
+                        if (relPath != null) {
+                            REnvironment createSrcfile = RSrcref.createSrcfile(relPath);
+                            Object createLloc = RSrcref.createLloc(ss, createSrcfile);
+                            writePairListEntry(RRuntime.R_SRCREF, createLloc);
+                            writePairListEntry(RRuntime.R_SRCFILE, createSrcfile);
+                        }
                     }
                 }
                 DynamicObject attributes = outAttrs.getExplicitAttributes();
@@ -2132,7 +2198,6 @@ public class RSerialize {
         public SourceSection getSourceReferenceAttributes() {
             return ss;
         }
-
     }
 
     /**
@@ -2434,18 +2499,36 @@ public class RSerialize {
         SourceSection ss = getFileSourceSection(syntaxElement);
         if (ss != null && serObj instanceof RAttributable) {
             String pathInternal = RSource.getPathInternal(ss.getSource());
-            RAttributable attributable = (RAttributable) serObj;
-            attributable.setAttr(RRuntime.R_SRCFILE, RSrcref.createSrcfile(pathInternal));
-            RList createBlockSrcrefs = RSrcref.createBlockSrcrefs(syntaxElement);
-            if (createBlockSrcrefs != null) {
-                attributable.setAttr(RRuntime.R_SRCREF, createBlockSrcrefs);
-                attributable.setAttr(RRuntime.R_WHOLE_SRCREF, RSrcref.createLloc(ss));
-            } else {
-                Object createLloc = RSrcref.createLloc(ss);
-                attributable.setAttr(RRuntime.R_SRCREF, createLloc);
-                attributable.setAttr(RRuntime.R_WHOLE_SRCREF, RSrcref.createLloc(ss));
+
+            // do this only for packages
+            Path relPath = relativizeLibPath(Paths.get(pathInternal));
+            if (relPath != null) {
+                RAttributable attributable = (RAttributable) serObj;
+                attributable.setAttr(RRuntime.R_SRCFILE, RSrcref.createSrcfile(relPath));
+                RList createBlockSrcrefs = RSrcref.createBlockSrcrefs(syntaxElement);
+                if (createBlockSrcrefs != null) {
+                    attributable.setAttr(RRuntime.R_SRCREF, createBlockSrcrefs);
+                    attributable.setAttr(RRuntime.R_WHOLE_SRCREF, RSrcref.createLloc(ss));
+                } else {
+                    Object createLloc = RSrcref.createLloc(ss);
+                    attributable.setAttr(RRuntime.R_SRCREF, createLloc);
+                    attributable.setAttr(RRuntime.R_WHOLE_SRCREF, RSrcref.createLloc(ss));
+                }
+            }
+        }
+    }
+
+    /**
+     * Relativizes the given path to its corresponding library path. If the given path is not a
+     * child of any library path, {@code null} will be returned.
+     */
+    private static Path relativizeLibPath(Path sourcePath) {
+        for (String libPath : RContext.getInstance().libraryPaths) {
+            if (sourcePath.startsWith(libPath)) {
+                return Paths.get(libPath).relativize(sourcePath);
             }
         }
+        return null;
     }
 
     private static SourceSection getFileSourceSection(RSyntaxElement syntaxElement) {
@@ -2492,14 +2575,12 @@ public class RSerialize {
      */
     private static final class PairlistDeserializer {
 
-        public static RFunction processFunction(Object car, Object cdr, Object tag, String functionName, String packageName) {
+        public static RFunction processFunction(Object car, Object cdr, REnvironment environment, String functionName, String packageName) {
             // car == arguments, cdr == body, tag == PairList(attributes, environment)
 
-            REnvironment environment = (REnvironment) tag;
-
             MaterializedFrame enclosingFrame = environment.getFrame();
-            RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(RSyntaxNode.LAZY_DEPARSE, processArguments(car), processBody(cdr), functionName);
 
+            RootCallTarget callTarget = RContext.getASTBuilder().rootFunction(RContext.getInstance().getLanguage(), RSyntaxNode.LAZY_DEPARSE, processArguments(car), processBody(cdr), functionName);
             FrameSlotChangeMonitor.initializeEnclosingFrame(callTarget.getRootNode().getFrameDescriptor(), enclosingFrame);
             RFunction func = RDataFactory.createFunction(functionName, packageName, callTarget, null, enclosingFrame);
 
@@ -2576,7 +2657,7 @@ public class RSerialize {
 
         private static RSyntaxNode processFunctionExpression(Object car, Object cdr, @SuppressWarnings("unused") Object tag) {
             // car == arguments, cdr == body
-            return RContext.getASTBuilder().function(RSyntaxNode.LAZY_DEPARSE, processArguments(car), processBody(cdr), null);
+            return RContext.getASTBuilder().function(RContext.getInstance().getLanguage(), RSyntaxNode.LAZY_DEPARSE, processArguments(car), processBody(cdr), null);
         }
 
         private static List<RCodeBuilder.Argument<RSyntaxNode>> processArguments(Object args) {
@@ -2663,25 +2744,63 @@ public class RSerialize {
                 assert srcfile instanceof REnvironment;
                 Source source = RSource.fromSrcfile((REnvironment) srcfile);
 
-                RList l = (RList) srcref;
+                RList blockSrcref = (RList) srcref;
                 RSyntaxElement[] syntaxArguments = elem.getSyntaxArguments();
-                assert syntaxArguments.length == l.getLength() - 1;
-
-                for (int i = 0; i < l.getLength(); i++) {
-                    Object dataAt = l.getDataAt(i);
-                    assert dataAt instanceof RAbstractIntVector;
-                    SourceSection ss = RSrcref.createSourceSection((RAbstractIntVector) dataAt, source);
-                    if (i == 0) {
-                        elem.setSourceSection(ss);
-                    } else {
-                        syntaxArguments[i - 1].setSourceSection(ss);
+                assert syntaxArguments.length == blockSrcref.getLength() - 1;
+
+                for (int i = 0; i < blockSrcref.getLength(); i++) {
+                    Object singleSrcref = blockSrcref.getDataAt(i);
+                    // could also be NULL
+                    if (singleSrcref instanceof RAbstractIntVector) {
+                        SourceSection ss = RSrcref.createSourceSection((RAbstractIntVector) singleSrcref, source);
+                        if (i == 0) {
+                            elem.setSourceSection(ss);
+                        } else {
+                            syntaxArguments[i - 1].setSourceSection(ss);
+                        }
                     }
                 }
             } catch (NoSuchFileException e) {
-                RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, "Missing source file: " + e.getMessage());
+                assert debugWarning("Missing source file: " + e.getMessage());
             } catch (IOException e) {
-                RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, "Cannot access source file: " + e.getMessage());
+                assert debugWarning("Cannot access source file: " + e.getMessage());
             }
         }
     }
+
+    private static boolean debugWarning(String message) {
+        RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, message);
+        return true;
+    }
+
+    /**
+     * Prepends the namespace's library location to the library paths in order to enable resolving
+     * of serialized relative paths.
+     *
+     * If a namespace is loaded, it remembers the path where it was loaded from. However, functions
+     * are loaded lazily and when deserializing them, there is no information about their origin.
+     * This method searches for the enclosing namespace environment (if available) and adds the
+     * origin path to the library paths.
+     *
+     * @param environment The function's environment.
+     * @return {@code true} if a path has been added, {@code false} otherwise.
+     */
+    private static boolean setupLibPath(REnvironment environment) {
+        REnvironment cur = environment;
+        while (cur != REnvironment.emptyEnv() && !cur.isNamespaceEnv()) {
+            cur = cur.getParent();
+        }
+        Object namespaceEnv = cur.get(REnvironment.NAMESPACE_KEY);
+        if (namespaceEnv != null) {
+            assert namespaceEnv instanceof REnvironment;
+            Object pathObj = ((REnvironment) namespaceEnv).get("path");
+            if (pathObj instanceof RAbstractStringVector) {
+                String path = ((RAbstractStringVector) pathObj).getDataAt(0);
+                Path libLoc = Paths.get(path).getParent();
+                RContext.getInstance().libraryPaths.add(0, libLoc.toString());
+                return true;
+            }
+        }
+        return false;
+    }
 }
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 e4bdde9ff45ac1d7c3b801028d1081d55d32fcf8..5ab18442c07ec3f80000e720722c5ae7bb63fc4a 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
@@ -27,12 +27,15 @@ import java.io.IOException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
+import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RSrcref.SrcrefFields;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 /**
@@ -98,7 +101,7 @@ public class RSource {
     public static Source fromFileName(String text, String path, boolean internal) throws URISyntaxException {
         File file = new File(path).getAbsoluteFile();
         URI uri = new URI("file://" + file.getAbsolutePath());
-        Source.Builder<RuntimeException, RuntimeException, RuntimeException> builder = Source.newBuilder(text).name(file.getName()).uri(uri).mimeType(RRuntime.R_APP_MIME);
+        Source.Builder<RuntimeException, RuntimeException, RuntimeException> builder = Source.newBuilder(file).content(text).uri(uri).mimeType(RRuntime.R_APP_MIME);
         if (internal) {
             builder.internal();
         }
@@ -163,7 +166,7 @@ public class RSource {
      * Create an (external) source from the file system path {@code path}.
      */
     public static Source fromFileName(String path, boolean internal) throws IOException {
-        Source.Builder<IOException, RuntimeException, RuntimeException> builder = Source.newBuilder(new File(path)).name(path).mimeType(RRuntime.R_APP_MIME);
+        Source.Builder<IOException, RuntimeException, RuntimeException> builder = Source.newBuilder(new File(path)).mimeType(RRuntime.R_APP_MIME);
         if (internal) {
             builder.internal();
         }
@@ -195,12 +198,30 @@ public class RSource {
      * Create an (external) source from an R srcfile ({@link RSrcref#createSrcfile(String)}).
      */
     public static Source fromSrcfile(REnvironment env) throws IOException {
-        Path filename = Paths.get((String) RRuntime.r2Java(env.get(SrcrefFields.filename.name())));
+        Path filename = Paths.get(getPath(env, SrcrefFields.filename.name()));
         if (filename.isAbsolute()) {
             return fromFileName(filename.toString(), false);
         }
-        Path wd = Paths.get((String) RRuntime.r2Java(env.get(SrcrefFields.wd.name())));
-        return fromFileName(wd.resolve(filename).toString(), false);
+        Path resolved = filename;
+        if (!filename.isAbsolute()) {
+            for (String libPath : RContext.getInstance().libraryPaths) {
+                resolved = Paths.get(libPath).resolve(filename);
+                if (Files.exists(resolved)) {
+                    break;
+                }
+            }
+        } else {
+            resolved = filename;
+        }
+        return fromFileName(resolved.toString(), false);
+    }
+
+    private static String getPath(REnvironment env, String name) {
+        Object o = env.get(name);
+        if (o instanceof RAbstractStringVector) {
+            return ((RAbstractStringVector) o).getDataAt(0);
+        }
+        return (String) o;
     }
 
     /**
@@ -260,5 +281,4 @@ public class RSource {
             return path;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java
index 63c82fd5e0eaa8dda66b6952f055c0f5c19d4de9..e8da4c611e3dab75d3cc60c6baacf2a4d9c51162 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java
@@ -79,7 +79,7 @@ public class RSrcref {
     }
 
     @TruffleBoundary
-    private static REnvironment createSrcfile(Path path) {
+    static REnvironment createSrcfile(Path path) {
         // A srcref is an environment
         REnvironment env = RContext.getInstance().srcfileEnvironments.get(path);
         if (env == null) {
@@ -159,6 +159,7 @@ public class RSrcref {
             try {
                 String pathStr = RSource.getPathInternal(source);
                 Path path = Paths.get(pathStr != null ? pathStr : "");
+
                 env.put(SrcrefFields.filename.name(), path.toString());
                 env.put(SrcrefFields.fixedNewlines.name(), RRuntime.LOGICAL_TRUE);
                 String[] lines = new String[source.getLineCount()];
@@ -223,15 +224,20 @@ public class RSrcref {
             int length = getLineStartOffset(source, srcrefVec.getDataAt(2)) + srcrefVec.getDataAt(3) - startIdx + 1;
             return source.createSection(startLine, startColumn, length);
         } catch (NoSuchFileException e) {
-            RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, "Missing source file: " + e.getMessage());
+            assert debugWarning("Missing source file: " + e.getMessage());
         } catch (IOException e) {
-            RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, "Cannot access source file: " + e.getMessage());
+            assert debugWarning("Cannot access source file: " + e.getMessage());
         } catch (IllegalArgumentException e) {
-            RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, "Invalid source reference: " + e.getMessage());
+            assert debugWarning("Invalid source reference: " + e.getMessage());
         }
         return RSourceSectionNode.LAZY_DEPARSE;
     }
 
+    private static boolean debugWarning(String message) {
+        RError.warning(RError.SHOW_CALLER, RError.Message.GENERIC, message);
+        return true;
+    }
+
     private static int getLineStartOffset(Source source, int lineNum) {
         try {
             return source.getLineStartOffset(lineNum);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java
deleted file mode 100644
index cdadca6a121452237e13e3aa3eb0059b9ac7c9d6..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * This material is distributed under the GNU General Public License
- * Version 2. You may review the terms of this license at
- * http://www.gnu.org/licenses/gpl-2.0.html
- *
- * Copyright (c) 1995-2015, The R Core Team
- * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.runtime;
-
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_ENVIRON;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_INIT_FILE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_READLINE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_RESTORE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_RESTORE_DATA;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_SAVE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.NO_SITE_FILE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.QUIET;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.RESTORE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SAVE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SILENT;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.SLAVE;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VANILLA;
-import static com.oracle.truffle.r.runtime.RCmdOptions.RCmdOption.VERBOSE;
-
-import com.oracle.truffle.r.runtime.context.RContext;
-
-/**
- * Defines startup parameters (that can be customized by embedding apps).
- */
-public class RStartParams {
-
-    public enum SA_TYPE {
-        NORESTORE(null),
-        RESTORE(null),
-        DEFAULT("default"),
-        NOSAVE("no"),
-        SAVE("yes"),
-        SAVEASK("ask"),
-        SUICIDE(null);
-
-        private String userName;
-
-        SA_TYPE(String userName) {
-            this.userName = userName;
-        }
-
-        public static final String[] SAVE_VALUES = new String[]{"yes", "no", "ask", "default"};
-
-        public String getUserName() {
-            return userName;
-        }
-
-        public static SA_TYPE fromString(String s) {
-            for (SA_TYPE t : values()) {
-                if (t.userName != null && t.userName.equals(s)) {
-                    return t;
-                }
-            }
-            return null;
-        }
-    }
-
-    private boolean quiet;
-    private boolean slave;
-    /**
-     * The setting of this value in GNU R is unusual and not simply based on the value of the
-     * --interactive option, so we do not check the option in
-     * {@link #RStartParams(RCmdOptions, boolean)}, but later in {@code RCommand}.
-     */
-    private boolean interactive = true;
-    private boolean verbose;
-    private boolean loadSiteFile = true;
-    private boolean loadInitFile = true;
-    private boolean debugInitFile;
-    private SA_TYPE restoreAction = SA_TYPE.RESTORE;
-    private SA_TYPE saveAction = SA_TYPE.SAVEASK;
-    private boolean noRenviron;
-    /**
-     * This is not a configurable option, but it is set on the command line and needs to be stored
-     * somewhere.
-     */
-    private boolean noReadline;
-
-    /**
-     * The result from parsing the command line options.
-     */
-    private final RCmdOptions cmdOptions;
-
-    /**
-     * Indicates that FastR is running embedded.
-     */
-    private boolean embedded;
-
-    public RStartParams(RCmdOptions options, boolean embedded) {
-        this.cmdOptions = options;
-        this.embedded = embedded;
-        if (options.getBoolean(VERBOSE)) {
-            this.verbose = true;
-        }
-        if (options.getBoolean(QUIET) || options.getBoolean(SILENT)) {
-            this.quiet = true;
-        }
-        if (options.getBoolean(NO_SITE_FILE)) {
-            this.loadSiteFile = false;
-        }
-        if (options.getBoolean(NO_INIT_FILE)) {
-            this.loadInitFile = false;
-        }
-        if (options.getBoolean(NO_ENVIRON)) {
-            this.noRenviron = true;
-        }
-        if (options.getBoolean(SAVE)) {
-            this.saveAction = SA_TYPE.SAVE;
-        }
-        if (options.getBoolean(NO_SAVE)) {
-            this.saveAction = SA_TYPE.NOSAVE;
-        }
-        if (options.getBoolean(RESTORE)) {
-            this.restoreAction = SA_TYPE.RESTORE;
-        }
-        if (options.getBoolean(NO_RESTORE) || options.getBoolean(NO_RESTORE_DATA)) {
-            this.restoreAction = SA_TYPE.NORESTORE;
-        }
-        if (options.getBoolean(NO_READLINE)) {
-            this.noReadline = true;
-        }
-        if (options.getBoolean(SLAVE)) {
-            this.slave = true;
-            this.quiet = true;
-            this.setSaveAction(SA_TYPE.NOSAVE);
-        }
-
-        if (options.getBoolean(VANILLA)) {
-            this.setSaveAction(SA_TYPE.NOSAVE);
-            this.noRenviron = true;
-            this.loadInitFile = false;
-            this.restoreAction = SA_TYPE.NORESTORE;
-        }
-    }
-
-    /**
-     * Only upcalled from native code.
-     */
-    @SuppressWarnings("unused")
-    private static void setParams(boolean quietA, boolean slaveA, boolean interactiveA, boolean verboseA, boolean loadSiteFileA,
-                    boolean loadInitFileA, boolean debugInitFileA, int restoreActionA,
-                    int saveActionA, boolean noRenvironA) {
-        RStartParams params = RContext.getInstance().getStartParams();
-        params.setQuiet(quietA);
-        params.setSlave(slaveA);
-        params.setInteractive(interactiveA);
-        params.setVerbose(verboseA);
-        params.setLoadSiteFile(loadSiteFileA);
-        params.setLoadInitFile(loadInitFileA);
-        params.setDebugInitFile(debugInitFileA);
-        params.setSaveAction(SA_TYPE.values()[saveActionA]);
-        params.setRestoreAction(SA_TYPE.values()[restoreActionA]);
-        params.setNoRenviron(noRenvironA);
-    }
-
-    public boolean getQuiet() {
-        return this.quiet;
-    }
-
-    public void setQuiet(boolean b) {
-        this.quiet = b;
-    }
-
-    public boolean getSlave() {
-        return slave;
-    }
-
-    public void setSlave(boolean b) {
-        this.slave = b;
-    }
-
-    public boolean getInteractive() {
-        return this.interactive;
-    }
-
-    public void setInteractive(boolean b) {
-        this.interactive = b;
-    }
-
-    public boolean getVerbose() {
-        return this.verbose;
-    }
-
-    public void setVerbose(boolean b) {
-        this.verbose = b;
-    }
-
-    public boolean getLoadSiteFile() {
-        return this.loadSiteFile;
-    }
-
-    public void setLoadSiteFile(boolean b) {
-        this.loadSiteFile = b;
-    }
-
-    public boolean getLoadInitFile() {
-        return this.loadInitFile;
-    }
-
-    public void setLoadInitFile(boolean b) {
-        this.loadInitFile = b;
-    }
-
-    public boolean getDebugInitFile() {
-        return this.debugInitFile;
-    }
-
-    public void setDebugInitFile(boolean b) {
-        this.debugInitFile = b;
-    }
-
-    public SA_TYPE getRestoreAction() {
-        return this.restoreAction;
-    }
-
-    public void setRestoreAction(SA_TYPE a) {
-        this.restoreAction = a;
-    }
-
-    public SA_TYPE getSaveAction() {
-        return this.saveAction;
-    }
-
-    public void setSaveAction(SA_TYPE a) {
-        this.saveAction = a;
-    }
-
-    public boolean getNoRenviron() {
-        return this.noRenviron;
-    }
-
-    public void setNoRenviron(boolean b) {
-        this.noRenviron = b;
-    }
-
-    public boolean getNoReadline() {
-        return this.noReadline;
-    }
-
-    public RCmdOptions getRCmdOptions() {
-        return cmdOptions;
-    }
-
-    public String[] getArguments() {
-        return cmdOptions.getArguments();
-    }
-
-    public void setEmbedded() {
-        this.embedded = true;
-    }
-
-    public boolean getEmbedded() {
-        return embedded;
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
index aa4108bd0360cd282c4e4cc2b35a642c0a56bba0..8886dac03caaee2f81ab4cc88f4587997476d035 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSubstitute.java
@@ -28,6 +28,7 @@ import java.util.Arrays;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RMissing;
@@ -87,7 +88,7 @@ public class RSubstitute {
      * <li>..., replace by contents of ... (if bound)</li>
      * </ul>
      */
-    private static <T> T substitute(RCodeBuilder<T> builder, RSyntaxElement original, REnvironment callEnv) {
+    private static <T> T substitute(RCodeBuilder<T> builder, RSyntaxElement original, REnvironment callEnv, TruffleRLanguage language) {
         return new RSyntaxVisitor<T>() {
 
             REnvironment env = callEnv;
@@ -178,13 +179,13 @@ public class RSubstitute {
             @Override
             protected T visit(RSyntaxFunction element) {
                 ArrayList<Argument<T>> params = createArguments(element.getSyntaxSignature(), element.getSyntaxArgumentDefaults());
-                return builder.function(RSyntaxNode.LAZY_DEPARSE, params, accept(element.getSyntaxBody()), element.getSyntaxDebugName());
+                return builder.function(language, RSyntaxNode.LAZY_DEPARSE, params, accept(element.getSyntaxBody()), element.getSyntaxDebugName());
             }
         }.accept(original);
     }
 
     @TruffleBoundary
-    public static RSyntaxNode substitute(REnvironment env, RBaseNode node) {
-        return substitute(RContext.getASTBuilder(), node.asRSyntaxNode(), env);
+    public static RSyntaxNode substitute(REnvironment env, RBaseNode node, TruffleRLanguage language) {
+        return substitute(RContext.getASTBuilder(), node.asRSyntaxNode(), env, language);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
index c4d03652bf2589339d29122b77bc67cd6709bc7d..58096f6025f86d97235ed5018532a3b3f1ada2e3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java
@@ -25,6 +25,7 @@ public enum RType {
     Logical("logical", 1),
     Integer("integer", 2),
     Double("double", "numeric", 3),
+    Numeric("numeric", 3),
     Complex("complex", 4),
     Character("character", 5),
     List("list", 6),
@@ -112,6 +113,15 @@ public enum RType {
     }
 
     public static RType fromMode(String mode) {
+        return fromMode(mode, false);
+    }
+
+    /**
+     * @param includeNumeric if {@code true}, then the method returns {@link #Numeric} for string
+     *            "numeric". This may be useful for callers that need to distinguish "numeric" and
+     *            "double" modes.
+     */
+    public static RType fromMode(String mode, boolean includeNumeric) {
         switch (mode) {
             case "any":
                 return Any;
@@ -126,6 +136,7 @@ public enum RType {
             case "integer":
                 return Integer;
             case "numeric":
+                return includeNumeric ? Numeric : Double;
             case "double":
                 return Double;
             case "complex":
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionInfo.java
index a75cadee75a33b68a9af0c30ef6fee1b9f13ad6b..3fd2193addef0b83a8f320f2a1c5793c661fda6f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RVersionInfo.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime;
 
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
 import com.oracle.truffle.r.runtime.ffi.BaseRFFI.UtsName;
 
@@ -40,6 +41,7 @@ public enum RVersionInfo {
     Day(RVersionNumber.RELEASE_DAY),
     SvnRev("svn rev", null),
     Language("R"),
+    Engine("FastR"),
     VersionString("version.string", RVersionNumber.VERSION_STRING);
     // @formatter:on
 
@@ -103,7 +105,11 @@ public enum RVersionInfo {
                                     data.value = "x86_64-unknown-linux-gnu";
                                 }
                             } else if (osName.toLowerCase().equals("sunos")) {
-                                data.value = "sparc-sun-solaris2.11";
+                                if (Arch.value.equals("sparcv9")) {
+                                    data.value = "sparcv9-sun-solaris2.11";
+                                } else {
+                                    data.value = "x86_64-pc-solaris2.11";
+                                }
                             } else {
                                 data.value = Arch.value + "-" + vendor + "-" + OS.value;
                             }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.java
index 519a11a0231f4c3b5d4a622b7bf1e6bb195ef8e6..d0be846c39ceb35722674b2e739774f67a6dddb3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RegExp.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
@@ -68,14 +68,33 @@ public class RegExp {
          * predefined classes like "[:alpha:]" with "\p{Alpha}".
          */
         boolean withinCharClass = false;
+        int parensNesting = 0;
         int i = 0;
         while (i < result.length()) {
             switch (result.charAt(i)) {
+                case '(':
+                    if (withinCharClass) {
+                        result = result.substring(0, i) + '\\' + result.substring(i);
+                        i++; // skip the newly inserted '\\'
+                    } else {
+                        parensNesting++;
+                    }
+                    break;
+                case ')':
+                    if (withinCharClass || parensNesting == 0) {
+                        result = result.substring(0, i) + '\\' + result.substring(i);
+                        i++; // skip the newly inserted '\\'
+                    } else {
+                        parensNesting--;
+                    }
+                    break;
                 case '\\':
                     if (withinCharClass) {
                         result = result.substring(0, i) + '\\' + result.substring(i);
+                        i++; // skip the newly inserted '\\'
+                    } else {
+                        i++; // skip the next character
                     }
-                    i++;
                     break;
                 case '[':
                     if (withinCharClass) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java
index f785535b8eb13581f3a81a38210827688cb6819e..ec6a3714d3ed527161e09e758bb282854b299ca4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ResourceHandlerFactory.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime;
 
 import java.io.InputStream;
 import java.net.URL;
+import java.util.Map;
 
 public abstract class ResourceHandlerFactory {
     /**
@@ -49,7 +50,7 @@ public abstract class ResourceHandlerFactory {
          * Return the contents of all "R" files (ending with ".r" or ".R") relative to
          * {@code accessor} and {@code pkgname/R}. I.e. essentially a directory search.
          */
-        String[] getRFiles(Class<?> accessor, String pkgName);
+        Map<String, String> getRFiles(Class<?> accessor, String pkgName);
     }
 
     static {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
index 822fd6f26e4052502405b6e19ed7b208469034ce..3c675356930cf83ae7d8788dd8b20904a2c2e56e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/TempPathName.java
@@ -87,8 +87,7 @@ public class TempPathName implements RContext.ContextState {
     }
 
     public static String tempDirPath() {
-        String result = RContext.getInstance().stateTempPath.tempDirPath;
-        return result;
+        return RContext.getInstance().stateTempPath.tempDirPath;
     }
 
     public static TempPathName newContextState() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
index 5d3c31feba257afdbfd70dbc0da57b7c367a7f19..f44a3cfa50fda6a71b4f6d89a442bfbc7e241c2c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java
@@ -39,7 +39,6 @@ import java.util.function.Function;
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleRuntime;
 import com.oracle.truffle.api.frame.Frame;
@@ -48,15 +47,13 @@ import com.oracle.truffle.api.frame.FrameInstance;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.FrameInstanceVisitor;
 import com.oracle.truffle.api.frame.FrameSlot;
-import com.oracle.truffle.api.nodes.GraphPrintVisitor;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPairList;
@@ -112,16 +109,6 @@ public final class Utils {
         return result;
     }
 
-    public static void dumpFunction(String groupName, RFunction function) {
-        GraphPrintVisitor graphPrinter = new GraphPrintVisitor();
-        RootCallTarget callTarget = function.getTarget();
-        if (callTarget != null) {
-            graphPrinter.beginGroup(groupName);
-            graphPrinter.beginGraph(RRuntime.toString(function)).visit(callTarget.getRootNode());
-        }
-        graphPrinter.printToNetwork(true);
-    }
-
     /**
      * Locates a resource that is used within the implementation, e.g. a file of R code, and returns
      * a {@link Source} instance that represents it. Since the location may vary between
@@ -191,7 +178,15 @@ public final class Utils {
      */
     public static RuntimeException rSuicide(String msg) {
         if (RInterfaceCallbacks.R_Suicide.isOverridden()) {
-            RFFIFactory.getRFFI().getREmbedRFFI().suicide(msg);
+            RFFIFactory.getREmbedRFFI().suicide(msg);
+        }
+        throw rSuicideDefault(msg);
+    }
+
+    public static RuntimeException rSuicide(Throwable cause, String msg) {
+        cause.printStackTrace();
+        if (RInterfaceCallbacks.R_Suicide.isOverridden()) {
+            RFFIFactory.getREmbedRFFI().suicide(msg);
         }
         throw rSuicideDefault(msg);
     }
@@ -204,7 +199,7 @@ public final class Utils {
      */
     public static RuntimeException rSuicideDefault(String msg) {
         System.err.println("FastR unexpected failure: " + msg);
-        throw new ExitException(2);
+        throw new ExitException(2, false);
     }
 
     /**
@@ -324,7 +319,11 @@ public final class Utils {
                         Path truePath = currentPath.resolve(p);
                         if (keepRelative) {
                             // relativize it (it was relative to start with)
-                            return currentPath.relativize(truePath).toString();
+                            if (".".equals(path) || "..".equals(path)) {
+                                return path;
+                            } else {
+                                return currentPath.relativize(truePath).toString();
+                            }
                         } else {
                             return truePath.toString();
                         }
@@ -640,10 +639,9 @@ public final class Utils {
             StdConnections.getStderr().writeString(s, nl);
         } catch (IOException ex) {
             // Very unlikely
-            ConsoleHandler consoleHandler = RContext.getInstance().getConsoleHandler();
-            consoleHandler.printErrorln("Error writing to stderr: " + ex.getMessage());
-            consoleHandler.printErrorln(s);
-
+            ConsoleIO console = RContext.getInstance().getConsole();
+            console.printErrorln("Error writing to stderr: " + ex.getMessage());
+            console.printErrorln(s);
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBehavior.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBehavior.java
index 47f5423505d2d38e4d39ac2c2ff1140985989275..58bc0c0db2c88b6a8e77bc09f0620733ee17ff6d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBehavior.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBehavior.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -33,7 +33,11 @@ public enum RBehavior {
      * This builtin always returns the same result or raises the same error if it is called with the
      * same arguments. It cannot depend on any external state, on the frame or on IO input.
      */
-    PURE,
+    PURE_ARITHMETIC(true), // the length of the result is the maximum of all inputs
+    PURE_SUMMARY(true), // the length of the result is exactly one
+    PURE_SUBSET(true), // the length of the result depends on the inputs
+    PURE_SUBSCRIPT(true), // the length of the result is exactly one
+    PURE(true), // unknown result length
     /**
      * This builtin performs IO operations.
      */
@@ -64,5 +68,19 @@ public enum RBehavior {
      * This builtin has arbitrary effects on the global state, on IO components, the frame, and the
      * AST itself. It also depends on the global state, IO and the frame.
      */
-    COMPLEX
+    COMPLEX;
+
+    private final boolean pure;
+
+    RBehavior() {
+        this(false);
+    }
+
+    RBehavior(boolean pure) {
+        this.pure = pure;
+    }
+
+    public boolean isPure() {
+        return pure;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
index 925e003fe787f28ce2f02cdcdd555db486ceb6ad..07ede76bbdf97724f7aa50ca9aa2e717b3d552c4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinDescriptor.java
@@ -35,6 +35,7 @@ public abstract class RBuiltinDescriptor {
     private static int primitiveMethodCount;
 
     private final String name;
+    private final Class<?> builtinMetaClass;
     private final Class<?> builtinNodeClass;
     private final RVisibility visibility;
     private final String[] aliases;
@@ -51,10 +52,12 @@ public abstract class RBuiltinDescriptor {
     private final int primitiveMethodIndex;
     @CompilationFinal(dimensions = 1) private final boolean[] evaluatesArgument;
 
-    public RBuiltinDescriptor(String name, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature, int[] nonEvalArgs, boolean splitCaller,
+    public RBuiltinDescriptor(String name, Class<?> builtinMetaClass, Class<?> builtinNodeClass, RVisibility visibility, String[] aliases, RBuiltinKind kind, ArgumentsSignature signature,
+                    int[] nonEvalArgs, boolean splitCaller,
                     boolean alwaysSplit, RDispatch dispatch, String genericName, RBehavior behavior, RSpecialFactory specialCall) {
         this.specialCall = specialCall;
         this.name = name.intern();
+        this.builtinMetaClass = builtinMetaClass;
         this.builtinNodeClass = builtinNodeClass;
         this.visibility = visibility;
         this.aliases = aliases;
@@ -132,6 +135,10 @@ public abstract class RBuiltinDescriptor {
         return visibility;
     }
 
+    public Class<?> getBuiltinMetaClass() {
+        return builtinMetaClass;
+    }
+
     public Class<?> getBuiltinNodeClass() {
         return builtinNodeClass;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinLookup.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinLookup.java
index 1102940fb2a0c858c01e52e6dc0a4399bc3a30f1..917474088ff333d3e06087cc9fb70b78c8033796 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinLookup.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/builtins/RBuiltinLookup.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
@@ -22,13 +22,14 @@
  */
 package com.oracle.truffle.r.runtime.builtins;
 
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RFunction;
 
 public interface RBuiltinLookup {
 
     boolean isPrimitiveBuiltin(String name);
 
-    RFunction lookupBuiltin(String methodName);
+    RFunction lookupBuiltin(TruffleRLanguage language, String methodName);
 
     RBuiltinDescriptor lookupBuiltinDescriptor(String methodName);
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java
index f5d8cd180262a621df563f2311e3ece0121fca12..51d36e909dabb82f39817d14b503d26055b79999 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ChannelConnections.java
@@ -69,7 +69,6 @@ public class ChannelConnections {
         public String getSummaryDescription() {
             return description;
         }
-
     }
 
     private static class ChannelReadWriteRConnection extends DelegateReadWriteRConnection {
@@ -90,7 +89,6 @@ public class ChannelConnections {
         public boolean isSeekable() {
             return false;
         }
-
     }
 
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
index d43eeb8e783e736fc98265c4972b04c6e6cd8f68..79911c2ea1a89f89c83829060c0a7021336f1895 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateRConnection.java
@@ -54,26 +54,40 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
  * </p>
  */
 abstract class DelegateRConnection implements RConnection, ByteChannel {
-    private static final int DEFAULT_CACHE_SIZE = 16 * 1024;
+    public static final int DEFAULT_CACHE_SIZE = 16 * 1024;
     protected final BaseRConnection base;
     private final ByteBuffer cache;
+    private final boolean readCache;
 
     DelegateRConnection(BaseRConnection base) {
-        this(base, DEFAULT_CACHE_SIZE);
+        this(base, DEFAULT_CACHE_SIZE, true);
     }
 
-    DelegateRConnection(BaseRConnection base, int cacheSize) {
+    DelegateRConnection(BaseRConnection base, int cacheSize, boolean readCache) {
         this.base = Objects.requireNonNull(base);
+        this.readCache = readCache;
 
         if (cacheSize > 0) {
             cache = ByteBuffer.allocate(cacheSize);
-            // indicate that there are no remaining bytes in the buffer
-            cache.flip();
+
+            // indicate that there are no remaining bytes in the buffer to read
+            if (readCache) {
+                cache.flip();
+            }
         } else {
             cache = null;
         }
     }
 
+    private static int transfer(ByteBuffer from, ByteBuffer to) {
+        int nbytes = Math.min(to.remaining(), from.remaining());
+        if (nbytes > 0) {
+            to.put(from.array(), from.arrayOffset() + from.position(), nbytes);
+            from.position(from.position() + nbytes);
+        }
+        return nbytes;
+    }
+
     @Override
     public int getDescriptor() {
         return base.getDescriptor();
@@ -438,7 +452,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
     @Override
     @TruffleBoundary
     public int read(ByteBuffer dst) throws IOException {
-        if (cache != null) {
+        if (readCache && cache != null) {
             final int bytesRequested = dst.remaining();
             int totalBytesRead = 0;
             int bytesToRead = 0;
@@ -459,7 +473,19 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
     @Override
     @TruffleBoundary
     public int write(ByteBuffer src) throws IOException {
-        return getChannel().write(src);
+        if (!readCache && cache != null) {
+            int total = 0;
+            while (src.hasRemaining()) {
+                total += transfer(src, cache);
+                if (!cache.hasRemaining()) {
+                    flush();
+                }
+            }
+            return total;
+        } else {
+            invalidateCache();
+            return getChannel().write(src);
+        }
     }
 
     /**
@@ -471,7 +497,7 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
      * </p>
      */
     protected int readInternal() throws IOException {
-        if (cache != null) {
+        if (readCache && cache != null) {
             ensureDataAvailable(1);
             if (!cache.hasRemaining()) {
                 return -1;
@@ -567,7 +593,11 @@ abstract class DelegateRConnection implements RConnection, ByteChannel {
 
     @Override
     public void flush() throws IOException {
-        // nothing to do for channels
+        if (!readCache && cache != null) {
+            cache.flip();
+            getChannel().write(cache);
+            cache.clear();
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
index d4b11c2d5723c037e1839c5f26b05f31b6e98bb5..fd7aaead631d1995c9f39abf27596f534f83eb77 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadRConnection.java
@@ -38,7 +38,7 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
     }
 
     protected DelegateReadRConnection(BaseRConnection base, int cacheSize) {
-        super(base, cacheSize);
+        super(base, cacheSize, true);
     }
 
     @Override
@@ -80,5 +80,4 @@ public abstract class DelegateReadRConnection extends DelegateRConnection {
     public void truncate() {
         throw RError.error(RError.SHOW_CALLER, RError.Message.TRUNCATE_ONLY_WRITE_CONNECTION);
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
index c445251b02495f80207f0c2507bcc046e64eadb9..b9b2869ecea91be4e65caad3d50c835aa2bd434f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateReadWriteRConnection.java
@@ -31,7 +31,6 @@ abstract class DelegateReadWriteRConnection extends DelegateRConnection {
     }
 
     protected DelegateReadWriteRConnection(BaseRConnection base, int cacheSize) {
-        super(base, cacheSize);
+        super(base, cacheSize, true);
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
index 16503501a0914f0e299d5e7c06f1eda99d0d4e88..f436a0a2f12b44520dafa0c0a63caff6467bde1a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/DelegateWriteRConnection.java
@@ -33,7 +33,11 @@ import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 abstract class DelegateWriteRConnection extends DelegateRConnection {
 
     protected DelegateWriteRConnection(BaseRConnection base) {
-        super(base, 0);
+        super(base, 0, false);
+    }
+
+    protected DelegateWriteRConnection(BaseRConnection base, int cacheSize) {
+        super(base, cacheSize, false);
     }
 
     @Override
@@ -75,4 +79,10 @@ abstract class DelegateWriteRConnection extends DelegateRConnection {
     public boolean canWrite() {
         return true;
     }
+
+    @Override
+    public void close() throws IOException {
+        flush();
+        super.close();
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
index ed9b67884e082b0043be6c6457567737bc1aeb92..4c8dceb0b58791ae3f0d68932cba66d12015cb5b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FifoConnections.java
@@ -182,7 +182,6 @@ public class FifoConnections {
         public ByteChannel getChannel() {
             return raf.getChannel();
         }
-
     }
 
     static class FifoReadNonBlockingRConnection extends DelegateReadRConnection {
@@ -240,7 +239,6 @@ public class FifoConnections {
         public boolean isSeekable() {
             return false;
         }
-
     }
 
     private static final String MKFIFO_ERROR_FILE_EXISTS = "File exists";
@@ -295,5 +293,4 @@ public class FifoConnections {
             // fall through
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
index b14529c998dfd7df4fa202a0df4e432724a99b7c..d7b01f19cd0c90c3661f8388e1a2937d64a062c5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/FileConnections.java
@@ -287,7 +287,6 @@ public class FileConnections {
         public ByteChannel getChannel() {
             return channel;
         }
-
     }
 
     static class FileReadTextRConnection extends FileReadBinaryRConnection {
@@ -324,7 +323,7 @@ public class FileConnections {
         private final FileChannel channel;
 
         FileWriteBinaryConnection(BasePathRConnection base, boolean append) throws IOException {
-            super(base);
+            super(base, 0);
             List<OpenOption> opts = new ArrayList<>();
             opts.add(StandardOpenOption.WRITE);
             opts.add(StandardOpenOption.CREATE);
@@ -355,7 +354,6 @@ public class FileConnections {
         public void truncate() throws IOException {
             channel.truncate(channel.position());
         }
-
     }
 
     private static class FileReadWriteTextConnection extends DelegateReadWriteRConnection {
@@ -525,7 +523,6 @@ public class FileConnections {
             // different as expected.
             writeOffset = channel.position();
         }
-
     }
 
     private static class FileReadWriteBinaryConnection extends DelegateReadWriteRConnection {
@@ -683,7 +680,6 @@ public class FileConnections {
             // different as expected.
             writeOffset = raf.getFilePointer();
         }
-
     }
 
     private static class CompressedInputRConnection extends DelegateReadRConnection {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
index 8aa871b1b29f22629d12022f1a37493da5a01970..fef080a05879e9106bf014aa943c7b8ab1641edf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/PipeConnections.java
@@ -181,9 +181,7 @@ public class PipeConnections {
             public int write(ByteBuffer src) throws IOException {
                 return wchannel.write(src);
             }
-
         }
 
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
index 3abb2e1bca5d47ddbe3ca820d2d6bd4952a22cde..37d8910f759ca434313200799bec0d5ac528e010 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RawConnections.java
@@ -111,7 +111,6 @@ public class RawConnections {
             }
             return origPos;
         }
-
     }
 
     static class RawReadRConnection extends DelegateReadRConnection {
@@ -235,5 +234,4 @@ public class RawConnections {
             channel.truncate(channel.position());
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
index 7476dc54267c8089785ea1fdb99c401363d34367..83461e10f336712018a71f5124a8946ef2c76a94 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/SeekableMemoryByteChannel.java
@@ -243,7 +243,6 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
         public int read() throws IOException {
             return SeekableMemoryByteChannel.this.read();
         }
-
     }
 
     public OutputStream getOutputStream() {
@@ -277,5 +276,4 @@ public class SeekableMemoryByteChannel implements SeekableByteChannel {
             SeekableMemoryByteChannel.this.write(ByteBuffer.wrap(b, off, len));
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index 6150dc902b2cf11456b38457c64e489a62bf8f12..fdbf611d927d1a4819af8be9f4888742857d1bd5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -34,8 +34,8 @@ import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 
 public class StdConnections {
@@ -63,11 +63,11 @@ public class StdConnections {
 
         @Override
         public RContext.ContextState initialize(RContext context) {
-            ConsoleHandler consoleHandler = context.getConsoleHandler();
+            ConsoleIO console = context.getConsole();
             try {
-                stdin = new StdinConnection();
-                stdout = new StdoutConnection(consoleHandler);
-                stderr = new StderrConnection(consoleHandler);
+                stdin = new StdinConnection(console);
+                stdout = new StdoutConnection(console);
+                stderr = new StderrConnection(console);
             } catch (IOException ex) {
                 throw Utils.rSuicide("failed to open stdconnections:");
             }
@@ -178,8 +178,11 @@ public class StdConnections {
 
     private static class StdinConnection extends StdConnection {
 
-        StdinConnection() throws IOException {
+        private final ConsoleIO console;
+
+        StdinConnection(ConsoleIO console) throws IOException {
             super(AbstractOpenMode.Read, 0);
+            this.console = console;
         }
 
         @Override
@@ -200,7 +203,6 @@ public class StdConnections {
         @Override
         @TruffleBoundary
         public String[] readLinesInternal(int n, boolean warn, boolean skipNul) throws IOException {
-            ConsoleHandler console = RContext.getInstance().getConsoleHandler();
             ArrayList<String> lines = new ArrayList<>();
             String line;
             while ((line = console.readLine()) != null) {
@@ -221,11 +223,11 @@ public class StdConnections {
     }
 
     private abstract static class StdoutputAdapter extends StdConnection {
-        protected final ConsoleHandler consoleHandler;
+        protected final ConsoleIO console;
 
-        StdoutputAdapter(int index, ConsoleHandler consoleHandler) throws IOException {
+        StdoutputAdapter(int index, ConsoleIO console) throws IOException {
             super(AbstractOpenMode.Write, index);
-            this.consoleHandler = consoleHandler;
+            this.console = console;
             this.opened = true;
         }
 
@@ -247,8 +249,8 @@ public class StdConnections {
 
     private static class StdoutConnection extends StdoutputAdapter {
 
-        StdoutConnection(ConsoleHandler consoleHandler) throws IOException {
-            super(1, consoleHandler);
+        StdoutConnection(ConsoleIO console) throws IOException {
+            super(1, console);
         }
 
         int numDiversions() {
@@ -292,9 +294,9 @@ public class StdConnections {
             ContextStateImpl state = getContextState();
             if (state.top < 0) {
                 if (nl) {
-                    consoleHandler.println(s);
+                    console.println(s);
                 } else {
-                    consoleHandler.print(s);
+                    console.print(s);
                 }
             } else {
                 getContextState().diversions[state.top].conn.writeString(s, nl);
@@ -327,8 +329,8 @@ public class StdConnections {
     private static class StderrConnection extends StdoutputAdapter {
         RConnection diversion;
 
-        StderrConnection(ConsoleHandler consoleHandler) throws IOException {
-            super(2, consoleHandler);
+        StderrConnection(ConsoleIO console) throws IOException {
+            super(2, console);
         }
 
         void divertErr(RConnection conn) {
@@ -379,9 +381,9 @@ public class StdConnections {
                 diversion.writeString(s, nl);
             } else {
                 if (nl) {
-                    consoleHandler.printErrorln(s);
+                    console.printErrorln(s);
                 } else {
-                    consoleHandler.printError(s);
+                    console.printError(s);
                 }
             }
         }
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/ChildContextInfo.java
similarity index 57%
rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ChildContextInfo.java
index 5a680554e95df9da0769f3809a8e8aedc9e2dff5..bdcd6c61d363601afc703ff79f0609aa8fd7202d 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/ChildContextInfo.java
@@ -22,30 +22,53 @@
  */
 package com.oracle.truffle.r.runtime.context;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.util.TimeZone;
 import java.util.concurrent.Executor;
 import java.util.concurrent.Executors;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import com.oracle.truffle.api.TruffleContext;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.api.vm.PolyglotEngine.Builder;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RStartParams;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 
+final class ConsoleHandlerInputStream extends InputStream {
+    @Override
+    public int read() throws IOException {
+        return 0;
+    }
+}
+
+final class ConsoleHandlerOutputStream extends OutputStream {
+
+    @Override
+    public void write(int b) throws IOException {
+
+    }
+}
+
 /**
- * Represents custom initialization state for an R instance.
+ * Represents custom initialization state for a "spawned" R instance, that is one created by, e.g.,
+ * {@code .fastr.context.eval} and test contexts. In particular there is no {@link ChildContextInfo}
+ * for the initial context, whether created by the {@code R/RScript} command or whether invoked from
+ * another language.
+ *
+ * There are some legacy functions that still use {@link PolyglotEngine} but the new way is to use
+ * {@link TruffleContext}.
  *
- * Use {@link #createVM()} to apply this information to a newly-built {@link PolyglotEngine}
- * instance (it will be stored in the "fastrContextInfo" global symbol).
  */
-public final class ContextInfo {
+public final class ChildContextInfo {
     static final String CONFIG_KEY = "fastrContextInfo";
 
-    private static final AtomicInteger contextInfoIds = new AtomicInteger();
-    private static final AtomicInteger multiSlotInds = new AtomicInteger(-1);
+    static final AtomicInteger contextInfoIds = new AtomicInteger();
+    static final AtomicInteger multiSlotInds = new AtomicInteger(-1);
 
     private final RStartParams startParams;
     private final String[] env;
@@ -57,18 +80,24 @@ public final class ContextInfo {
      * the RContext.threadLocalContext to the parent.
      */
     private final RContext parent;
-    private final ConsoleHandler consoleHandler;
+    private final InputStream stdin;
+    private final OutputStream stdout;
+    private final OutputStream stderr;
     private final int id;
     private final int multiSlotInd;
+    private TruffleContext truffleContext;
     private PolyglotEngine vm;
     public Executor executor;
 
-    private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone, int id, int multiSlotInd) {
+    private ChildContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr, TimeZone systemTimeZone, int id,
+                    int multiSlotInd) {
         this.startParams = startParams;
         this.env = env;
         this.kind = kind;
         this.parent = parent;
-        this.consoleHandler = consoleHandler;
+        this.stdin = stdin;
+        this.stdout = stdout;
+        this.stderr = stderr;
         this.systemTimeZone = systemTimeZone;
         this.multiSlotInd = multiSlotInd;
         this.id = id;
@@ -86,26 +115,29 @@ public final class ContextInfo {
         multiSlotInds.set(0); // to account for primordial context
     }
 
+    public TruffleContext createTruffleContext() {
+        this.truffleContext = RContext.getInstance().getEnv().newContextBuilder().config("parentContext", parent.getVM()).config(CONFIG_KEY, this).build();
+        return this.truffleContext;
+    }
+
+    public TruffleContext createVM(ChildContextInfo childContextInfo) {
+        this.truffleContext = RContext.getInstance().getEnv().newContextBuilder().config("parentContext", parent.getVM()).config(CONFIG_KEY, this).build();
+        return this.truffleContext;
+    }
+
     public PolyglotEngine createVM() {
         Builder builder = PolyglotEngine.newBuilder();
-        if (startParams.getInteractive()) {
+        if (startParams.isInteractive()) {
             this.executor = Executors.newSingleThreadExecutor();
             builder = builder.executor(executor);
         }
-        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build();
+        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).setIn(stdin).setOut(stdout).setErr(stderr).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;
     }
 
     public PolyglotEngine createVM(PolyglotEngine.Builder builder) {
-        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build();
+        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).setIn(stdin).setOut(stdout).setErr(stderr).build();
         this.vm = newVM;
         return newVM;
     }
@@ -113,15 +145,14 @@ public final class ContextInfo {
     /**
      * Create a context configuration object.
      *
-     * @param startParams the start parameters passed this R session
-     * @param env TODO
+     * @param startParams the start parameters passed this spawned R session
      * @param kind defines the degree to which this context shares base and package environments
      *            with its parent
      * @param parent if non-null {@code null}, the parent creating the context
-     * @param consoleHandler a {@link ConsoleHandler} for output
      * @param systemTimeZone the system's time zone
      */
-    public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler, TimeZone systemTimeZone) {
+    public static ChildContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr,
+                    TimeZone systemTimeZone) {
         int id = contextInfoIds.incrementAndGet();
         int multiSlotInd = multiSlotInds.get();
         if (kind == ContextKind.SHARE_ALL || kind == ContextKind.SHARE_NOTHING) {
@@ -133,11 +164,11 @@ public final class ContextInfo {
             throw RInternalError.shouldNotReachHere();
         }
         assert kind != ContextKind.SHARE_PARENT_RW || (kind == ContextKind.SHARE_PARENT_RW && parent.getKind() == ContextKind.SHARE_NOTHING && parent.getMultiSlotInd() == 0);
-        return new ContextInfo(startParams, env, kind, parent, consoleHandler, systemTimeZone, id, kind == ContextKind.SHARE_PARENT_RW ? 0 : multiSlotInd);
+        return new ChildContextInfo(startParams, env, kind, parent, stdin, stdout, stderr, systemTimeZone, id, kind == ContextKind.SHARE_PARENT_RW ? 0 : multiSlotInd);
     }
 
-    public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler) {
-        return create(startParams, env, kind, parent, consoleHandler, TimeZone.getDefault());
+    public static ChildContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr) {
+        return create(startParams, env, kind, parent, stdin, stdout, stderr, TimeZone.getDefault());
     }
 
     /**
@@ -148,11 +179,10 @@ public final class ContextInfo {
      * @param kind defines the degree to which this context shares base and package environments
      *            with its parent
      * @param parent if non-null {@code null}, the parent creating the context
-     * @param consoleHandler a {@link ConsoleHandler} for output
      */
-    public static ContextInfo createNoRestore(Client client, String[] env, ContextKind kind, RContext parent, ConsoleHandler consoleHandler) {
-        RStartParams params = new RStartParams(RCmdOptions.parseArguments(client, new String[]{"--no-restore"}, false), false);
-        return create(params, env, kind, parent, consoleHandler);
+    public static ChildContextInfo createNoRestore(Client client, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr) {
+        RStartParams params = new RStartParams(RCmdOptions.parseArguments(client, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false);
+        return create(params, env, kind, parent, stdin, stdout, stderr);
     }
 
     public RStartParams getStartParams() {
@@ -171,10 +201,6 @@ public final class ContextInfo {
         return parent;
     }
 
-    public ConsoleHandler getConsoleHandler() {
-        return consoleHandler;
-    }
-
     public TimeZone getSystemTimeZone() {
         return systemTimeZone;
     }
@@ -187,7 +213,24 @@ public final class ContextInfo {
         return multiSlotInd;
     }
 
+    public TruffleContext getTruffleContext() {
+        return truffleContext;
+    }
+
+    @Deprecated
     public PolyglotEngine getVM() {
         return vm;
     }
+
+    public InputStream getStdin() {
+        return stdin;
+    }
+
+    public OutputStream getStdout() {
+        return stdout;
+    }
+
+    public OutputStream getStderr() {
+        return stderr;
+    }
 }
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
deleted file mode 100644
index cd21de478bcbbc641621ce8c4e41ec50082b40e5..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ConsoleHandler.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package com.oracle.truffle.r.runtime.context;
-
-import java.io.File;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-
-/**
- * The interface to a source of input/output for the context, which may have different
- * 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 abstract class ConsoleHandler {
-
-    private RContext ctx;
-
-    /**
-     * Normal output with a new line.
-     */
-    @TruffleBoundary
-    public abstract void println(String s);
-
-    /**
-     * Normal output without a newline.
-     */
-    @TruffleBoundary
-    public abstract void print(String s);
-
-    /**
-     * Formatted output.
-     */
-    @TruffleBoundary
-    public void printf(String format, Object... args) {
-        print(String.format(format, args));
-    }
-
-    /**
-     * Error output with a newline.
-     *
-     * @param s
-     */
-    @TruffleBoundary
-    public abstract void printErrorln(String s);
-
-    /**
-     * Error output without a newline.
-     */
-    @TruffleBoundary
-    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
-    public abstract String readLine();
-
-    /**
-     * Denote whether the FastR instance is running in 'interactive' mode. This can be set in a
-     * number of ways and is <b>not</> simply equivalent to taking input from a file. However, it is
-     * final once set.
-     */
-    @TruffleBoundary
-    public abstract boolean isInteractive();
-
-    /**
-     * Get the current prompt.
-     */
-    @TruffleBoundary
-    public abstract String getPrompt();
-
-    /**
-     * Set the R prompt.
-     */
-    @TruffleBoundary
-    public abstract void setPrompt(String prompt);
-
-    public abstract String getInputDescription();
-
-    public void setContext(RContext ctx) {
-        this.ctx = ctx;
-    }
-
-    public RContext getContext() {
-        return ctx;
-    }
-
-    public void setHistoryFrom(@SuppressWarnings("unused") File file) {
-        // by default, do nothing
-    }
-
-    public void flushHistory() {
-        // by default, do nothing
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
index fe6fc77fa95752f8dea4d2fced40aa64930cd326..8ad26ae5a0872114391b191edec01b2bc93c85cf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
@@ -22,16 +22,24 @@
  */
 package com.oracle.truffle.r.runtime.context;
 
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.TruffleException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RSource;
+import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -42,7 +50,7 @@ public interface Engine {
 
     Source GET_CONTEXT = RSource.fromTextInternal("<<<get_context>>>", RSource.Internal.GET_CONTEXT);
 
-    class ParseException extends RuntimeException {
+    class ParseException extends RuntimeException implements TruffleException {
         private static final long serialVersionUID = 1L;
 
         private final Source source;
@@ -68,14 +76,37 @@ public interface Engine {
         }
 
         @TruffleBoundary
-        public void report(ConsoleHandler consoleHandler) {
+        public void report(OutputStream output) {
+            try {
+                output.write(getErrorMessage().getBytes(StandardCharsets.UTF_8));
+            } catch (IOException e) {
+                throw new RInternalError(e, "error while printing parse exception");
+            }
+        }
+
+        @TruffleBoundary
+        public void report(ConsoleIO console) {
+            console.println(getErrorMessage());
+        }
+
+        private String getErrorMessage() {
             String msg;
             if (source.getLineCount() == 1) {
                 msg = String.format(RError.Message.UNEXPECTED.message, token, substring);
             } else {
                 msg = String.format(RError.Message.UNEXPECTED_LINE.message, token, substring, line);
             }
-            consoleHandler.println("Error: " + msg);
+            return "Error: " + msg;
+        }
+
+        @Override
+        public Node getLocation() {
+            return null;
+        }
+
+        @Override
+        public boolean isSyntaxError() {
+            return true;
         }
     }
 
@@ -85,6 +116,11 @@ public interface Engine {
         public IncompleteSourceException(Throwable cause, Source source, String token, String substring, int line) {
             super(cause, source, token, substring, line);
         }
+
+        @Override
+        public boolean isIncompleteSource() {
+            return true;
+        }
     }
 
     /**
@@ -171,7 +207,7 @@ public interface Engine {
      * namespace, but the current stack is not empty. So when {@code frame} is not {@code null} a
      * {@code caller} should be passed to maintain the call stack correctly. {@code names} string
      * vector describing (optional) argument names
-     * 
+     *
      * @param names signature of the given parameters, may be {@code null} in which case the empty
      *            signature of correct cardinality shall be used.
      * @param evalPromises whether to evaluate promises in args array before calling the function.
@@ -201,4 +237,10 @@ public interface Engine {
      * Essentially this is equivalent to {@link #evalFunction} using the {@code "print"} function.
      */
     void printResult(Object value);
+
+    /**
+     * Return the "global" frame for this {@link Engine}, aka {@code globalEnv}.
+     *
+     */
+    MaterializedFrame getGlobalFrame();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java
new file mode 100644
index 0000000000000000000000000000000000000000..1f7f44cfd908b41d44562972e372863bb67212b5
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.runtime.context;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.TruffleContext;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.ExitException;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.context.Engine.ParseException;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+
+/**
+ * A thread for performing an evaluation (used by {@code .fastr} builtins).
+ */
+public class EvalThread extends Thread {
+
+    private final Source source;
+    private final ChildContextInfo info;
+    private final TruffleContext truffleContext;
+    private final boolean usePolyglot;
+    private RList evalResult;
+    private Semaphore init = new Semaphore(0);
+
+    private final Map<Integer, Thread> threadMap;
+
+    /** This table is required to create several bunches of child contexts. */
+    public static final Map<Integer, Integer> idToMultiSlotTable = 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(Map<Integer, Thread> threadMap, ChildContextInfo info, Source source, boolean usePolyglot) {
+        this.threadMap = threadMap;
+        this.info = info;
+        this.source = source;
+        threadCnt.incrementAndGet();
+        threadMap.put(info.getId(), this);
+        idToMultiSlotTable.put(info.getId(), info.getMultiSlotInd());
+        this.usePolyglot = usePolyglot;
+        this.truffleContext = usePolyglot ? null : info.createTruffleContext();
+    }
+
+    @Override
+    public void run() {
+        init.release();
+        try {
+            if (usePolyglot) {
+                PolyglotEngine vm = info.createVM(PolyglotEngine.newBuilder());
+                evalResult = run(vm, info, source);
+            } else {
+                evalResult = run(truffleContext, info, source);
+            }
+        } finally {
+            threadMap.remove(info.getId());
+            threadCnt.decrementAndGet();
+        }
+    }
+
+    /*
+     * Parent context uses this method to wait for initialization of the child to complete to
+     * prevent potential updates to runtime's meta data from interfering with program's execution.
+     */
+    public void waitForInit() {
+        try {
+            init.acquire();
+        } catch (InterruptedException x) {
+            throw new RInternalError(x, "error waiting to initialize eval thread");
+        }
+    }
+
+    /**
+     * Convenience method for {@code .fastr.context.eval} in same thread.
+     */
+    public static RList run(TruffleContext truffleContext, ChildContextInfo info, Source source) {
+        RList result = null;
+        Object parent = null;
+        try {
+            parent = truffleContext.enter();
+            // this is the engine for the new child context
+            Engine rEngine = RContext.getEngine();
+            // Object eval = rEngine.eval(rEngine.parse(source), rEngine.getGlobalFrame());
+            Object evalResult = rEngine.parseAndEval(source, rEngine.getGlobalFrame(), false);
+            result = createEvalResult(evalResult == null ? RNull.instance : evalResult, false);
+        } catch (ParseException e) {
+            e.report(info.getStdout());
+            result = createErrorResult(e.getMessage());
+        } catch (ExitException e) {
+            // termination, treat this as "success"
+            result = RDataFactory.createList(new Object[]{e.getStatus()});
+        } catch (RError e) {
+            // nothing to do
+            result = RDataFactory.createList(new Object[]{RNull.instance});
+        } catch (Throwable t) {
+            // some internal error
+            RInternalError.reportErrorAndConsoleLog(t, info.getId());
+            result = createErrorResult(t.getClass().getSimpleName());
+        } finally {
+            truffleContext.leave(parent);
+            truffleContext.close();
+        }
+        return result;
+    }
+
+    public static RList run(PolyglotEngine vm, ChildContextInfo info, Source source) {
+        RList evalResult;
+        try {
+            PolyglotEngine.Value resultValue = vm.eval(source);
+            evalResult = createEvalResult(resultValue, true);
+        } catch (ParseException e) {
+            e.report(info.getStdout());
+            evalResult = createErrorResult(e.getMessage());
+        } catch (ExitException e) {
+            // termination, treat this as "success"
+            evalResult = RDataFactory.createList(new Object[]{e.getStatus()});
+        } catch (RError e) {
+            // nothing to do
+            evalResult = RDataFactory.createList(new Object[]{RNull.instance});
+        } catch (Throwable t) {
+            // some internal error
+            RInternalError.reportErrorAndConsoleLog(t, info.getId());
+            evalResult = createErrorResult(t.getClass().getSimpleName());
+        } finally {
+            vm.dispose();
+        }
+        return evalResult;
+    }
+
+    /**
+     * The result is an {@link RList} contain the value, plus an "error" attribute if the evaluation
+     * resulted in an error.
+     */
+    @TruffleBoundary
+    private static RList createEvalResult(Object result, boolean usePolyglot) {
+        assert result != null;
+        Object listResult = result;
+        if (usePolyglot && result instanceof TruffleObject) {
+            listResult = ((PolyglotEngine.Value) result).as(Object.class);
+        } else {
+            listResult = result;
+        }
+        return RDataFactory.createList(new Object[]{listResult});
+    }
+
+    @TruffleBoundary
+    public static RList createErrorResult(String errorMsg) {
+        RList list = RDataFactory.createList(new Object[]{RRuntime.LOGICAL_NA});
+        list.setAttr("error", errorMsg);
+        return list;
+
+    }
+
+    public RList getEvalResult() {
+        return evalResult;
+    }
+
+    public ChildContextInfo getContextInfo() {
+        return info;
+    }
+}
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 b24e38155395003f558c015e45c8799dbf3844d6..5a94cb1380634e9d42b98d7c91fbe30eeee9d416 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
@@ -22,37 +22,60 @@
  */
 package com.oracle.truffle.r.runtime.context;
 
-import java.io.Closeable;
 import java.util.ArrayList;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
 import java.lang.ref.WeakReference;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.EnumSet;
-import java.lang.ref.WeakReference;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 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 java.util.concurrent.Executor;
+import java.util.function.Supplier;
 
 import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.TruffleContext;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.instrumentation.AllocationReporter;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
+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.nodes.Node;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.r.runtime.ExitException;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RStartParams;
+import com.oracle.truffle.r.runtime.FastRConfig;
 import com.oracle.truffle.r.runtime.LazyDBCache;
 import com.oracle.truffle.r.runtime.PrimitiveMethodsInfo;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.REnvVars;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RErrorHandling;
@@ -63,19 +86,15 @@ import com.oracle.truffle.r.runtime.RProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RSerialize;
-import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.TempPathName;
-import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinLookup;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport;
 import com.oracle.truffle.r.runtime.conn.StdConnections;
-import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 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.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -95,7 +114,7 @@ import qir.ast.QIRNode;
  *
  * Contexts are created during construction of the {@link PolyglotEngine} instance. In case a
  * context needs to be configured, the PolyglotEngine needs to be created via the
- * {@code RContextFactory} class, which takes a {@link ContextInfo} object for configuration.
+ * {@code RContextFactory} class, which takes a {@link ChildContextInfo} object for configuration.
  *
  * The context provides a so-called {@link Engine} (accessed via {@link #getEngine()}), which
  * provides basic parsing and execution functionality .
@@ -105,8 +124,7 @@ import qir.ast.QIRNode;
  *
  * Contexts can be destroyed
  */
-@SuppressWarnings("deprecation")
-public final class RContext extends com.oracle.truffle.api.ExecutionContext implements RTruffleObject {
+public final class RContext implements RTruffleObject {
     private static int queryId = 0;
     public static final int INVALID_QUERY_ID = -1;
     // Static representation of queries.
@@ -241,140 +259,40 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         }
     }
 
-    /**
-     * A thread that is explicitly associated with a context for efficient lookup.
-     */
-    public abstract static class ContextThread extends Thread {
-        protected RContext context;
-
-        public ContextThread(RContext context) {
-            this.context = context;
-        }
+    private final RStartParams startParameters;
+    private final RCmdOptions cmdOptions;
+    private final String[] environment;
+    private final RContext.ContextKind contextKind;
+    private final TimeZone systemTimeZone;
+    public final Map<Class<?>, RootCallTarget> nativeCallTargets = new HashMap<>();
 
-        public void setContext(RContext context) {
-            this.context = context;
+    public RootCallTarget getOrCreateNativeCallTarget(Class<?> clazz, Supplier<RootCallTarget> creatFunction) {
+        RootCallTarget result = nativeCallTargets.get(clazz);
+        if (result == null) {
+            result = creatFunction.get();
+            nativeCallTargets.put(clazz, result);
         }
+        return result;
     }
 
     /**
-     * A thread for performing an evaluation (used by {@code .fastr} builtins).
+     * Any context created by another has a parent. When such a context is destroyed we must reset
+     * the RContext.threadLocalContext to the parent.
      */
-    public static class EvalThread extends ContextThread {
-
-        private final Source source;
-        private final ContextInfo info;
-        private RList evalResult;
-        private Semaphore init = new Semaphore(0);
-
-        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);
-        }
-
-        @Override
-        public void run() {
-            PolyglotEngine vm = info.createVM(PolyglotEngine.newBuilder());
-            try {
-                setContext(vm.eval(Engine.GET_CONTEXT).as(RContext.class));
-            } catch (Throwable t) {
-                throw new RInternalError(t, "error while initializing eval thread");
-            }
-            init.release();
-            try {
-                evalResult = run(vm, info, source);
-            } finally {
-                vm.dispose();
-                threads.remove(info.getId());
-                threadCnt.decrementAndGet();
-            }
-        }
-
-        /*
-         * Parent context uses this method to wait for initialization of the child to complete to
-         * prevent potential updates to runtime's meta data from interfering with program's
-         * execution.
-         */
-        public void waitForInit() {
-            try {
-                init.acquire();
-            } catch (InterruptedException x) {
-                throw new RInternalError(x, "error waiting to initialize eval thread");
-            }
-        }
+    private final RContext parentContext;
+    private final int id;
+    private final int multiSlotIndex;
+    private TruffleContext truffleContext;
+    private PolyglotEngine vm;
 
-        /**
-         * Convenience method for {@code .fastr.context.eval} in same thread.
-         */
-        public static RList run(PolyglotEngine vm, ContextInfo info, Source source) {
-            RList evalResult;
-            try {
-                PolyglotEngine.Value resultValue = vm.eval(source);
-                evalResult = createEvalResult(resultValue);
-            } catch (ParseException e) {
-                e.report(info.getConsoleHandler());
-                evalResult = createErrorResult(e.getMessage());
-            } catch (ExitException e) {
-                // termination, treat this as "success"
-                evalResult = RDataFactory.createList(new Object[]{e.getStatus()});
-            } catch (RError e) {
-                // nothing to do
-                evalResult = RDataFactory.createList(new Object[]{RNull.instance});
-            } catch (Throwable t) {
-                // some internal error
-                RInternalError.reportErrorAndConsoleLog(t, info.getConsoleHandler(), info.getId());
-                evalResult = createErrorResult(t.getClass().getSimpleName());
-            }
-            return evalResult;
-        }
-
-        /**
-         * The result is an {@link RList} contain the value, plus an "error" attribute if the
-         * evaluation resulted in an error.
-         */
-        @TruffleBoundary
-        private static RList createEvalResult(PolyglotEngine.Value resultValue) {
-            Object result = resultValue.get();
-            Object listResult = result;
-            String error = null;
-            if (result == null) {
-                // this means an error occurred and there is no result
-                listResult = RRuntime.LOGICAL_NA;
-                error = "R error";
-            } else if (result instanceof TruffleObject) {
-                listResult = resultValue.as(Object.class);
-            } else {
-                listResult = result;
-            }
-            RList list = RDataFactory.createList(new Object[]{listResult});
-            if (error != null) {
-                list.setAttr("error", error);
-            }
-            return list;
-        }
-
-        @TruffleBoundary
-        public static RList createErrorResult(String errorMsg) {
-            RList list = RDataFactory.createList(new Object[]{RRuntime.LOGICAL_NA});
-            list.setAttr("error", errorMsg);
-            return list;
+    public Executor executor;
 
-        }
-
-        public RList getEvalResult() {
-            return evalResult;
-        }
-    }
+    private final InputStream stdin;
+    private final OutputStreamWriter stdout;
+    private final OutputStreamWriter stderr;
 
-    private final ContextInfo info;
     private final Engine engine;
+    private final TruffleRLanguage language;
 
     /**
      * A context-specific value that is checked in {@code HiddenInternalFunctions} to avoid an error
@@ -387,16 +305,6 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
      */
     private RContext sharedChild;
 
-    /**
-     * Typically there is a 1-1 relationship between an {@link RContext} and the thread that is
-     * performing the evaluation, so we can store the {@link RContext} in a {@link ThreadLocal}.
-     *
-     * When a context is first created no threads are attached, to allow contexts to be used as
-     * values in the experimental {@code fastr.context.xxx} functions. Additional threads can be
-     * added by the {@link #attachThread} method.
-     */
-    private static final ThreadLocal<RContext> threadLocalContext = new ThreadLocal<>();
-
     /**
      * Used by the MethodListDispatch class.
      */
@@ -410,6 +318,9 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
 
     private PrimitiveMethodsInfo primitiveMethodsInfo;
 
+    /** Class loader for Java interop. */
+    private ClassLoader interopClassLoader = FastRConfig.InternalGridAwtSupport ? getClass().getClassLoader() : null;
+
     /**
      * Set to {@code true} when in embedded mode to allow other parts of the system to determine
      * whether embedded mode is in effect, <b>before</b> the initial context is created.
@@ -441,27 +352,11 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         RContext.foreignAccessFactory = rForeignAccessFactory;
     }
 
-    /**
-     * Associates this {@link RContext} with the current thread.
-     */
-    private void attachThread() {
-        Thread current = Thread.currentThread();
-        if (current instanceof ContextThread) {
-            ((ContextThread) current).setContext(this);
-        } else {
-            threadLocalContext.set(this);
-        }
-    }
-
-    private static final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("single RContext");
-    @CompilationFinal private static RContext singleContext;
-
     // need an additional flag as we don't want multi-slot processing to start until context
     // initialization is fully complete - singleContext flag is not good enough for that
     private static final Assumption isSingleContextAssumption = Truffle.getRuntime().createAssumption("is single RContext");
 
     private final Env env;
-    private final HashMap<String, TruffleObject> exportedSymbols = new HashMap<>();
     private final boolean initial;
     /**
      * State that is used to support interposing on loadNamespace() for overrides.
@@ -496,11 +391,14 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
     public final WeakHashMap<String, WeakReference<String>> stringMap = new WeakHashMap<>();
     public final WeakHashMap<Source, REnvironment> sourceRefEnvironments = new WeakHashMap<>();
     public final WeakHashMap<Path, REnvironment> srcfileEnvironments = new WeakHashMap<>();
+    public final List<String> libraryPaths = new ArrayList<>(1);
+    public final Map<Integer, Thread> threads = new ConcurrentHashMap<>();
+
+    private final AllocationReporter allocationReporter;
 
     private ContextState[] contextStates() {
         return new ContextState[]{stateREnvVars, stateRProfile, stateTempPath, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI,
-                        stateRSerialize,
-                        stateLazyDBCache, stateInstrumentation, stateDLL};
+                        stateRSerialize, stateLazyDBCache, stateInstrumentation, stateDLL};
     }
 
     public static void setEmbedded() {
@@ -527,20 +425,53 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
      * @param instrumenter value passed from {@link TruffleLanguage#createContext}
      * @param isInitial {@code true} if this is the initial (primordial) context.
      */
-    private RContext(Env env, Instrumenter instrumenter, boolean isInitial) {
-        Object initialInfo = env.getConfig().get(ContextInfo.CONFIG_KEY);
+    private RContext(TruffleRLanguage language, Env env, Instrumenter instrumenter, boolean isInitial) {
+        this.language = language;
+        String[] args;
+        if (env.getApplicationArguments().length == 0) {
+            args = new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"};
+        } else {
+            args = env.getApplicationArguments();
+        }
+
+        Object initialInfo = env.getConfig().get(ChildContextInfo.CONFIG_KEY);
         if (initialInfo == null) {
             /*
-             * This implies that FastR is being invoked initially from another Truffle language and
-             * not via RCommand/RscriptCommand. In this case, we also assume that no previously
+             * This implies that FastR is being invoked initially from another Truffle language or
+             * via RCommand/RscriptCommand. TODO How to deciden if session state is to be restored
              * stored session should be restored.
              */
-            this.info = ContextInfo.create(new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"--no-restore"}, false), false), null,
-                            ContextKind.SHARE_NOTHING, null, new DefaultConsoleHandler(env.in(), env.out()));
+            this.cmdOptions = RCmdOptions.parseArguments(Client.R, args, true);
+            this.startParameters = new RStartParams(cmdOptions, false);
+            this.environment = null;
+            this.contextKind = ContextKind.SHARE_NOTHING;
+            this.systemTimeZone = TimeZone.getDefault();
+            this.parentContext = null;
+            this.id = ChildContextInfo.contextInfoIds.incrementAndGet();
+            this.multiSlotIndex = 0;
+            this.truffleContext = null; // TODO
+            this.executor = null;
         } else {
-            this.info = (ContextInfo) initialInfo;
+            // child spawned explicitly by R
+            ChildContextInfo info = (ChildContextInfo) initialInfo;
+            this.cmdOptions = RCmdOptions.parseArguments(Client.R, args, true);
+            this.startParameters = info.getStartParams();
+            this.environment = info.getEnv();
+            this.contextKind = info.getKind();
+            this.systemTimeZone = info.getSystemTimeZone();
+            this.parentContext = info.getParent();
+            this.id = info.getId();
+            this.multiSlotIndex = info.getMultiSlotInd();
+            this.truffleContext = info.getTruffleContext();
+            this.executor = info.executor;
         }
 
+        outputWelcomeMessage(startParameters);
+
+        this.stdin = env.in();
+        this.stdout = new OutputStreamWriter(env.out());
+        this.stderr = new OutputStreamWriter(env.err());
+
         this.initial = isInitial;
         this.env = env;
         this.stateREnvVars = REnvVars.newContextState();
@@ -559,6 +490,21 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         this.stateDLL = DLL.ContextStateImpl.newContextState();
         this.engine = RContext.getRRuntimeASTAccess().createEngine(this);
         state.add(State.CONSTRUCTED);
+
+        this.allocationReporter = env.lookup(AllocationReporter.class);
+        this.allocationReporter.addPropertyChangeListener(ALLOCATION_ACTIVATION_LISTENER);
+        RDataFactory.setAllocationTracingEnabled(allocationReporter.isActive());
+    }
+
+    static void outputWelcomeMessage(RStartParams rsp) {
+        /*
+         * Outputting the welcome message here has the virtue that the VM initialization delay
+         * occurs later. However, it does not work in embedded mode as console redirects have not
+         * been installed at this point. So we do it later in REmbedded.
+         */
+        if (!rsp.isQuiet() && !embedded) {
+            System.out.println(RRuntime.WELCOME_MESSAGE);
+        }
     }
 
     /**
@@ -567,42 +513,22 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
      */
     public RContext initializeContext() {
         // this must happen before engine activation in the code below
-        if (info.getKind() == ContextKind.SHARE_NOTHING) {
-            if (info.getParent() == null) {
+        if (contextKind == ContextKind.SHARE_NOTHING) {
+            if (parentContext == null) {
                 this.primitiveMethodsInfo = new PrimitiveMethodsInfo();
             } else {
                 // share nothing contexts need their own copy of the primitive methods meta-data as
                 // they can run (and update this meta data) concurrently with the parent;
                 // alternative would be to copy on-write but we would need some kind of locking
                 // machinery to avoid races
-                assert info.getParent().getPrimitiveMethodsInfo() != null;
-                this.primitiveMethodsInfo = info.getParent().getPrimitiveMethodsInfo().duplicate();
-            }
-        }
-
-        if (info.getConsoleHandler() == null) {
-            throw Utils.rSuicide("no console handler set");
-        }
-
-        if (singleContextAssumption.isValid()) {
-            if (singleContext == null) {
-                singleContext = this;
-            } else {
-                singleContext = null;
-                singleContextAssumption.invalidate();
+                assert parentContext.getPrimitiveMethodsInfo() != null;
+                this.primitiveMethodsInfo = parentContext.getPrimitiveMethodsInfo().duplicate();
             }
         }
 
         /*
-         * Activate the context by attaching the current thread and initializing the {@link
-         * ContextState} objects. Note that we attach the thread before creating the new context
-         * state. This means that code that accesses the state through this interface will receive a
-         * {@code null} value. Access to the parent state is available through the {@link RContext}
-         * argument passed to the newContext methods. It might be better to attach the thread after
-         * state creation but it is a finely balanced decision and risks incorrectly accessing the
-         * parent state.
+         * Activate the context by initializing the {@link ContextState} objects.
          */
-        attachThread();
         state.add(State.ATTACHED);
 
         stateDLL.initialize(this);
@@ -634,14 +560,14 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
             state.add(State.ACTIVE);
         }
 
-        if (info.getKind() == ContextKind.SHARE_PARENT_RW) {
-            if (info.getParent().sharedChild != null) {
+        if (contextKind == ContextKind.SHARE_PARENT_RW) {
+            if (parentContext.sharedChild != null) {
                 throw RError.error(RError.SHOW_CALLER2, RError.Message.GENERIC, "can't have multiple active SHARED_PARENT_RW contexts");
             }
-            info.getParent().sharedChild = this;
+            parentContext.sharedChild = this;
             // this one must be shared between contexts - otherwise testing contexts do not know
             // that methods package is loaded
-            this.methodTableDispatchOn = info.getParent().methodTableDispatchOn;
+            this.methodTableDispatchOn = parentContext.methodTableDispatchOn;
         }
         if (initial && !embedded) {
             initialContextInitialized = true;
@@ -680,8 +606,8 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
      *
      * @param isInitial {@code true} iff this is the initial context
      */
-    public static RContext create(Env env, Instrumenter instrumenter, boolean isInitial) {
-        return new RContext(env, instrumenter, isInitial);
+    public static RContext create(TruffleRLanguage language, Env env, Instrumenter instrumenter, boolean isInitial) {
+        return new RContext(language, env, instrumenter, isInitial);
     }
 
     /**
@@ -694,20 +620,17 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
                     contextState.beforeDestroy(this);
                 }
             }
-            if (info.getKind() == ContextKind.SHARE_PARENT_RW) {
-                info.getParent().sharedChild = null;
-            }
-            if (info.getParent() == null) {
-                threadLocalContext.set(null);
-            } else {
-                threadLocalContext.set(info.getParent());
+            if (contextKind == ContextKind.SHARE_PARENT_RW) {
+                parentContext.sharedChild = null;
             }
             state = EnumSet.of(State.DESTROYED);
+
+            this.allocationReporter.removePropertyChangeListener(ALLOCATION_ACTIVATION_LISTENER);
         }
     }
 
     public RContext getParent() {
-        return info.getParent();
+        return parentContext;
     }
 
     public Env getEnv() {
@@ -719,33 +642,15 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
     }
 
     public ContextKind getKind() {
-        return info.getKind();
+        return contextKind;
     }
 
     public int getId() {
-        return info.getId();
+        return id;
     }
 
     public int getMultiSlotInd() {
-        return info.getMultiSlotInd();
-    }
-
-    @TruffleBoundary
-    public static RContext getThreadLocalInstance() {
-        return threadLocalContext.get();
-    }
-
-    @TruffleBoundary
-    public static void setThreadLocalInstance(RContext context) {
-        threadLocalContext.set(context);
-    }
-
-    @TruffleBoundary
-    private static RContext getInstanceInternal() {
-        RContext result = threadLocalContext.get();
-        assert result != null;
-        assert result.state.contains(State.ATTACHED);
-        return result;
+        return multiSlotIndex;
     }
 
     public static boolean isSingle() {
@@ -757,19 +662,11 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
     }
 
     public static RContext getInstance() {
-        RContext context = singleContext;
-        if (singleContextAssumption.isValid() && context != null) {
-            return context;
-        }
+        return getRRuntimeASTAccess().getCurrentContext();
+    }
 
-        Thread current = Thread.currentThread();
-        if (current instanceof ContextThread) {
-            context = ((ContextThread) current).context;
-            assert context != null;
-            return context;
-        } else {
-            return getInstanceInternal();
-        }
+    public boolean isInteractive() {
+        return startParameters.isInteractive();
     }
 
     /**
@@ -817,22 +714,14 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         if (primitiveMethodsInfo == null) {
             // shared contexts do not run concurrently with their parent and re-use primitive
             // methods information
-            assert info.getKind() != ContextKind.SHARE_NOTHING;
-            assert info.getParent() != null;
-            return info.getParent().getPrimitiveMethodsInfo();
+            assert contextKind != ContextKind.SHARE_NOTHING;
+            assert parentContext != null;
+            return parentContext.getPrimitiveMethodsInfo();
         } else {
             return primitiveMethodsInfo;
         }
     }
 
-    public boolean isInteractive() {
-        return info.getConsoleHandler().isInteractive();
-    }
-
-    public ConsoleHandler getConsoleHandler() {
-        return info.getConsoleHandler();
-    }
-
     /**
      * This is a static property of the implementation and not context-specific.
      */
@@ -858,8 +747,8 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
      * Return the {@link RFunction} for the builtin {@code name}.
      */
     @TruffleBoundary
-    public static RFunction lookupBuiltin(String name) {
-        return builtinLookup.lookupBuiltin(name);
+    public RFunction lookupBuiltin(String name) {
+        return builtinLookup.lookupBuiltin(language, name);
     }
 
     /**
@@ -874,16 +763,20 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         return foreignAccessFactory;
     }
 
+    public RCmdOptions getCmdOptions() {
+        return cmdOptions;
+    }
+
     public RStartParams getStartParams() {
-        return info.getStartParams();
+        return startParameters;
     }
 
     public String[] getEnvSettings() {
-        return info.getEnv();
+        return environment;
     }
 
     public boolean hasExecutor() {
-        return info.executor != null;
+        return executor != null;
     }
 
     /**
@@ -892,12 +785,12 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
      */
     public void schedule(Runnable action) {
         assert hasExecutor() : "Cannot run RContext#schedule() when there is no executor.";
-        info.executor.execute(action);
+        executor.execute(action);
     }
 
     @Override
     public String toString() {
-        return "context: " + info.getId();
+        return "context: " + id;
     }
 
     /*
@@ -909,13 +802,21 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         return RContext.getInstance().engine;
     }
 
+    public TruffleRLanguage getLanguage() {
+        return language;
+    }
+
     public ContextState getStateRFFI() {
         assert stateRFFI != null;
         return stateRFFI;
     }
 
+    public TruffleContext getTruffleContext() {
+        return truffleContext;
+    }
+
     public PolyglotEngine getVM() {
-        return info.getVM();
+        return vm;
     }
 
     public boolean isInitial() {
@@ -930,16 +831,8 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         return loadingBase;
     }
 
-    public Map<String, TruffleObject> getExportedSymbols() {
-        return exportedSymbols;
-    }
-
-    public void addExportedSymbol(String name, TruffleObject obj) {
-        exportedSymbols.put(name, obj);
-    }
-
     public TimeZone getSystemTimeZone() {
-        return info.getSystemTimeZone();
+        return systemTimeZone;
     }
 
     public String getNamespaceName() {
@@ -950,20 +843,217 @@ public final class RContext extends com.oracle.truffle.api.ExecutionContext impl
         nameSpaceName = name;
     }
 
-    public interface RCloseable extends Closeable {
+    public static Class<? extends TruffleRLanguage> getTruffleRLanguage() {
+        return getRRuntimeASTAccess().getTruffleRLanguage();
+    }
+
+    public AllocationReporter getAllocationReporter() {
+        return this.allocationReporter;
+    }
+
+    private static final PropertyChangeListener ALLOCATION_ACTIVATION_LISTENER = new PropertyChangeListener() {
         @Override
-        void close();
+        public void propertyChange(PropertyChangeEvent event) {
+            RDataFactory.setAllocationTracingEnabled(event.getNewValue() == Boolean.TRUE);
+        }
+    };
+
+    public Class<?> loadClass(String className) throws ClassNotFoundException {
+        if (FastRConfig.InternalGridAwtSupport) {
+            return interopClassLoader.loadClass(className);
+        }
+        return Class.forName(className);
     }
 
-    @TruffleBoundary
-    public static RCloseable withinContext(RContext context) {
-        RContext oldContext = RContext.threadLocalContext.get();
-        RContext.threadLocalContext.set(context);
-        return new RCloseable() {
-            @Override
-            public void close() {
-                RContext.threadLocalContext.set(oldContext);
+    /**
+     * Adds entries to the Java interop class loader. This will effectively create a new class
+     * loader with the previous one as parent.
+     */
+    public void addInteropClasspathEntries(String... entries) throws MalformedURLException {
+        if (!FastRConfig.InternalGridAwtSupport) {
+            throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Custom class loading not supported.");
+        }
+
+        URL[] urls = new URL[entries.length];
+        for (int i = 0; i < entries.length; i++) {
+            urls[i] = Paths.get(entries[i]).toUri().toURL();
+        }
+        interopClassLoader = URLClassLoader.newInstance(urls, interopClassLoader);
+    }
+
+    public final class ConsoleIO {
+
+        private final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
+
+        {
+            decoder.onMalformedInput(CodingErrorAction.IGNORE);
+            decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+        }
+
+        @TruffleBoundary
+        public String readLine() {
+            /*
+             * We cannot use an InputStreamReader because it buffers characters internally, whereas
+             * readLine() should not buffer across newlines.
+             */
+
+            ByteBuffer bytes = ByteBuffer.allocate(16);
+            CharBuffer chars = CharBuffer.allocate(16);
+            StringBuilder str = new StringBuilder();
+            decoder.reset();
+            while (true) {
+                int inputByte;
+                try {
+                    inputByte = stdin.read();
+                } catch (IOException e) {
+                    throw new RInternalError(e, "error writing to stderr");
+                }
+                if (inputByte == -1) {
+                    return str.toString();
+                }
+                bytes.put((byte) inputByte);
+                bytes.flip();
+                decoder.decode(bytes, chars, false);
+                chars.flip();
+                while (chars.hasRemaining()) {
+                    char c = chars.get();
+                    if (c == '\n' || c == '\r') {
+                        return str.toString();
+                    }
+                    str.append(c);
+                }
+                bytes.compact();
+                chars.clear();
             }
-        };
+        }
+
+        @TruffleBoundary
+        public void print(String message) {
+            try {
+                stdout.write(message);
+                stdout.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stdout");
+            }
+        }
+
+        @TruffleBoundary
+        public void println(String message) {
+            try {
+                stdout.write(message);
+                stdout.write('\n');
+                stdout.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stdout");
+            }
+        }
+
+        @TruffleBoundary
+        public void printf(String format, Object... args) {
+            try {
+                stdout.write(String.format(format, args));
+                stdout.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stdout");
+            }
+        }
+
+        @TruffleBoundary
+        public void printError(String message) {
+            try {
+                stderr.write(message);
+                stderr.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stderr");
+            }
+        }
+
+        @TruffleBoundary
+        public void printErrorln(String message) {
+            try {
+                stderr.write(message);
+                stderr.write('\n');
+                stderr.flush();
+            } catch (IOException e) {
+                throw new RInternalError(e, "error writing to stderr");
+            }
+        }
+
+        private final Node read = Message.READ.createNode();
+        private final Node write = Message.WRITE.createNode();
+
+        @TruffleBoundary
+        public String getPrompt() {
+            if (handler != null) {
+                Object result;
+                try {
+                    result = ForeignAccess.sendRead(read, handler, "prompt");
+                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
+                    throw new RInternalError(e, "error while reading prompt");
+                }
+                return (String) result;
+            }
+            return "";
+        }
+
+        @TruffleBoundary
+        public void setPrompt(String prompt) {
+            if (handler != null) {
+                try {
+                    ForeignAccess.sendWrite(write, handler, "prompt", prompt);
+                } catch (UnknownIdentifierException | UnsupportedMessageException | UnsupportedTypeException e) {
+                    throw new RInternalError(e, "error while writing prompt");
+                }
+            }
+        }
+
+        @TruffleBoundary
+        public String getHistory() {
+            if (handler != null) {
+                Object result;
+                try {
+                    result = ForeignAccess.sendRead(read, handler, "history");
+                } catch (UnknownIdentifierException | UnsupportedMessageException e) {
+                    throw new RInternalError(e, "error while reading history");
+                }
+                return (String) result;
+            }
+            return "";
+        }
+
+        @TruffleBoundary
+        public void setHistory(String history) {
+            if (handler != null) {
+                try {
+                    ForeignAccess.sendWrite(write, handler, "history", history);
+                } catch (UnknownIdentifierException | UnsupportedMessageException | UnsupportedTypeException e) {
+                    throw new RInternalError(e, "error while writing history");
+                }
+            }
+        }
+
+        public InputStream getStdin() {
+            return env.in();
+        }
+
+        public OutputStream getStdout() {
+            return env.out();
+        }
+
+        public OutputStream getStderr() {
+            return env.err();
+        }
+
+        private TruffleObject handler;
+
+        public void setHandler(TruffleObject handler) {
+            this.handler = handler;
+        }
+    }
+
+    private final ConsoleIO console = new ConsoleIO();
+
+    public ConsoleIO getConsole() {
+        return console;
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java
index d5732acff89aa0c8213f3b1c59fe3220f4b677f3..32aa23a769200d1129ec96f8ca339dbc47a4ec26 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RForeignAccessFactory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.context;
 
-import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 
@@ -34,7 +33,11 @@ public interface RForeignAccessFactory {
     ForeignAccess getForeignAccess(RTruffleObject obj);
 
     /**
-     * Return the {@link TruffleLanguage} instance for R. (Project circularity workaround).
+     * Changes the interpretation of {@RNull} as {@code null} to {@code value}. This allows the
+     * {@code FFI} implementations to prevent {@RNull} being converted across the {@code FFI}
+     * interface, which would be incorrect.
+     *
+     * @return the previous setting
      */
-    Class<? extends TruffleLanguage<RContext>> getTruffleLanguage();
+    boolean setIsNull(boolean value);
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeIntegerArray.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/TruffleRLanguage.java
similarity index 68%
rename from com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeIntegerArray.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/TruffleRLanguage.java
index 217f5fa0169424bd5bc72ead54127ed0bead6d3a..b7f120bf34bf4374b9209411baafbf05f697e303 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/NativeIntegerArray.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/TruffleRLanguage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, 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
@@ -20,19 +20,15 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.engine.interop;
+package com.oracle.truffle.r.runtime.context;
 
-import com.oracle.truffle.r.runtime.data.RTruffleObject;
+import java.util.HashMap;
 
-public class NativeIntegerArray extends NativeNACheck implements RTruffleObject {
-    public final int[] value;
+import com.oracle.truffle.api.TruffleLanguage;
+import com.oracle.truffle.r.runtime.data.RFunction;
 
-    public NativeIntegerArray(Object obj, int[] value) {
-        super(obj);
-        this.value = value;
-    }
+public abstract class TruffleRLanguage extends TruffleLanguage<RContext> {
+
+    public abstract HashMap<String, RFunction> getBuiltinFunctionCache();
 
-    public NativeIntegerArray(int[] value) {
-        this(null, value);
-    }
 }
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 1f874d0842786b2e9c4e944544a9815dc2941bab..132f153d20779c4fae436c2d095926e573206952 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
@@ -28,6 +28,7 @@ import com.oracle.truffle.r.runtime.Arguments;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
 
 /**
  * A simple wrapper class for passing the ... argument through RArguments
@@ -60,4 +61,24 @@ public final class RArgsValuesAndNames extends Arguments<Object> implements RTyp
     public void setTypedValueInfo(int value) {
         throw RInternalError.shouldNotReachHere();
     }
+
+    public RPairList toPairlist() {
+        RPairList head = null;
+        ArgumentsSignature signature = getSignature();
+        assert signature.getLength() == getLength();
+        for (int i = 0; i < getLength(); i++) {
+            String name = signature.getName(i);
+            RPairList cur = RDataFactory.createPairList(getArgument(i), RNull.instance, name != null ? name : RNull.instance, SEXPTYPE.DOTSXP);
+
+            if (head == null) {
+                head = cur;
+            } else {
+                head.appendToEnd(cur);
+            }
+        }
+        if (head != null) {
+            return head;
+        }
+        return RDataFactory.createPairList(RNull.instance);
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBaseObject.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBaseObject.java
index 20681ec6eb703962e8ad4df2cd5e1b5d7c4b12fd..52e181b7b495afc5e697ff40bff8347e407e17ff 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBaseObject.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBaseObject.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
@@ -48,16 +48,16 @@ abstract class RBaseObject implements RTypedValue {
 
     @Override
     public final boolean isS4() {
-        return (getGPBits() & S4_MASK) == S4_MASK;
+        return (getTypedValueInfo() & S4_MASK_SHIFTED) != 0;
     }
 
     @Override
     public final void setS4() {
-        setGPBits(getGPBits() | S4_MASK);
+        setTypedValueInfo(getTypedValueInfo() | S4_MASK_SHIFTED);
     }
 
     @Override
     public final void unsetS4() {
-        setGPBits(getGPBits() & ~S4_MASK);
+        setTypedValueInfo(getTypedValueInfo() & ~S4_MASK_SHIFTED);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index 2192e8f0598c9b472336e793a2cefe92a5593ef8..eb98e8cdd860a965330f16fb53512c3de75354cc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
@@ -31,18 +31,21 @@ import com.oracle.truffle.api.Assumption;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.utilities.CyclicAssumption;
+import com.oracle.truffle.api.instrumentation.AllocationReporter;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinDescriptor;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerFeedback;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseState;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 import com.oracle.truffle.r.runtime.gnur.SEXPTYPE;
@@ -462,11 +465,19 @@ public final class RDataFactory {
     }
 
     public static Object createLangPairList(int size) {
-        return size == 0 ? RNull.instance : traceDataCreated(RPairList.create(size, SEXPTYPE.LANGSXP));
+        if (size == 0) {
+            return RNull.instance;
+        } else {
+            return traceDataCreated(RPairList.create(size, SEXPTYPE.LANGSXP));
+        }
     }
 
     public static Object createPairList(int size) {
-        return size == 0 ? RNull.instance : traceDataCreated(RPairList.create(size));
+        if (size == 0) {
+            return RNull.instance;
+        } else {
+            return traceDataCreated(RPairList.create(size));
+        }
     }
 
     public static RPairList createPairList() {
@@ -474,6 +485,7 @@ public final class RDataFactory {
     }
 
     public static RPairList createPairList(Object car) {
+
         return traceDataCreated(new RPairList(car, RNull.instance, RNull.instance, null));
     }
 
@@ -545,26 +557,72 @@ public final class RDataFactory {
      * allocated. Owing to the use of the Assumption, there should be no overhead when disabled.
      */
 
-    private static Deque<Listener> listeners = new ConcurrentLinkedDeque<>();
-    @CompilationFinal private static boolean enabled;
-    private static final CyclicAssumption noAllocationTracingAssumption = new CyclicAssumption("data allocation");
+    private static final Deque<Listener> listeners = new ConcurrentLinkedDeque<>();
+    private static boolean allocationTracingEnabled = false;
+
+    @CompilationFinal private static StateAssumption stateAssumption = new StateAssumption();
+
+    /**
+     * As long as "off" is valid, the feature is off. It is on as long as "on" is valid.
+     */
+    public static final class StateAssumption {
+        private final Assumption off = Truffle.getRuntime().createAssumption("off");
+        private final Assumption on = Truffle.getRuntime().createAssumption("on");
+
+        public boolean isEnabled() {
+            return !off.isValid() && on.isValid();
+        }
 
-    public static void setTracingState(boolean newState) {
-        if (enabled != newState) {
-            noAllocationTracingAssumption.invalidate();
-            enabled = newState;
+        public StateAssumption setState(boolean enabled) {
+            if (enabled && !stateAssumption.isEnabled()) {
+                assert !isEnabled();
+                off.invalidate();
+                return this;
+            } else if (!enabled && stateAssumption.isEnabled()) {
+                assert isEnabled();
+                on.invalidate();
+                return new StateAssumption();
+            } else {
+                // no change needed
+                return this;
+            }
         }
     }
 
+    public static synchronized void setAllocationTracingEnabled(boolean enabled) {
+        allocationTracingEnabled = enabled;
+        updateTracingState();
+    }
+
+    private static synchronized void updateTracingState() {
+        boolean enabled = !listeners.isEmpty() || allocationTracingEnabled;
+        stateAssumption = stateAssumption.setState(enabled);
+    }
+
     private static <T> T traceDataCreated(T data) {
-        if (enabled) {
-            for (Listener listener : listeners) {
-                listener.reportAllocation((RTypedValue) data);
-            }
+        if (stateAssumption.isEnabled()) {
+            reportDataCreated(data);
         }
         return data;
     }
 
+    @TruffleBoundary
+    private static void reportDataCreated(Object data) {
+        if (allocationTracingEnabled) {
+            RContext ctx = RContext.getInstance();
+            assert ctx != null;
+            AllocationReporter allocationReporter = ctx.getAllocationReporter();
+
+            allocationReporter.onEnter(null, 0, AllocationReporter.SIZE_UNKNOWN);
+
+            long size = data instanceof RTypedValue ? getSize((RTypedValue) data) : AllocationReporter.SIZE_UNKNOWN;
+            allocationReporter.onReturnValue(data, 0, size);
+        }
+        for (Listener listener : listeners) {
+            listener.reportAllocation((RTypedValue) data);
+        }
+    }
+
     public interface Listener {
         /**
          * Invoked when an instance of an {@link RTypedValue} is created. Note that the initial
@@ -581,8 +639,14 @@ public final class RDataFactory {
      * Sets the listener of memory tracing events. For the time being there can only be one
      * listener. This can be extended to an array should we need more listeners.
      */
-    public static void addListener(Listener listener) {
+    public static synchronized void addListener(Listener listener) {
         listeners.addLast(listener);
+        updateTracingState();
+    }
+
+    public static synchronized void removeListener(Listener listener) {
+        listeners.remove(listener);
+        updateTracingState();
     }
 
     private static Object[] createRNullArray(int size) {
@@ -590,4 +654,28 @@ public final class RDataFactory {
         Arrays.fill(data, RNull.instance);
         return data;
     }
+
+    private static long getSize(RTypedValue data) {
+        long multiplier = 8;
+        switch (data.getRType()) {
+            case Complex:
+                multiplier = 16;
+                break;
+            case Integer:
+                multiplier = 4;
+                break;
+            case Logical:
+            case Raw:
+                multiplier = 1;
+                break;
+        }
+        if (data instanceof RSequence) {
+            return 32 + 2 * multiplier;
+        } else if (data instanceof RAbstractVector) {
+            return 32 + ((RAbstractVector) data).getLength() * multiplier;
+        } else {
+            // take a default value for non-vector objects
+            return 64;
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
index 4c064cf3cb5555c458fb56e9edbfaac35888062e..e8cbeb5a4e73d8d7f97be1fa5774fbfede93c691 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
@@ -80,5 +80,4 @@ public final class RExpression extends RListBase implements RAbstractVector {
     protected RExpression internalCopyResized(int size, boolean fillNA, int[] dimensions) {
         return RDataFactory.createExpression(copyResizedData(size, fillNA), dimensions);
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java
index 639450e7440cf0abbd65a88beda2d3f760389140..57aa7933b90f2b5c600d539a1aef31aa713390cd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExternalPtr.java
@@ -91,5 +91,4 @@ public class RExternalPtr extends RAttributeStorage implements RTypedValue {
     public RType getRType() {
         return RType.ExternalPtr;
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
index ed06179415b6664a02f7c636e3f3e317cea37ea4..aa46ff8da7eb3ac5072177291084578551044f86 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLanguage.java
@@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode;
  *
  */
 @ValueType
-public class RLanguage extends RSharingAttributeStorage implements RAbstractContainer {
+public final class RLanguage extends RSharingAttributeStorage implements RAbstractContainer {
 
     /*
      * Used for RLanguage construction from separate AST components.
@@ -76,6 +76,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
         this.length = length;
     }
 
+    @TruffleBoundary
     public static Object fromList(Object o, RLanguage.RepType type) {
         RList l;
         if (o instanceof RPairList) {
@@ -192,7 +193,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
     }
 
     @Override
-    public final void setNames(RStringVector newNames) {
+    public void setNames(RStringVector newNames) {
         if (list == null) {
             /* See getNames */
             RContext.getRRuntimeASTAccess().setNames(this, newNames);
@@ -240,7 +241,7 @@ public class RLanguage extends RSharingAttributeStorage implements RAbstractCont
         return String.format("RLanguage(rep=%s)", getRep());
     }
 
-    public final RPairList getPairListInternal() {
+    public RPairList getPairListInternal() {
         return this.list;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
index e0dea79dbdf32083f1d006f49363d8983aa5af67..4b0bb9a76b856198d26874513fa49fb2100aef33 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
@@ -79,5 +79,4 @@ public final class RList extends RListBase implements RAbstractListVector {
     protected RList internalCopyResized(int size, boolean fillNA, int[] dimensions) {
         return RDataFactory.createList(copyResizedData(size, fillNA), dimensions);
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
index ed3fc3d9597bbe51ceb02ee05f9d04aca3cccf33..3a1a9ebb4f4cbaaa1541878964a135926363ebcf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
@@ -206,5 +206,4 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
     public Object getDataAtAsObject(int index) {
         return getDataAt(index);
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
index cdb65dbbb957235d9dfec9dc55625d5da653694b..d00b8e455b51a5c1f9798159a6c029ea78f64191 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java
@@ -203,6 +203,17 @@ public class RPromise implements RTypedValue {
         return value;
     }
 
+    /**
+     * Discards any previously evaluated value if this is not an eager promise. This is for
+     * debugging purposes only!
+     */
+    public final void resetValue() {
+        // Only non-eager promises can be reset.
+        if (!PromiseState.isEager(state)) {
+            value = null;
+        }
+    }
+
     /**
      * Used in case the {@link RPromise} is evaluated outside.
      *
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
index 32e0a2c866408d7b66b444fa494d1a841ee705aa..712b3deb8dc0cb22f6c21155f4b7fd08e5253fe6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
@@ -94,6 +94,19 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
         return copy;
     }
 
+    public RStringVector copyResetData(String[] newData) {
+        boolean isComplete = true;
+        for (int i = 0; i < newData.length; i++) {
+            if (RRuntime.isNA(newData[i])) {
+                isComplete = false;
+                break;
+            }
+        }
+        RStringVector result = new RStringVector(newData, isComplete, null);
+        setAttributes(result);
+        return result;
+    }
+
     /**
      * Intended for external calls where a copy is not needed. WARNING: think carefully before using
      * this method rather than {@link #getDataCopy()}.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTruffleObject.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTruffleObject.java
index 89439de52f366b72b88796f90e1ff9f76697a565..a984127ef4c1c6e73154c2144a807cfac064c9df 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTruffleObject.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTruffleObject.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -26,6 +26,19 @@ import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.r.runtime.context.RContext;
 
+/**
+ * A tagging interface that indicates that a {@link TruffleObject} belongs to the R language. There
+ * are actually two sets of such types; those that are reflected at the R language level and
+ * therefore suitable for passing to other peer languages, e.g. {@link RIntVector}, and those that
+ * are used within the implementation for handling the {@code R FFI}, which uses Truffle interop
+ * internally. The latter types should not leak to other languages.
+ *
+ * As a convenience the interface provides a default implementation of
+ * {@link TruffleObject#getForeignAccess()} that indirects through
+ * {@link RContext#getRForeignAccessFactory()}. This is entirely optional and can be overridden to
+ * use an alternate implementation.
+ *
+ */
 public interface RTruffleObject extends TruffleObject {
     @Override
     default ForeignAccess getForeignAccess() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
index 153949e45e9d8ed54ec4614f4b6e9e51ffed9155..66a09ba04184c303325de0635064333a2497634e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
@@ -27,6 +27,8 @@ public interface RTypedValue extends RTruffleObject {
     int GP_BITS_MASK_SHIFT = 8;
     int GP_BITS_MASK = 0xFFFF << GP_BITS_MASK_SHIFT;
 
+    int S4_MASK_SHIFTED = 1 << (4 + GP_BITS_MASK_SHIFT);
+
     RType getRType();
 
     int getTypedValueInfo();
@@ -42,14 +44,14 @@ public interface RTypedValue extends RTruffleObject {
     }
 
     default boolean isS4() {
-        return (getGPBits() & S4_MASK) == S4_MASK;
+        return (getTypedValueInfo() & S4_MASK_SHIFTED) != 0;
     }
 
     default void setS4() {
-        setGPBits(getGPBits() | S4_MASK);
+        setTypedValueInfo(getTypedValueInfo() | S4_MASK_SHIFTED);
     }
 
     default void unsetS4() {
-        setGPBits(getGPBits() & ~S4_MASK);
+        setTypedValueInfo(getTypedValueInfo() & ~S4_MASK_SHIFTED);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/UpdateShareableChildValue.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/UpdateShareableChildValue.java
new file mode 100644
index 0000000000000000000000000000000000000000..c08e0b7a43d9932f8277adc99da06508dcd69cd7
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/UpdateShareableChildValue.java
@@ -0,0 +1,55 @@
+/*
+ * 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.runtime.data;
+
+public final class UpdateShareableChildValue {
+    private UpdateShareableChildValue() {
+    }
+
+    // slow-path implementation of the same algorithm as in UpdateShareableChildValueNode
+    public static <T> T update(Object originalOwner, T originalVal) {
+        if (!(originalVal instanceof RSharingAttributeStorage) || !(originalOwner instanceof RSharingAttributeStorage)) {
+            RSharingAttributeStorage.verify(originalOwner);
+            RSharingAttributeStorage.verify(originalVal);
+            return originalVal;
+        }
+
+        RSharingAttributeStorage val = (RSharingAttributeStorage) originalVal;
+        if (val.isShared()) {
+            return originalVal;
+        }
+
+        RSharingAttributeStorage owner = (RSharingAttributeStorage) originalOwner;
+        if (owner.isTemporary()) {
+            return originalVal;
+        }
+
+        if (val.isTemporary()) {
+            val.incRefCount();
+        }
+        if (owner.isShared()) {
+            val.incRefCount();
+        }
+        return originalVal;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
index b8ba2fe1c75518f24ba5f714d69ba7077ecbbd99..dcb01ee548ac70950daf8f94469abd7aa8adf2c2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
@@ -50,6 +50,7 @@ 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.RStringVector;
+import com.oracle.truffle.r.runtime.data.UpdateShareableChildValue;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
 import com.oracle.truffle.r.runtime.env.frame.NSBaseMaterializedFrame;
 import com.oracle.truffle.r.runtime.env.frame.REnvEmptyFrameAccess;
@@ -181,7 +182,7 @@ public abstract class REnvironment extends RAttributeStorage {
 
         @TruffleBoundary
         public PutException(RError.Message msg, Object... args) {
-            super(msg, args);
+            super(null, msg, args);
         }
     }
 
@@ -589,7 +590,7 @@ public abstract class REnvironment extends RAttributeStorage {
         private static final long serialVersionUID = 1L;
 
         DetachException(RError.Message msg, Object... args) {
-            super(msg, args);
+            super(null, msg, args);
         }
     }
 
@@ -666,7 +667,7 @@ public abstract class REnvironment extends RAttributeStorage {
         RStringVector names = list.getNames();
         for (int i = 0; i < list.getLength(); i++) {
             try {
-                result.put(names.getDataAt(i), list.getDataAt(i));
+                result.put(names.getDataAt(i), UpdateShareableChildValue.update(list, list.getDataAt(i)));
             } catch (PutException ex) {
                 throw RError.error(RError.SHOW_CALLER2, ex);
             }
@@ -676,7 +677,7 @@ public abstract class REnvironment extends RAttributeStorage {
 
     // END of static methods
 
-    private static final String NAMESPACE_KEY = ".__NAMESPACE__.";
+    public static final String NAMESPACE_KEY = ".__NAMESPACE__.";
 
     /**
      * GnuR creates {@code Namespace} environments in {@code namespace.R} using {@code new.env} and
@@ -910,32 +911,67 @@ public abstract class REnvironment extends RAttributeStorage {
         return getPrintName();
     }
 
-    public static void convertSearchpathToMultiSlot() {
+    public static <T> void applyToSearchPath(SearchPathFun fun) {
         CompilerAsserts.neverPartOfCompilation();
         RContext.markNonSingle();
         ContextStateImpl parentState = RContext.getInstance().stateREnvironment;
         SearchPath searchPath = parentState.getSearchPath();
         assert searchPath.size() > 0 && searchPath.get(0).getSearchName() == Global.SEARCHNAME;
         // for global space don't replicate entries as all contexts should see their own values
-        FrameSlotChangeMonitor.handleAllMultiSlots(searchPath.get(0).getFrame(), false);
+        fun.apply(searchPath.get(0).getFrame(), false);
         for (int i = 1; i < searchPath.size(); i++) {
-            FrameSlotChangeMonitor.handleAllMultiSlots(searchPath.get(i).getFrame(), true);
+            fun.apply(searchPath.get(i).getFrame(), true);
         }
         REnvironment namespaces = parentState.namespaceRegistry;
         Frame namespacesFrame = namespaces.getFrame();
+        fun.apply(namespacesFrame, true);
         // make a copy avoid potential updates to the array iterated over
         FrameSlot[] slots = new FrameSlot[namespacesFrame.getFrameDescriptor().getSlots().size()];
         slots = namespacesFrame.getFrameDescriptor().getSlots().toArray(slots);
         for (int i = 0; i < slots.length; i++) {
-            REnvironment namespaceEnv = (REnvironment) namespacesFrame.getValue(slots[i]);
+            REnvironment namespaceEnv = (REnvironment) FrameSlotChangeMonitor.getValue(slots[i], namespacesFrame);
             if (namespaceEnv != Base.baseNamespaceEnv()) {
                 // base namespace frame redirects all accesses to base frame and this would
                 // result in processing the slots twice
-                FrameSlotChangeMonitor.handleAllMultiSlots(namespaceEnv.getFrame(), true);
+                fun.apply(namespaceEnv.getFrame(), true);
             }
         }
     }
 
+    private interface SearchPathFun {
+        void apply(Frame frame, boolean replicate);
+    }
+
+    public static void convertSearchpathToMultiSlot(int[] indices) {
+        applyToSearchPath(new SearchPathFun() {
+
+            @Override
+            public void apply(Frame frame, boolean replicate) {
+                FrameSlotChangeMonitor.handleAllMultiSlots(frame, indices, replicate);
+            }
+        });
+    }
+
+    public static void cleanupSearchpathFromMultiSlot() {
+        applyToSearchPath(new SearchPathFun() {
+
+            @Override
+            public void apply(Frame frame, boolean replicate) {
+                FrameSlotChangeMonitor.cleanMultiSlots(frame, null);
+            }
+        });
+    }
+
+    public static void cleanupSearchpathFromMultiSlot(int[] multiSlotIndices) {
+        applyToSearchPath(new SearchPathFun() {
+
+            @Override
+            public void apply(Frame frame, boolean replicate) {
+                FrameSlotChangeMonitor.cleanMultiSlots(frame, multiSlotIndices);
+            }
+        });
+    }
+
     private static final class BaseNamespace extends REnvironment {
         private BaseNamespace(String name, MaterializedFrame frame) {
             super(name, frame);
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 c93bf6935e6818f563f04f9fb608e2a658bee006..3d0ebeeded4794001e641a87ef5fb5bd729c9423 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
@@ -26,6 +26,8 @@ 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.KeyInfo;
+import com.oracle.truffle.api.interop.KeyInfo.Builder;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
@@ -43,6 +45,8 @@ 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;
+import com.oracle.truffle.r.runtime.env.frame.REnvFrameAccess;
+import com.oracle.truffle.r.runtime.env.frame.REnvTruffleFrameAccess;
 
 /**
  * Represents a variable scope for external tools like a debugger.<br>
@@ -91,17 +95,19 @@ public final class RScope extends AbstractScope {
 
     @Override
     protected Object getVariables(Frame frame) {
-        return new VariablesMapObject(env, false);
+        return new EnvVariablesObject(env, false);
     }
 
     private static REnvironment getEnv(Frame frame) {
-        assert RArguments.isRFrame(frame);
-        return REnvironment.frameToEnvironment(frame.materialize());
+        if (RArguments.isRFrame(frame)) {
+            return REnvironment.frameToEnvironment(frame.materialize());
+        }
+        return null;
     }
 
     @Override
     protected Object getArguments(Frame frame) {
-        return new VariablesMapObject(env, true);
+        return new EnvVariablesObject(env, true);
     }
 
     @Override
@@ -112,30 +118,12 @@ public final class RScope extends AbstractScope {
         return new RScope(env.getParent());
     }
 
-    private static String[] ls(REnvironment env) {
-        RStringVector ls = env.ls(true, null, false);
-        return ls.getDataWithoutCopying();
-    }
-
-    private static String[] collectArgs(REnvironment env) {
-
-        if (env != REnvironment.emptyEnv()) {
-            assert RArguments.isRFrame(env.getFrame());
-            RFunction f = RArguments.getFunction(env.getFrame());
-            if (f != null) {
-                return RContext.getRRuntimeASTAccess().getArgumentsSignature(f).getNames();
-            } else {
-                ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(env.getFrame());
-                if (suppliedSignature != null) {
-                    return suppliedSignature.getNames();
-                }
-            }
+    public static AbstractScope createScope(Node node, Frame frame) {
+        REnvironment env = getEnv(frame);
+        if (env != null && env != REnvironment.emptyEnv()) {
+            return new RScope(node.getRootNode(), env);
         }
-        return new String[0];
-    }
-
-    public static RScope createScope(Node node, Frame frame) {
-        return new RScope(node.getRootNode(), getEnv(frame));
+        return new GenericScope(node, frame.materialize());
     }
 
     /**
@@ -150,38 +138,81 @@ public final class RScope extends AbstractScope {
         return obj;
     }
 
-    static final class VariablesMapObject implements TruffleObject {
+    private static final class GenericScope extends AbstractScope {
 
-        private final REnvironment env;
+        private final MaterializedFrame mFrame;
+        private final Node node;
+
+        protected GenericScope(Node node, MaterializedFrame frame) {
+            this.node = node;
+            this.mFrame = frame;
+        }
+
+        @Override
+        protected String getName() {
+            return node.getRootNode().getName();
+        }
+
+        @Override
+        protected Node getNode() {
+            return node;
+        }
+
+        @Override
+        protected Object getVariables(Frame frame) {
+            return new GenericVariablesObject(mFrame, false);
+        }
+
+        @Override
+        protected Object getArguments(Frame frame) {
+            return new GenericVariablesObject(mFrame, true);
+        }
+
+        @Override
+        protected AbstractScope findParent() {
+            return null;
+        }
+    }
+
+    abstract static class VariablesObject implements TruffleObject {
+
+        private final REnvFrameAccess frameAccess;
         private final boolean argumentsOnly;
 
-        private VariablesMapObject(REnvironment env, boolean argumentsOnly) {
-            this.env = env;
+        private VariablesObject(REnvFrameAccess frameAccess, boolean argumentsOnly) {
+            this.frameAccess = frameAccess;
             this.argumentsOnly = argumentsOnly;
         }
 
         @Override
         public ForeignAccess getForeignAccess() {
-            return VariablesMapMessageResolutionForeign.ACCESS;
+            return VariablesMessageResolutionForeign.ACCESS;
+        }
+
+        private String[] ls() {
+            RStringVector ls = frameAccess.ls(true, null, false);
+            return ls.getDataWithoutCopying();
         }
 
         public static boolean isInstance(TruffleObject obj) {
-            return obj instanceof VariablesMapObject;
+            return obj instanceof VariablesObject;
         }
 
-        @MessageResolution(receiverType = VariablesMapObject.class)
-        static final class VariablesMapMessageResolution {
+        protected abstract String[] collectArgs();
+
+        @MessageResolution(receiverType = VariablesObject.class)
+        static final class VariablesMessageResolution {
 
             @Resolve(message = "KEYS")
             abstract static class VarsMapKeysNode extends Node {
 
                 @TruffleBoundary
-                public Object access(VariablesMapObject varMap) {
-                    String[] names;
+                public Object access(VariablesObject varMap) {
+                    String[] names = null;
                     if (varMap.argumentsOnly) {
-                        names = collectArgs(varMap.env);
+                        names = varMap.collectArgs();
                     } else {
-                        names = ls(varMap.env);
+                        names = varMap.ls();
                     }
                     return new ArgumentNamesObject(names);
                 }
@@ -190,21 +221,17 @@ public final class RScope extends AbstractScope {
             @Resolve(message = "KEY_INFO")
             public abstract static class VarMapsKeyInfoNode extends Node {
 
-                private static final int READABLE = 1 << 1;
-                private static final int WRITABLE = 1 << 2;
-                private static final int INVOCABLE = 1 << 3;
-
-                @SuppressWarnings("try")
-                protected Object access(VariablesMapObject receiver, String identifier) {
-                    int info = READABLE;
+                protected Object access(VariablesObject receiver, String identifier) {
+                    Builder builder = KeyInfo.newBuilder();
+                    builder.setReadable(true);
 
-                    if (!receiver.env.bindingIsLocked(identifier)) {
-                        info += WRITABLE;
+                    if (!receiver.frameAccess.bindingIsLocked(identifier)) {
+                        builder.setWritable(true);
                     }
-                    if (receiver.env.get(identifier) instanceof RFunction) {
-                        info += INVOCABLE;
+                    if (receiver.frameAccess.get(identifier) instanceof RFunction) {
+                        builder.setInvocable(true);
                     }
-                    return info;
+                    return builder.build();
                 }
             }
 
@@ -212,11 +239,11 @@ public final class RScope extends AbstractScope {
             abstract static class VarsMapReadNode extends Node {
 
                 @TruffleBoundary
-                public Object access(VariablesMapObject varMap, String name) {
-                    if (varMap.env == null) {
+                public Object access(VariablesObject varMap, String name) {
+                    if (varMap.frameAccess == null) {
                         throw UnsupportedMessageException.raise(Message.READ);
                     }
-                    Object value = varMap.env.get(name);
+                    Object value = varMap.frameAccess.get(name);
 
                     // If Java-null is returned, the identifier does not exist !
                     if (value == null) {
@@ -231,22 +258,61 @@ public final class RScope extends AbstractScope {
             abstract static class VarsMapWriteNode extends Node {
 
                 @TruffleBoundary
-                public Object access(VariablesMapObject varMap, String name, Object value) {
-                    if (varMap.env == null) {
+                public Object access(VariablesObject varMap, String name, Object value) {
+                    if (varMap.frameAccess == null) {
                         throw UnsupportedMessageException.raise(Message.WRITE);
                     }
                     if (!(value instanceof RTypedValue)) {
                         throw UnsupportedTypeException.raise(new Object[]{value});
                     }
                     try {
-                        varMap.env.put(name, value);
+                        varMap.frameAccess.put(name, value);
                         return value;
                     } catch (PutException e) {
                         throw RInternalError.shouldNotReachHere(e);
                     }
                 }
             }
+        }
+    }
+
+    static final class EnvVariablesObject extends VariablesObject {
+
+        private final REnvironment env;
 
+        private EnvVariablesObject(REnvironment env, boolean argumentsOnly) {
+            super(new REnvTruffleFrameAccess(env.getFrame()), argumentsOnly);
+            this.env = env;
+        }
+
+        @Override
+        protected String[] collectArgs() {
+
+            if (env != REnvironment.emptyEnv()) {
+                assert RArguments.isRFrame(env.getFrame());
+                RFunction f = RArguments.getFunction(env.getFrame());
+                if (f != null) {
+                    return RContext.getRRuntimeASTAccess().getArgumentsSignature(f).getNames();
+                } else {
+                    ArgumentsSignature suppliedSignature = RArguments.getSuppliedSignature(env.getFrame());
+                    if (suppliedSignature != null) {
+                        return suppliedSignature.getNames();
+                    }
+                }
+            }
+            return new String[0];
+        }
+    }
+
+    static final class GenericVariablesObject extends VariablesObject {
+
+        private GenericVariablesObject(MaterializedFrame frame, boolean argumentsOnly) {
+            super(new REnvTruffleFrameAccess(frame), argumentsOnly);
+        }
+
+        @Override
+        protected String[] collectArgs() {
+            return new String[0];
         }
     }
 
@@ -300,8 +366,6 @@ public final class RScope extends AbstractScope {
                     }
                 }
             }
-
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
index 892566e5bf11b2a9067369e42ae9b843a4f01afd..2fda68c09347c0694ba0396078276920e2dae205 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/ActiveBinding.java
@@ -69,5 +69,4 @@ public class ActiveBinding implements RTruffleObject {
     public Object readValue() {
         return RContext.getEngine().evalFunction(function, REnvironment.baseEnv().getFrame(), RCaller.createInvalid(null), true, null);
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
index 8c7e60ef51c8b7702fac9021c1b41902a2c9d1fa..47d82e72ec4d51d22f415a1e825236a9454ed16c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java
@@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.StableValue;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.ChildContextInfo;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RPromise;
 
@@ -189,7 +189,7 @@ public final class FrameSlotChangeMonitor {
 
         private WeakReference<FrameDescriptor> enclosingFrameDescriptor = new WeakReference<>(null);
         private Assumption enclosingFrameDescriptorAssumption = Truffle.getRuntime().createAssumption("enclosing frame descriptor");
-        private Assumption containsNoActiveBindingAssumption = Truffle.getRuntime().createAssumption("contains no active binding");
+        private final Assumption containsNoActiveBindingAssumption = Truffle.getRuntime().createAssumption("contains no active binding");
 
         private FrameDescriptorMetaData(String name, MaterializedFrame singletonFrame) {
             this.name = name;
@@ -374,14 +374,15 @@ public final class FrameSlotChangeMonitor {
         invalidateAllNames(target);
 
         FrameDescriptor oldEnclosingDescriptor = target.getEnclosingFrameDescriptor();
-        assert (oldEnclosingDescriptor == null) == (oldEnclosingFrame == null) : "mismatch " + oldEnclosingDescriptor + " / " + oldEnclosingFrame;
+        FrameDescriptor newEnclosingDescriptor = handleBaseNamespaceEnv(newEnclosingFrame);
+        assert newEnclosingDescriptor == oldEnclosingDescriptor || (oldEnclosingDescriptor == null) == (oldEnclosingFrame == null) : "mismatch " + oldEnclosingDescriptor + " / " + oldEnclosingFrame;
 
         if (oldEnclosingDescriptor != null) {
-            assert oldEnclosingDescriptor == oldEnclosingFrame.getFrameDescriptor() : "mismatch " + oldEnclosingDescriptor + " / " + oldEnclosingFrame.getFrameDescriptor();
+            assert newEnclosingDescriptor == oldEnclosingDescriptor || oldEnclosingDescriptor == oldEnclosingFrame.getFrameDescriptor() : "mismatch " + oldEnclosingDescriptor + " / " +
+                            oldEnclosingFrame.getFrameDescriptor();
             FrameDescriptorMetaData oldEnclosing = getMetaData(oldEnclosingDescriptor);
             oldEnclosing.subDescriptors.remove(descriptor);
         }
-        FrameDescriptor newEnclosingDescriptor = handleBaseNamespaceEnv(newEnclosingFrame);
         target.updateEnclosingFrameDescriptor(newEnclosingDescriptor);
 
         if (newEnclosingDescriptor != null) {
@@ -460,7 +461,15 @@ public final class FrameSlotChangeMonitor {
 
     public static final class MultiSlotData {
 
-        private final Object[] data = new Object[ContextInfo.contextNum()];
+        private final Object[] data;
+
+        public MultiSlotData(MultiSlotData prevValue) {
+            data = Arrays.copyOf(prevValue.data, ChildContextInfo.contextNum());
+        }
+
+        public MultiSlotData() {
+            data = new Object[ChildContextInfo.contextNum()];
+        }
 
         public Object get(int ind) {
             return data[ind];
@@ -473,7 +482,6 @@ public final class FrameSlotChangeMonitor {
         public void setAll(Object val) {
             Arrays.fill(data, val);
         }
-
     }
 
     private static final class FrameSlotInfoImpl {
@@ -600,14 +608,13 @@ public final class FrameSlotChangeMonitor {
             }
         }
 
-        public static void handleSearchPathMultiSlot(Frame frame, FrameSlot slot, boolean replicate) {
+        public static void handleSearchPathMultiSlot(Frame frame, FrameSlot slot, int[] indices, boolean replicate) {
             CompilerAsserts.neverPartOfCompilation();
             while (true) {
                 FrameSlotInfoImpl info = (FrameSlotInfoImpl) slot.getInfo();
                 if (info.stableValue == null || !replicate) {
                     // create a multi slot for slots whose stableValue is null but also for all
-                    // slots of
-                    // the global frame (which are marked as !replicate)
+                    // slots of the global frame (which are marked as !replicate)
                     info.stableValue = null;
                     info.nonLocalModifiedAssumption.invalidate();
                     info.noMultiSlot.invalidate();
@@ -617,20 +624,28 @@ public final class FrameSlotChangeMonitor {
                     // TODO: do we have to worry that prevValue can be invalid?
                     if (prevValue instanceof MultiSlotData) {
                         // this handles the case when we create share contexts for the second time -
-                        // existing multi slots are an artifact of the previous executions and must
-                        // be
-                        // discarded
-                        // TOOD: consider re-using multi slots but since we don't expect many of
-                        // them,
-                        // perhaps it's too much work for too little gain
+                        // existing multi slots are an artifact of a previous executions and must
+                        // be extended
+                        // TODO: consider re-using multi slots but since we don't expect many of
+                        // them, perhaps it's too much work for too little gain
+                        data = new MultiSlotData((MultiSlotData) prevValue);
                         prevValue = ((MultiSlotData) prevValue).get(0);
-                    } else if (FastROptions.SearchPathForcePromises.getBooleanValue()) {
-                        prevValue = RContext.getRRuntimeASTAccess().forcePromise("searchPathPromiseForce", prevValue);
-                    }
-                    if (replicate) {
-                        data.setAll(prevValue);
+
+                        // replicate value only for newly created child contexts
+                        if (replicate) {
+                            for (int i : indices) {
+                                data.set(i, prevValue);
+                            }
+                        }
                     } else {
-                        data.set(0, prevValue);
+                        if (FastROptions.SearchPathForcePromises.getBooleanValue()) {
+                            prevValue = RContext.getRRuntimeASTAccess().forcePromise("searchPathPromiseForce", prevValue);
+                        }
+                        if (replicate) {
+                            data.setAll(prevValue);
+                        } else {
+                            data.set(0, prevValue);
+                        }
                     }
                     frame.setObject(slot, data);
                     break;
@@ -640,7 +655,6 @@ public final class FrameSlotChangeMonitor {
                     }
                     // otherwise stable value may get nullified and slot turned into multi slot
                 }
-
             }
         }
 
@@ -920,14 +934,12 @@ public final class FrameSlotChangeMonitor {
     /*
      * This method should be called for frames of all environments on the search path.
      */
-    public static void handleAllMultiSlots(Frame frame, boolean replicate) {
+    public static void handleAllMultiSlots(Frame frame, int[] indices, boolean replicate) {
         // make a copy avoid potential updates to the array iterated over
         FrameSlot[] slots = new FrameSlot[frame.getFrameDescriptor().getSlots().size()];
         slots = frame.getFrameDescriptor().getSlots().toArray(slots);
         for (int i = 0; i < slots.length; i++) {
-            if (!(slots[i].getIdentifier() instanceof RFrameSlot)) {
-                FrameSlotInfoImpl.handleSearchPathMultiSlot(frame, slots[i], replicate);
-            }
+            FrameSlotInfoImpl.handleSearchPathMultiSlot(frame, slots[i], indices, replicate);
         }
     }
 
@@ -974,4 +986,32 @@ public final class FrameSlotChangeMonitor {
             return frame.getValue(slot);
         }
     }
+
+    /**
+     * Nullifies a set of slots in a {@link MultiSlotData} to avoid memory leaks. When providing
+     * {@code null} as indices, alls subslots except the first one are nullified.
+     */
+    public static void cleanMultiSlots(Frame frame, int[] indices) {
+        CompilerAsserts.neverPartOfCompilation();
+        // make a copy avoid potential updates to the array iterated over
+        FrameSlot[] slots = frame.getFrameDescriptor().getSlots().toArray(new FrameSlot[0]);
+
+        for (int i = 0; i < slots.length; i++) {
+            Object value = frame.getValue(slots[i]);
+            if (value instanceof MultiSlotData) {
+                MultiSlotData msd = (MultiSlotData) value;
+                if (indices != null) {
+                    for (int j = 0; j < indices.length; j++) {
+                        assert indices[j] != 0;
+                        msd.set(indices[j], null);
+                    }
+                } else {
+                    // only safe value of primordial context
+                    Object initialValue = msd.get(0);
+                    msd.setAll(null);
+                    msd.set(0, initialValue);
+                }
+            }
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java
index 29afedc8a40c5c747d5969575a8bcff44d5706af..2a6ad6919008ef22802b97f96c276d9377bab21f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/BaseRFFI.java
@@ -26,7 +26,7 @@ import java.io.IOException;
 import java.util.ArrayList;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * A statically typed interface to exactly those native functions required by the R {@code base}
@@ -34,50 +34,51 @@ import com.oracle.truffle.api.nodes.Node;
  * map 1-1 to a native function, they may involve the invocation of several native functions.
  */
 public interface BaseRFFI {
-    abstract class GetpidNode extends Node {
-        public abstract int execute();
 
-        public static GetpidNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createGetpidNode();
+    interface GetpidNode extends NodeInterface {
+        int execute();
+
+        static GetpidNode create() {
+            return RFFIFactory.getBaseRFFI().createGetpidNode();
         }
     }
 
-    abstract class GetwdNode extends Node {
+    interface GetwdNode extends NodeInterface {
         /**
          * Returns the current working directory, in the face of calls to {@code setwd}.
          */
-        public abstract String execute();
+        String execute();
 
-        public static GetwdNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createGetwdNode();
+        static GetwdNode create() {
+            return RFFIFactory.getBaseRFFI().createGetwdNode();
         }
     }
 
-    abstract class SetwdNode extends Node {
+    interface SetwdNode extends NodeInterface {
         /**
          * Sets the current working directory to {@code dir}. (cf. Unix {@code chdir}).
          *
          * @return 0 if successful.
          */
-        public abstract int execute(String dir);
+        int execute(String dir);
 
-        public static SetwdNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createSetwdNode();
+        static SetwdNode create() {
+            return RFFIFactory.getBaseRFFI().createSetwdNode();
         }
     }
 
-    abstract class MkdirNode extends Node {
+    interface MkdirNode extends NodeInterface {
         /**
-         * Create directory with given mode. Exception is thrown omn error.
+         * Create directory with given mode. Exception is thrown on error.
          */
-        public abstract void execute(String dir, int mode) throws IOException;
+        void execute(String dir, int mode) throws IOException;
 
-        public static MkdirNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createMkdirNode();
+        static MkdirNode create() {
+            return RFFIFactory.getBaseRFFI().createMkdirNode();
         }
     }
 
-    abstract class ReadlinkNode extends Node {
+    interface ReadlinkNode extends NodeInterface {
         /**
          * Try to convert a symbolic link to it's target.
          *
@@ -85,44 +86,44 @@ public interface BaseRFFI {
          * @return the target if {@code path} is a link else {@code null}
          * @throws IOException for any other error except "not a link"
          */
-        public abstract String execute(String path) throws IOException;
+        String execute(String path) throws IOException;
 
-        public static ReadlinkNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createReadlinkNode();
+        static ReadlinkNode create() {
+            return RFFIFactory.getBaseRFFI().createReadlinkNode();
         }
     }
 
-    abstract class MkdtempNode extends Node {
+    interface MkdtempNode extends NodeInterface {
         /**
          * Creates a temporary directory using {@code template} and return the resulting path or
          * {@code null} if error.
          */
-        public abstract String execute(String template);
+        String execute(String template);
 
-        public static MkdtempNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createMkdtempNode();
+        static MkdtempNode create() {
+            return RFFIFactory.getBaseRFFI().createMkdtempNode();
         }
     }
 
-    abstract class ChmodNode extends Node {
+    interface ChmodNode extends NodeInterface {
         /**
          * Change the file mode of {@code path}.
          */
-        public abstract int execute(String path, int mode);
+        int execute(String path, int mode);
 
-        public static ChmodNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createChmodNode();
+        static ChmodNode create() {
+            return RFFIFactory.getBaseRFFI().createChmodNode();
         }
     }
 
-    abstract class StrolNode extends Node {
+    interface StrolNode extends NodeInterface {
         /**
          * Convert string to long.
          */
-        public abstract long execute(String s, int base) throws IllegalArgumentException;
+        long execute(String s, int base) throws IllegalArgumentException;
 
-        public static StrolNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createStrolNode();
+        static StrolNode create() {
+            return RFFIFactory.getBaseRFFI().createStrolNode();
         }
     }
 
@@ -138,27 +139,27 @@ public interface BaseRFFI {
         String nodename();
     }
 
-    abstract class UnameNode extends Node {
+    interface UnameNode extends NodeInterface {
         /**
          * Return {@code utsname} info.
          */
-        public abstract UtsName execute();
+        UtsName execute();
 
-        public static UnameNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createUnameNode();
+        static UnameNode create() {
+            return RFFIFactory.getBaseRFFI().createUnameNode();
         }
     }
 
-    abstract class GlobNode extends Node {
+    interface GlobNode extends NodeInterface {
         /**
          * Returns an array of pathnames that match {@code pattern} using the OS glob function. This
          * is done in native code because it is very hard to write in Java in the face of
          * {@code setwd}.
          */
-        public abstract ArrayList<String> glob(String pattern);
+        ArrayList<String> glob(String pattern);
 
-        public static GlobNode create() {
-            return RFFIFactory.getRFFI().getBaseRFFI().createGlobNode();
+        static GlobNode create() {
+            return RFFIFactory.getBaseRFFI().createGlobNode();
         }
     }
 
@@ -196,7 +197,7 @@ public interface BaseRFFI {
         private static GetpidRootNode getpidRootNode;
 
         private GetpidRootNode() {
-            super(RFFIFactory.getRFFI().getBaseRFFI().createGetpidNode());
+            super(RFFIFactory.getBaseRFFI().createGetpidNode());
         }
 
         @Override
@@ -216,7 +217,7 @@ public interface BaseRFFI {
         private static GetwdRootNode getwdRootNode;
 
         private GetwdRootNode() {
-            super(RFFIFactory.getRFFI().getBaseRFFI().createGetwdNode());
+            super(RFFIFactory.getBaseRFFI().createGetwdNode());
         }
 
         @Override
@@ -236,7 +237,7 @@ public interface BaseRFFI {
         private static MkdtempRootNode mkdtempRootNode;
 
         private MkdtempRootNode() {
-            super(RFFIFactory.getRFFI().getBaseRFFI().createMkdtempNode());
+            super(RFFIFactory.getBaseRFFI().createMkdtempNode());
         }
 
         @Override
@@ -257,7 +258,7 @@ public interface BaseRFFI {
         private static UnameRootNode unameRootNode;
 
         private UnameRootNode() {
-            super(RFFIFactory.getRFFI().getBaseRFFI().createUnameNode());
+            super(RFFIFactory.getBaseRFFI().createUnameNode());
         }
 
         @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java
index 8d0949631ee56fc97910b13fafdbb658d5434617..070fb25fb0d4ad831bc43084f25de50b58cef01c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java
@@ -22,19 +22,23 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * Support for the {.C} and {.Fortran} calls.
  */
 public interface CRFFI {
-    abstract class InvokeCNode extends Node {
+    interface InvokeCNode extends NodeInterface {
         /**
          * Invoke the native method identified by {@code symbolInfo} passing it the arguments in
          * {@code args}. The values in {@code args} should be native types,e.g., {@code double[]}
-         * not {@code RDoubleVector}.
+         * not {@code RDoubleVector}. Strings are already converted to 2-dimensional byte arrays.
+         *
+         * @param hasStrings if {@code true}, then the {@code args} array may contain one or more
+         *            values of type {@code byte[][]}, which represent arrays of strings in ASCII
+         *            encoding.
          */
-        public abstract void execute(NativeCallInfo nativeCallInfo, Object[] args);
+        void execute(NativeCallInfo nativeCallInfo, Object[] args, boolean hasStrings);
     }
 
     InvokeCNode createInvokeCNode();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
index 19de11e00e6a455f942f8dec4ed711f07faf0708..19f20718cee563658ec4faf3b1e65b009706c34e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
@@ -23,28 +23,27 @@
 package com.oracle.truffle.r.runtime.ffi;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 import com.oracle.truffle.r.runtime.data.RNull;
 
 /**
  * Support for the {.Call} and {.External} calls.
  */
 public interface CallRFFI {
-    abstract class InvokeCallNode extends Node {
+    interface InvokeCallNode extends NodeInterface {
         /**
          * Invoke the native function identified by {@code symbolInfo} passing it the arguments in
          * {@code args}. The values in {@code args} can be any of the types used to represent
          * {@code R} values in the implementation.
          */
-        public abstract Object execute(NativeCallInfo nativeCallInfo, Object[] args);
+        Object execute(NativeCallInfo nativeCallInfo, Object[] args);
     }
 
-    abstract class InvokeVoidCallNode extends Node {
+    interface InvokeVoidCallNode extends NodeInterface {
         /**
          * Variant that does not return a result (primarily for library "init" methods).
          */
-        public abstract void execute(NativeCallInfo nativeCallInfo, Object[] args);
-
+        void execute(NativeCallInfo nativeCallInfo, Object[] args);
     }
 
     InvokeCallNode createInvokeCallNode();
@@ -55,7 +54,7 @@ public interface CallRFFI {
         private static InvokeCallRootNode invokeCallRootNode;
 
         private InvokeCallRootNode() {
-            super(RFFIFactory.getRFFI().getCallRFFI().createInvokeCallNode());
+            super(RFFIFactory.getCallRFFI().createInvokeCallNode());
         }
 
         @Override
@@ -76,7 +75,7 @@ public interface CallRFFI {
         private static InvokeVoidCallRootNode InvokeVoidCallRootNode;
 
         private InvokeVoidCallRootNode() {
-            super(RFFIFactory.getRFFI().getCallRFFI().createInvokeVoidCallNode());
+            super(RFFIFactory.getCallRFFI().createInvokeVoidCallNode());
         }
 
         @Override
@@ -93,5 +92,4 @@ public interface CallRFFI {
             return InvokeVoidCallRootNode;
         }
     }
-
 }
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 b6969e1e37aca0b51d612c706f7f30191e31d3cc..4bf6fc5df3017989027c04c09bd60e0648dff815 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
@@ -19,18 +19,20 @@ import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RError.RErrorException;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.context.RContext.ContextState;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
@@ -40,6 +42,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI.InvokeVoidCallNode;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.rng.user.UserRNG;
 
 /**
@@ -82,7 +85,7 @@ public class DLL {
         @Override
         public ContextState initialize(RContext contextArg) {
             this.context = contextArg;
-            if (context.getKind() == RContext.ContextKind.SHARE_PARENT_RW) {
+            if (isShareDLLKind(context.getKind())) {
                 list = context.getParent().stateDLL.list;
             } else {
                 list = new ArrayList<>();
@@ -96,7 +99,7 @@ public class DLL {
 
         @Override
         public void beforeDestroy(RContext contextArg) {
-            if (context.getKind() != RContext.ContextKind.SHARE_PARENT_RW) {
+            if (!isShareDLLKind(context.getKind())) {
                 for (int i = 1; i < list.size(); i++) {
                     DLLInfo dllInfo = list.get(i);
                     DLLRFFI.DLCloseRootNode.create().getCallTarget().call(dllInfo.handle);
@@ -105,6 +108,10 @@ public class DLL {
             list = null;
         }
 
+        private static boolean isShareDLLKind(RContext.ContextKind kind) {
+            return kind == ContextKind.SHARE_PARENT_RW || kind == ContextKind.SHARE_ALL;
+        }
+
         private void addLibR(DLLInfo dllInfo) {
             assert list.isEmpty();
             list.add(dllInfo);
@@ -364,11 +371,15 @@ public class DLL {
             }
         }
 
+        public boolean isLong() {
+            return value instanceof Long;
+        }
+
         public TruffleObject asTruffleObject() {
             if (value instanceof TruffleObject) {
                 return (TruffleObject) value;
             } else {
-                throw RInternalError.shouldNotReachHere();
+                throw RInternalError.shouldNotReachHere("value: " + value);
             }
         }
     }
@@ -395,8 +406,8 @@ public class DLL {
     public static class DLLException extends RErrorException {
         private static final long serialVersionUID = 1L;
 
-        public DLLException(RError.Message msg, Object... args) {
-            super(msg, args);
+        public DLLException(Throwable cause, RError.Message msg, Object... args) {
+            super(cause, msg, args);
         }
     }
 
@@ -405,7 +416,7 @@ public class DLL {
      */
     public static void loadLibR(String path) {
         RContext context = RContext.getInstance();
-        Object handle = DLLRFFI.DLOpenRootNode.create().getCallTarget().call(path, false, false);
+        Object handle = DLLRFFI.DLOpenRootNode.create(context).call(path, false, false);
         if (handle == null) {
             throw Utils.rSuicide("error loading libR from: " + path + "\n");
         }
@@ -427,8 +438,8 @@ public class DLL {
 
     public static class LoadPackageDLLNode extends Node {
         @Child private InvokeVoidCallNode invokeVoidCallNode;
-        @Child private DLLRFFI.DLSymNode dlSymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
-        @Child private DLLRFFI.DLOpenNode dlOpenNode = RFFIFactory.getRFFI().getDLLRFFI().createDLOpenNode();
+        @Child private DLLRFFI.DLSymNode dlSymNode = RFFIFactory.getDLLRFFI().createDLSymNode();
+        @Child private DLLRFFI.DLOpenNode dlOpenNode = RFFIFactory.getDLLRFFI().createDLOpenNode();
 
         public static LoadPackageDLLNode create() {
             return new LoadPackageDLLNode();
@@ -453,18 +464,18 @@ public class DLL {
                 try {
                     if (invokeVoidCallNode == null) {
                         CompilerDirectives.transferToInterpreterAndInvalidate();
-                        invokeVoidCallNode = insert(RFFIFactory.getRFFI().getCallRFFI().createInvokeVoidCallNode());
+                        invokeVoidCallNode = (InvokeVoidCallNode) insert((Node) RFFIFactory.getCallRFFI().createInvokeVoidCallNode());
                     }
                     invokeVoidCallNode.execute(new NativeCallInfo(pkgInit, initFunc, dllInfo), new Object[]{dllInfo});
                 } catch (ReturnException ex) {
                     // An error call can, due to condition handling, throw this which we must
-                    // propogate
+                    // propagate
                     throw ex;
                 } catch (Throwable ex) {
                     if (RContext.isInitialContextInitialized()) {
-                        throw new DLLException(RError.Message.DLL_RINIT_ERROR);
+                        throw new DLLException(ex, RError.Message.DLL_RINIT_ERROR);
                     } else {
-                        throw Utils.rSuicide(RError.Message.DLL_RINIT_ERROR.message + " on default package: " + path);
+                        throw Utils.rSuicide(ex, RError.Message.DLL_RINIT_ERROR.message + " on default package: " + path);
                     }
                 }
             } catch (UnsatisfiedLinkError ex) {
@@ -488,17 +499,16 @@ public class DLL {
             } catch (UnsatisfiedLinkError ex) {
                 String dlError = ex.getMessage();
                 if (RContext.isInitialContextInitialized()) {
-                    throw new DLLException(RError.Message.DLL_LOAD_ERROR, absPath, dlError);
+                    throw new DLLException(ex, RError.Message.DLL_LOAD_ERROR, absPath, dlError);
                 } else {
-                    throw Utils.rSuicide("error loading default package: " + absPath + "\n" + dlError);
+                    throw Utils.rSuicide(ex, "error loading default package: " + absPath + "\n" + dlError);
                 }
             }
         }
-
     }
 
     public static class UnloadNode extends Node {
-        @Child private DLLRFFI.DLCloseNode dlCloseNode = RFFIFactory.getRFFI().getDLLRFFI().createDLCloseNode();
+        @Child private DLLRFFI.DLCloseNode dlCloseNode = RFFIFactory.getDLLRFFI().createDLCloseNode();
 
         @TruffleBoundary
         public void execute(String path) throws DLLException {
@@ -508,13 +518,13 @@ public class DLL {
                 if (info.path.equals(absPath)) {
                     int rc = dlCloseNode.execute(info.handle);
                     if (rc != 0) {
-                        throw new DLLException(RError.Message.DLL_LOAD_ERROR, path, "");
+                        throw new DLLException(null, RError.Message.DLL_LOAD_ERROR, path, "");
                     }
                     contextState.list.remove(info);
                     return;
                 }
             }
-            throw new DLLException(RError.Message.DLL_NOT_LOADED, path);
+            throw new DLLException(null, RError.Message.DLL_NOT_LOADED, path);
         }
 
         public static UnloadNode create() {
@@ -607,7 +617,6 @@ public class DLL {
         public static RFindSymbolNode create() {
             return new RFindSymbolNode();
         }
-
     }
 
     private static final class RFindSymbolRootNode extends RootNode {
@@ -615,9 +624,13 @@ public class DLL {
 
         @Child RFindSymbolNode findSymbolNode = RFindSymbolNode.create();
 
-        @SuppressWarnings("deprecation")
         private RFindSymbolRootNode() {
-            super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
+            super(RContext.getInstance().getLanguage());
+        }
+
+        @Override
+        public SourceSection getSourceSection() {
+            return RSyntaxNode.INTERNAL;
         }
 
         @Override
@@ -633,11 +646,10 @@ public class DLL {
             }
             return findSymbolRootNode;
         }
-
     }
 
     public static final class RdlsymNode extends Node {
-        @Child DLLRFFI.DLSymNode dlSymNode = RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
+        @Child DLLRFFI.DLSymNode dlSymNode = RFFIFactory.getDLLRFFI().createDLSymNode();
 
         /**
          * Directly analogous to the GnuR function {@code R_dlsym}. Checks first for a
@@ -748,4 +760,13 @@ public class DLL {
         return result;
     }
 
+    public 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/ffi/DLLRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
index fecf157ec83894882d71052ca23f81d31f587cf8..5b9d61239f89ebe117cf3b8fafef84b7e023415f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
@@ -22,46 +22,48 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
+import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
 
 public interface DLLRFFI {
-    abstract class DLOpenNode extends Node {
+    interface DLOpenNode extends NodeInterface {
         /**
          * Open a DLL.
          *
          * @return {@code null} on error, opaque handle for following calls otherwise.
          */
-        public abstract Object execute(String path, boolean local, boolean now) throws UnsatisfiedLinkError;
+        Object execute(String path, boolean local, boolean now) throws UnsatisfiedLinkError;
 
-        public static DLOpenNode create() {
-            return RFFIFactory.getRFFI().getDLLRFFI().createDLOpenNode();
+        static DLOpenNode create() {
+            return RFFIFactory.getDLLRFFI().createDLOpenNode();
         }
     }
 
-    abstract class DLSymNode extends Node {
+    interface DLSymNode extends NodeInterface {
         /**
          * Search for {@code symbol} in DLL specified by {@code handle}. To accommodate differing
          * implementations of this interface the result is {@link SymbolHandle}. For the standard OS
          * implementation this will encapsulate a {@link Long} or {@code null} if an error occurred.
          *
          */
-        public abstract SymbolHandle execute(Object handle, String symbol) throws UnsatisfiedLinkError;
+        SymbolHandle execute(Object handle, String symbol) throws UnsatisfiedLinkError;
 
-        public static DLSymNode create() {
-            return RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode();
+        static DLSymNode create() {
+            return RFFIFactory.getDLLRFFI().createDLSymNode();
         }
     }
 
-    abstract class DLCloseNode extends Node {
+    interface DLCloseNode extends NodeInterface {
         /**
          * Close DLL specified by {@code handle}.
          */
-        public abstract int execute(Object handle);
+        int execute(Object handle);
 
-        public static DLCloseNode create() {
-            return RFFIFactory.getRFFI().getDLLRFFI().createDLCloseNode();
+        static DLCloseNode create() {
+            return RFFIFactory.getDLLRFFI().createDLCloseNode();
         }
     }
 
@@ -74,10 +76,8 @@ public interface DLLRFFI {
     // RootNodes
 
     final class DLOpenRootNode extends RFFIRootNode<DLOpenNode> {
-        private static DLOpenRootNode dlOpenRootNode;
-
         private DLOpenRootNode() {
-            super(RFFIFactory.getRFFI().getDLLRFFI().createDLOpenNode());
+            super(RFFIFactory.getDLLRFFI().createDLOpenNode());
         }
 
         @Override
@@ -86,11 +86,8 @@ public interface DLLRFFI {
             return rffiNode.execute((String) args[0], (boolean) args[1], (boolean) args[2]);
         }
 
-        public static DLOpenRootNode create() {
-            if (dlOpenRootNode == null) {
-                dlOpenRootNode = new DLOpenRootNode();
-            }
-            return dlOpenRootNode;
+        public static RootCallTarget create(RContext context) {
+            return context.getOrCreateNativeCallTarget(DLOpenRootNode.class, () -> new DLOpenRootNode().getCallTarget());
         }
     }
 
@@ -98,7 +95,7 @@ public interface DLLRFFI {
         private static DLSymRootNode dlSymRootNode;
 
         private DLSymRootNode() {
-            super(RFFIFactory.getRFFI().getDLLRFFI().createDLSymNode());
+            super(RFFIFactory.getDLLRFFI().createDLSymNode());
         }
 
         @Override
@@ -119,7 +116,7 @@ public interface DLLRFFI {
         private static DLCloseRootNode dlCloseRootNode;
 
         private DLCloseRootNode() {
-            super(RFFIFactory.getRFFI().getDLLRFFI().createDLCloseNode());
+            super(RFFIFactory.getDLLRFFI().createDLCloseNode());
         }
 
         @Override
@@ -135,5 +132,4 @@ public interface DLLRFFI {
             return dlCloseRootNode;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
index 30632fc5d3d2457910993d77303c3e236f829171..d995028b428278380d452486f8a8faab5237ae56 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/LapackRFFI.java
@@ -22,7 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * Collection of statically typed Lapack methods that are used in the {@code base} package. The
@@ -30,151 +30,151 @@ import com.oracle.truffle.api.nodes.Node;
  * the result of the call.
  */
 public interface LapackRFFI {
-    abstract class IlaverNode extends Node {
+    interface IlaverNode extends NodeInterface {
         /**
          * Return version info, mjor, minor, patch, in {@code version}.
          */
-        public abstract void execute(int[] version);
+        void execute(int[] version);
 
-        public static IlaverNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createIlaverNode();
+        static IlaverNode create() {
+            return RFFIFactory.getLapackRFFI().createIlaverNode();
         }
     }
 
-    abstract class DgeevNode extends Node {
+    interface DgeevNode extends NodeInterface {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d9/d28/dgeev_8f.html">spec</a>.
          */
-        public abstract int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork);
+        int execute(char jobVL, char jobVR, int n, double[] a, int lda, double[] wr, double[] wi, double[] vl, int ldvl, double[] vr, int ldvr, double[] work, int lwork);
 
-        public static DgeevNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDgeevNode();
+        static DgeevNode create() {
+            return RFFIFactory.getLapackRFFI().createDgeevNode();
         }
     }
 
-    abstract class Dgeqp3Node extends Node {
+    interface Dgeqp3Node extends NodeInterface {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/db/de5/dgeqp3_8f.html">spec</a>.
          */
-        public abstract int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork);
+        int execute(int m, int n, double[] a, int lda, int[] jpvt, double[] tau, double[] work, int lwork);
 
-        public static Dgeqp3Node create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDgeqp3Node();
+        static Dgeqp3Node create() {
+            return RFFIFactory.getLapackRFFI().createDgeqp3Node();
         }
     }
 
-    abstract class DormqrNode extends Node {
+    interface DormqrNode extends NodeInterface {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/da/d82/dormqr_8f.html">spec</a>.
          */
-        public abstract int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork);
+        int execute(char side, char trans, int m, int n, int k, double[] a, int lda, double[] tau, double[] c, int ldc, double[] work, int lwork);
 
-        public static DormqrNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDormqrNode();
+        static DormqrNode create() {
+            return RFFIFactory.getLapackRFFI().createDormqrNode();
         }
     }
 
-    abstract class DtrtrsNode extends Node {
+    interface DtrtrsNode extends NodeInterface {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d6/d6f/dtrtrs_8f.html">spec</a>.
          */
-        public abstract int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb);
+        int execute(char uplo, char trans, char diag, int n, int nrhs, double[] a, int lda, double[] b, int ldb);
 
-        public static DtrtrsNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDtrtrsNode();
+        static DtrtrsNode create() {
+            return RFFIFactory.getLapackRFFI().createDtrtrsNode();
         }
     }
 
-    abstract class DgetrfNode extends Node {
+    interface DgetrfNode extends NodeInterface {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d3/d6a/dgetrf_8f.html">spec</a>.
          */
-        public abstract int execute(int m, int n, double[] a, int lda, int[] ipiv);
+        int execute(int m, int n, double[] a, int lda, int[] ipiv);
 
-        public static DgetrfNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDgetrfNode();
+        static DgetrfNode create() {
+            return RFFIFactory.getLapackRFFI().createDgetrfNode();
         }
     }
 
-    abstract class DpotrfNode extends Node {
+    interface DpotrfNode extends NodeInterface {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d0/d8a/dpotrf_8f.html">spec</a>.
          */
-        public abstract int execute(char uplo, int n, double[] a, int lda);
+        int execute(char uplo, int n, double[] a, int lda);
 
-        public static DpotrfNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDpotrfNode();
+        static DpotrfNode create() {
+            return RFFIFactory.getLapackRFFI().createDpotrfNode();
         }
     }
 
-    abstract class DpotriNode extends Node {
+    interface DpotriNode extends NodeInterface {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d0/d8a/dpotri_8f.html">spec</a>.
          */
-        public abstract int execute(char uplo, int n, double[] a, int lda);
+        int execute(char uplo, int n, double[] a, int lda);
 
-        public static DpotriNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDpotriNode();
+        static DpotriNode create() {
+            return RFFIFactory.getLapackRFFI().createDpotriNode();
         }
     }
 
-    abstract class DpstrfNode extends Node {
+    interface DpstrfNode extends NodeInterface {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/dd/dad/dpstrf_8f.html">spec</a>.
          */
-        public abstract int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work);
+        int execute(char uplo, int n, double[] a, int lda, int[] piv, int[] rank, double tol, double[] work);
 
-        public static DpstrfNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDpstrfNode();
+        static DpstrfNode create() {
+            return RFFIFactory.getLapackRFFI().createDpstrfNode();
         }
     }
 
-    abstract class DgesvNode extends Node {
+    interface DgesvNode extends NodeInterface {
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/d8/d72/dgesv_8f.html">spec</a>.
          */
-        public abstract int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb);
+        int execute(int n, int nrhs, double[] a, int lda, int[] ipiv, double[] b, int ldb);
 
-        public static DgesvNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDgesvNode();
+        static DgesvNode create() {
+            return RFFIFactory.getLapackRFFI().createDgesvNode();
         }
     }
 
-    abstract class DlangeNode extends Node {
+    interface DlangeNode extends NodeInterface {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/dc/d09/dlange_8f.html">spec</a>.
          */
-        public abstract double execute(char norm, int m, int n, double[] a, int lda, double[] work);
+        double execute(char norm, int m, int n, double[] a, int lda, double[] work);
 
-        public static DlangeNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDlangeNode();
+        static DlangeNode create() {
+            return RFFIFactory.getLapackRFFI().createDlangeNode();
         }
     }
 
-    abstract class DgeconNode extends Node {
+    interface DgeconNode extends NodeInterface {
 
         /**
          * See <a href="http://www.netlib.org/lapack/explore-html/db/de4/dgecon_8f.html">spec</a>.
          */
-        public abstract int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork);
+        int execute(char norm, int n, double[] a, int lda, double anorm, double[] rcond, double[] work, int[] iwork);
 
-        public static DgeconNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDgeconNode();
+        static DgeconNode create() {
+            return RFFIFactory.getLapackRFFI().createDgeconNode();
         }
     }
 
-    abstract class DsyevrNode extends Node {
+    interface DsyevrNode extends NodeInterface {
 
-        public abstract int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w,
-                        double[] z, int ldz, int[] isuppz, double[] work, int lwork, int[] iwork, int liwork);
+        int execute(char jobz, char range, char uplo, int n, double[] a, int lda, double vl, double vu, int il, int iu, double abstol, int[] m, double[] w, double[] z, int ldz, int[] isuppz,
+                        double[] work, int lwork, int[] iwork, int liwork);
 
-        public static DsyevrNode create() {
-            return RFFIFactory.getRFFI().getLapackRFFI().createDsyevrNode();
+        static DsyevrNode create() {
+            return RFFIFactory.getLapackRFFI().createDsyevrNode();
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
index a401f6b1b84c35c807d0f3051392adfbb77692e4..7f20d3f638ce6e30adf34948f1231f4e42315bd7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/MiscRFFI.java
@@ -22,18 +22,18 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * Miscellaneous methods implemented in native code.
  *
  */
 public interface MiscRFFI {
-    abstract class ExactSumNode extends Node {
-        public abstract double execute(double[] values, boolean hasNa, boolean naRm);
+    interface ExactSumNode extends NodeInterface {
+        double execute(double[] values, boolean hasNa, boolean naRm);
 
-        public static ExactSumNode create() {
-            return RFFIFactory.getRFFI().getMiscRFFI().createExactSumNode();
+        static ExactSumNode create() {
+            return RFFIFactory.getMiscRFFI().createExactSumNode();
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java
index c963ab2ec8ff7385eb2d5eb97d09196fab53f23b..90489b5ffc5ac02677c3454379bb3b45015dac57 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/PCRERFFI.java
@@ -22,7 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * An interface to the <a href="http://www.pcre.org/original/doc/html/index.html">PCRE</a> library
@@ -49,54 +49,51 @@ public interface PCRERFFI {
         }
     }
 
-    abstract class MaketablesNode extends Node {
+    interface MaketablesNode extends NodeInterface {
+        long execute();
 
-        public abstract long execute();
-
-        public static MaketablesNode create() {
-            return RFFIFactory.getRFFI().getPCRERFFI().createMaketablesNode();
+        static MaketablesNode create() {
+            return RFFIFactory.getPCRERFFI().createMaketablesNode();
         }
     }
 
-    abstract class CompileNode extends Node {
-
-        public abstract Result execute(String pattern, int options, long tables);
+    interface CompileNode extends NodeInterface {
+        Result execute(String pattern, int options, long tables);
 
-        public static CompileNode create() {
-            return RFFIFactory.getRFFI().getPCRERFFI().createCompileNode();
+        static CompileNode create() {
+            return RFFIFactory.getPCRERFFI().createCompileNode();
         }
     }
 
-    abstract class GetCaptureCountNode extends Node {
-
-        public abstract int execute(long code, long extra);
+    interface GetCaptureCountNode extends NodeInterface {
+        int execute(long code, long extra);
 
-        public static GetCaptureCountNode create() {
-            return RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureCountNode();
+        static GetCaptureCountNode create() {
+            return RFFIFactory.getPCRERFFI().createGetCaptureCountNode();
         }
     }
 
-    abstract class GetCaptureNamesNode extends Node {
-        public abstract String[] execute(long code, long extra, int captureCount);
+    interface GetCaptureNamesNode extends NodeInterface {
+        String[] execute(long code, long extra, int captureCount);
 
-        public static GetCaptureNamesNode create() {
-            return RFFIFactory.getRFFI().getPCRERFFI().createGetCaptureNamesNode();
+        static GetCaptureNamesNode create() {
+            return RFFIFactory.getPCRERFFI().createGetCaptureNamesNode();
         }
     }
 
-    abstract class StudyNode extends Node {
-        public abstract Result execute(long code, int options);
+    interface StudyNode extends NodeInterface {
+        Result execute(long code, int options);
 
-        public static StudyNode create() {
-            return RFFIFactory.getRFFI().getPCRERFFI().createStudyNode();
+        static StudyNode create() {
+            return RFFIFactory.getPCRERFFI().createStudyNode();
         }
     }
 
-    abstract class ExecNode extends Node {
-        public abstract int execute(long code, long extra, String subject, int offset, int options, int[] ovector);
+    interface ExecNode extends NodeInterface {
+        int execute(long code, long extra, String subject, int offset, int options, int[] ovector);
 
-        public static ExecNode create() {
-            return RFFIFactory.getRFFI().getPCRERFFI().createExecNode();
+        static ExecNode create() {
+            return RFFIFactory.getPCRERFFI().createExecNode();
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java
index a8e4d2aa6dfb3ca4e740913ef8b28a1fad4b152e..1134a3c705374c907bed9a82be01a8c04bdb589f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RApplRFFI.java
@@ -22,7 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * Collection of statically typed methods (from Linpack and elsewhere) that are built in to a GnuR
@@ -30,27 +30,60 @@ import com.oracle.truffle.api.nodes.Node;
  * {@code libappl} library in GnuR.
  */
 public interface RApplRFFI {
-    abstract class Dqrdc2Node extends Node {
-        public abstract void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work);
+    interface Dqrdc2Node extends NodeInterface {
+        void execute(double[] x, int ldx, int n, int p, double tol, int[] rank, double[] qraux, int[] pivot, double[] work);
 
-        public static Dqrdc2Node create() {
-            return RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node();
+        static Dqrdc2Node create() {
+            return RFFIFactory.getRApplRFFI().createDqrdc2Node();
         }
     }
 
-    abstract class DqrcfNode extends Node {
-        public abstract void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info);
+    interface DqrcfNode extends NodeInterface {
+        void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] b, int[] info);
 
-        public static Dqrdc2Node create() {
-            return RFFIFactory.getRFFI().getRApplRFFI().createDqrdc2Node();
+        static Dqrdc2Node create() {
+            return RFFIFactory.getRApplRFFI().createDqrdc2Node();
         }
     }
 
-    abstract class DqrlsNode extends Node {
-        public abstract void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work);
+    interface DqrlsNode extends NodeInterface {
+        void execute(double[] x, int n, int p, double[] y, int ny, double tol, double[] b, double[] rsd, double[] qty, int[] k, int[] jpvt, double[] qraux, double[] work);
 
-        public static DqrlsNode create() {
-            return RFFIFactory.getRFFI().getRApplRFFI().createDqrlsNode();
+        static DqrlsNode create() {
+            return RFFIFactory.getRApplRFFI().createDqrlsNode();
+        }
+    }
+
+    interface DqrqtyNode extends NodeInterface {
+        void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] qty);
+
+        static DqrqtyNode create() {
+
+            return RFFIFactory.getRApplRFFI().createDqrqtyNode();
+        }
+    }
+
+    interface DqrqyNode extends NodeInterface {
+        void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] qy);
+
+        static DqrqyNode create() {
+            return RFFIFactory.getRApplRFFI().createDqrqyNode();
+        }
+    }
+
+    interface DqrrsdNode extends NodeInterface {
+        void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] rsd);
+
+        static DqrrsdNode create() {
+            return RFFIFactory.getRApplRFFI().createDqrrsdNode();
+        }
+    }
+
+    interface DqrxbNode extends NodeInterface {
+        void execute(double[] x, int n, int k, double[] qraux, double[] y, int ny, double[] xb);
+
+        static DqrxbNode create() {
+            return RFFIFactory.getRApplRFFI().createDqrxbNode();
         }
     }
 
@@ -60,4 +93,11 @@ public interface RApplRFFI {
 
     DqrlsNode createDqrlsNode();
 
+    DqrqtyNode createDqrqtyNode();
+
+    DqrqyNode createDqrqyNode();
+
+    DqrrsdNode createDqrrsdNode();
+
+    DqrxbNode createDqrxbNode();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
index 12c23e7e6db57193e08ae842b1559bfe94e3a517..6c517528b906b3274703dcc6482faa6f59875c8d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFI.java
@@ -41,10 +41,9 @@ package com.oracle.truffle.r.runtime.ffi;
  * <li>{@link ZipRFFI}: interface to zip compression</li>
  * <li>{@link DLLRFFI}: interface to dll functions, e.g., {@code dlopen}</li>
  * <li>{@link REmbedRFFI}: interface to embedded support</li>
- * <li>{@link MiscRFFI}: interface to miscellaneous native functions</li>
- * <li>{@link UpCallsRFFI}: interface that defines the set of upcalls from native code (resulting
- * from {@link CallRFFI}). There is no public access to this interface as it should never be called
- * from FastR Java code and is always implemented by a specific FFI factory.
+ * <li>{@link MiscRFFI}: interface to miscellaneous native functions</li> from {@link CallRFFI}).
+ * There is no public access to this interface as it should never be called from FastR Java code and
+ * is always implemented by a specific FFI factory.
  * </ul>
  *
  * These interfaces may be implemented by one or more providers, specified either when the FastR
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
index 60d3811bdbcefdcc5734b1e99cc5d6defc588114..daf3e5a28c864d6f524bfec8e7a684ba68c7f9cb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
@@ -38,23 +38,22 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextState;
  * point.
  */
 public abstract class RFFIFactory {
-    private enum Factory {
-        JNI("com.oracle.truffle.r.runtime.ffi.jni.JNI_RFFIFactory"),
-        LLVM("com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_RFFIFactory"),
-        MANAGED("com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory"),
-        NFI("com.oracle.truffle.r.engine.interop.ffi.nfi.TruffleNFI_RFFIFactory");
+    public enum Type {
+        JNI("com.oracle.truffle.r.ffi.impl.jni.JNI_RFFIFactory"),
+        LLVM("com.oracle.truffle.r.ffi.impl.llvm.TruffleLLVM_RFFIFactory"),
+        MANAGED("com.oracle.truffle.r.ffi.impl.managed.Managed_RFFIFactory"),
+        NFI("com.oracle.truffle.r.ffi.impl.nfi.TruffleNFI_RFFIFactory");
 
         private final String klassName;
 
-        Factory(String klassName) {
+        Type(String klassName) {
             this.klassName = klassName;
         }
     }
 
-    private static final String FACTORY_CLASS_PROPERTY = "fastr.rffi.factory.class";
-    private static final String FACTORY_CLASS_NAME_PROPERTY = "fastr.rffi.factory";
+    private static final String FACTORY_TYPE_PROPERTY = "fastr.rffi.factory.type";
     private static final String FACTORY_CLASS_ENV = "FASTR_RFFI";
-    private static final Factory DEFAULT_FACTORY = Factory.JNI;
+    private static final Type DEFAULT_FACTORY = Type.JNI;
 
     /**
      * Singleton instance of the factory.
@@ -62,10 +61,12 @@ public abstract class RFFIFactory {
     private static RFFIFactory instance;
 
     @CompilationFinal protected static RFFI theRFFI;
+    @CompilationFinal private static Type type;
 
     static {
         if (instance == null) {
-            String klassName = getFactoryClassName();
+            type = getFactoryType();
+            String klassName = type.klassName;
             try {
                 instance = (RFFIFactory) Class.forName(klassName).newInstance();
                 theRFFI = instance.createRFFI();
@@ -75,12 +76,8 @@ public abstract class RFFIFactory {
         }
     }
 
-    private static String getFactoryClassName() {
-        String prop = System.getProperty(FACTORY_CLASS_PROPERTY);
-        if (prop != null) {
-            return prop;
-        }
-        prop = System.getProperty(FACTORY_CLASS_NAME_PROPERTY);
+    private static Type getFactoryType() {
+        String prop = System.getProperty(FACTORY_TYPE_PROPERTY);
         if (prop != null) {
             return checkFactoryName(prop);
         }
@@ -89,19 +86,18 @@ public abstract class RFFIFactory {
             return checkFactoryName(prop);
         }
         if (FastRConfig.ManagedMode) {
-            return Factory.MANAGED.klassName;
+            return Type.MANAGED;
         }
-        return DEFAULT_FACTORY.klassName;
+        return DEFAULT_FACTORY;
     }
 
-    private static String checkFactoryName(String prop) {
+    private static Type checkFactoryName(String prop) {
         try {
-            Factory factory = Factory.valueOf(prop.toUpperCase());
-            return factory.klassName;
+            Type factory = Type.valueOf(prop.toUpperCase());
+            return factory;
         } catch (IllegalArgumentException ex) {
             throw Utils.rSuicide("No RFFI factory: " + prop);
         }
-
     }
 
     public static RFFIFactory getInstance() {
@@ -109,11 +105,71 @@ public abstract class RFFIFactory {
         return instance;
     }
 
-    public static RFFI getRFFI() {
+    private static RFFI getRFFI() {
         assert theRFFI != null : "RFFI factory is not initialized!";
         return theRFFI;
     }
 
+    /*
+     * Some shortcuts to the specific RFFI interfaces:
+     */
+
+    public static BaseRFFI getBaseRFFI() {
+        return getRFFI().getBaseRFFI();
+    }
+
+    public static LapackRFFI getLapackRFFI() {
+        return getRFFI().getLapackRFFI();
+    }
+
+    public static RApplRFFI getRApplRFFI() {
+        return getRFFI().getRApplRFFI();
+    }
+
+    public static StatsRFFI getStatsRFFI() {
+        return getRFFI().getStatsRFFI();
+    }
+
+    public static ToolsRFFI getToolsRFFI() {
+        return getRFFI().getToolsRFFI();
+    }
+
+    public static CRFFI getCRFFI() {
+        return getRFFI().getCRFFI();
+    }
+
+    public static CallRFFI getCallRFFI() {
+        return getRFFI().getCallRFFI();
+    }
+
+    public static UserRngRFFI getUserRngRFFI() {
+        return getRFFI().getUserRngRFFI();
+    }
+
+    public static PCRERFFI getPCRERFFI() {
+        return getRFFI().getPCRERFFI();
+    }
+
+    public static ZipRFFI getZipRFFI() {
+        return getRFFI().getZipRFFI();
+    }
+
+    public static DLLRFFI getDLLRFFI() {
+        return getRFFI().getDLLRFFI();
+    }
+
+    public static REmbedRFFI getREmbedRFFI() {
+        return getRFFI().getREmbedRFFI();
+    }
+
+    public static MiscRFFI getMiscRFFI() {
+        return getRFFI().getMiscRFFI();
+    }
+
+    public static Type getType() {
+        return type;
+    }
+
     /**
      * Subclass implements this method to actually create the concrete {@link RFFI} instance.
      */
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java
index d6b8451a812102fa1304ee76503492aad10c0fc0..d7ddf499f6679be776b5ce12d7a281da6f3f9f47 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIRootNode.java
@@ -23,19 +23,23 @@
 package com.oracle.truffle.r.runtime.ffi;
 
 import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.nodes.NodeInterface;
 import com.oracle.truffle.api.nodes.RootNode;
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
-public abstract class RFFIRootNode<T extends Node> extends RootNode {
-    @Child T rffiNode;
+public abstract class RFFIRootNode<T extends NodeInterface> extends RootNode {
+    @Child protected T rffiNode;
 
-    @SuppressWarnings("deprecation")
     protected RFFIRootNode(T baseRFFINode) {
-        super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
+        super(RContext.getInstance().getLanguage());
         this.rffiNode = baseRFFINode;
         Truffle.getRuntime().createCallTarget(this);
     }
 
+    @Override
+    public SourceSection getSourceSection() {
+        return RSyntaxNode.INTERNAL;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
similarity index 88%
rename from com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
index be05015ada910b1c72a7a596469ba54285284f47..83dbd06f652fc392cbffe67925100887b6071adb 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIVariables.java
@@ -37,15 +37,16 @@ public enum RFFIVariables {
     R_NilValue(RNull.instance),
     R_UnboundValue(RUnboundValue.instance),
     R_MissingArg(RMissing.instance),
-    R_GlobalEnv(null),
+    R_GlobalEnv(null, true),
     R_EmptyEnv(REnvironment.emptyEnv()),
-    R_BaseEnv(null),
-    R_BaseNamespace(null),
-    R_NamespaceRegistry(null),
+    R_BaseEnv(null, true),
+    R_BaseNamespace(null, true),
+    R_NamespaceRegistry(null, true),
     R_Srcref(null),
     R_Bracket2Symbol(RDataFactory.createSymbol("[[")),
     R_BracketSymbol(RDataFactory.createSymbol("[")),
     R_BraceSymbol(RDataFactory.createSymbol("{")),
+    R_DoubleColonSymbol(RDataFactory.createSymbol("::")),
     R_ClassSymbol(RDataFactory.createSymbol("class")),
     R_DeviceSymbol(RDataFactory.createSymbol(".Device")),
     R_DevicesSymbol(RDataFactory.createSymbol(".Devices")),
@@ -84,9 +85,15 @@ public enum RFFIVariables {
     R_RestartToken(null);
 
     private Object value;
+    public final boolean alwaysUpCall;
 
-    RFFIVariables(Object value) {
+    RFFIVariables(Object value, boolean alwaysUpCall) {
         this.value = value;
+        this.alwaysUpCall = alwaysUpCall;
+    }
+
+    RFFIVariables(Object value) {
+        this(value, false);
     }
 
     public Object getValue() {
@@ -99,6 +106,11 @@ public enum RFFIVariables {
     public static RFFIVariables[] initialize() {
         R_TempDir.value = TempPathName.tempDirPath();
         return values();
+    }
 
+    public static void main(String[] args) {
+        for (RFFIVariables var : RFFIVariables.values()) {
+            System.out.printf("#define %s_x %d\n", var.name(), var.ordinal());
+        }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StatsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StatsRFFI.java
index d1dcd13fc0be31779570e816926bfa3cf6b1d3e3..5fc727da587d79245183abee162095104739d644 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StatsRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/StatsRFFI.java
@@ -22,7 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * Interface to native (C) methods provided by the {@code stats} package that are used to implement
@@ -30,19 +30,19 @@ import com.oracle.truffle.api.nodes.Node;
  * {@code fft_factor} and {@code fft_work}. functions from the GNU R C code.
  */
 public interface StatsRFFI {
-    abstract class FactorNode extends Node {
-        public abstract void execute(int n, int[] pmaxf, int[] pmaxp);
+    interface FactorNode extends NodeInterface {
+        void execute(int n, int[] pmaxf, int[] pmaxp);
 
-        public static FactorNode create() {
-            return RFFIFactory.getRFFI().getStatsRFFI().createFactorNode();
+        static FactorNode create() {
+            return RFFIFactory.getStatsRFFI().createFactorNode();
         }
     }
 
-    abstract class WorkNode extends Node {
-        public abstract int execute(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork);
+    interface WorkNode extends NodeInterface {
+        int execute(double[] a, int nseg, int n, int nspn, int isn, double[] work, int[] iwork);
 
-        public static WorkNode create() {
-            return RFFIFactory.getRFFI().getStatsRFFI().createWorkNode();
+        static WorkNode create() {
+            return RFFIFactory.getStatsRFFI().createWorkNode();
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ToolsRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ToolsRFFI.java
index 7d797e62f112dfb5f13ca953d802bd2c0f3086d2..629bc1a5889deaf3bfc9beaa9784423f32ae5e16 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ToolsRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ToolsRFFI.java
@@ -22,7 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 import com.oracle.truffle.r.runtime.conn.RConnection;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RStringVector;
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment;
  * Interface to native (C) methods provided by the {@code tools} package.
  */
 public interface ToolsRFFI {
-    abstract class ParseRdNode extends Node {
+    interface ParseRdNode extends NodeInterface {
         /**
          * This invokes the Rd parser, written in C, and part of GnuR, that does its work using the
          * R FFI interface. The R code initially invokes this via {@code .External2(C_parseRd, ...)}
@@ -41,7 +41,7 @@ public interface ToolsRFFI {
          * code. We can't go straight to the GnuR C entry point as that makes GnuR-specific
          * assumptions about, for example, how connections are implemented.
          */
-        public abstract Object execute(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros,
+        Object execute(RConnection con, REnvironment srcfile, RLogicalVector verbose, RLogicalVector fragment, RStringVector basename, RLogicalVector warningCalls, Object macros,
                         RLogicalVector warndups);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java
index 64059decbdafae4071c9165e91a345da6c2f313d..d2be2ee0cfb6bb86ffe7a2ea8d6b9c87d726b844 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/UserRngRFFI.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
@@ -22,23 +22,37 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * Explicit statically typed interface to user-supplied random number generators.
  */
 public interface UserRngRFFI {
-    abstract class UserRngRFFINode extends Node {
+    interface InitNode extends NodeInterface {
 
-        public abstract void init(int seed);
+        void execute(int seed);
+    }
+
+    interface RandNode extends NodeInterface {
+
+        double execute();
+    }
 
-        public abstract double rand();
+    interface NSeedNode extends NodeInterface {
 
-        public abstract int nSeed();
+        int execute();
+    }
+
+    interface SeedsNode extends NodeInterface {
 
-        public abstract void seeds(int[] n);
+        void execute(int[] n);
     }
 
-    UserRngRFFINode createUserRngRFFINode();
+    InitNode createInitNode();
+
+    RandNode createRandNode();
+
+    NSeedNode createNSeedNode();
 
+    SeedsNode createSeedsNode();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
index 1eecb127e95bfe8e20a69978b753c93811f79a2b..d41187a6c10cabb41638ca7e7fd5a215884fd667 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
@@ -23,33 +23,33 @@
 package com.oracle.truffle.r.runtime.ffi;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.api.nodes.NodeInterface;
 
 /**
  * zip compression/uncompression.
  */
 public interface ZipRFFI {
 
-    abstract class CompressNode extends Node {
+    interface CompressNode extends NodeInterface {
         /**
          * compress {@code source} into {@code dest}.
          *
          * @return standard return code (0 ok)
          */
-        public abstract int execute(byte[] dest, byte[] source);
+        int execute(byte[] dest, byte[] source);
 
-        public static CompressNode create() {
-            return RFFIFactory.getRFFI().getZipRFFI().createCompressNode();
+        static CompressNode create() {
+            return RFFIFactory.getZipRFFI().createCompressNode();
         }
     }
 
-    abstract class UncompressNode extends Node {
+    interface UncompressNode extends NodeInterface {
         /**
          * uncompress {@code source} into {@code dest}.
          *
          * @return standard return code (0 ok)
          */
-        public abstract int execute(byte[] dest, byte[] source);
+        int execute(byte[] dest, byte[] source);
     }
 
     CompressNode createCompressNode();
@@ -62,7 +62,7 @@ public interface ZipRFFI {
         private static CompressRootNode compressRootNode;
 
         private CompressRootNode() {
-            super(RFFIFactory.getRFFI().getZipRFFI().createCompressNode());
+            super(RFFIFactory.getZipRFFI().createCompressNode());
         }
 
         @Override
@@ -83,7 +83,7 @@ public interface ZipRFFI {
         private static UncompressRootNode uncompressRootNode;
 
         private UncompressRootNode() {
-            super(RFFIFactory.getRFFI().getZipRFFI().createUncompressNode());
+            super(RFFIFactory.getZipRFFI().createUncompressNode());
         }
 
         @Override
@@ -99,5 +99,4 @@ public interface ZipRFFI {
             return uncompressRootNode;
         }
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java
deleted file mode 100644
index 36a30ba75a0f91ad6cfd0cfe9b4d2267bb454782..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/managed/Managed_RFFIFactory.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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.runtime.ffi.managed;
-
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
-import com.oracle.truffle.r.runtime.RError;
-import com.oracle.truffle.r.runtime.RError.Message;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.ContextState;
-import com.oracle.truffle.r.runtime.ffi.BaseRFFI;
-import com.oracle.truffle.r.runtime.ffi.CRFFI;
-import com.oracle.truffle.r.runtime.ffi.CallRFFI;
-import com.oracle.truffle.r.runtime.ffi.DLLRFFI;
-import com.oracle.truffle.r.runtime.ffi.LapackRFFI;
-import com.oracle.truffle.r.runtime.ffi.MiscRFFI;
-import com.oracle.truffle.r.runtime.ffi.PCRERFFI;
-import com.oracle.truffle.r.runtime.ffi.RApplRFFI;
-import com.oracle.truffle.r.runtime.ffi.REmbedRFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFI;
-import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
-import com.oracle.truffle.r.runtime.ffi.StatsRFFI;
-import com.oracle.truffle.r.runtime.ffi.ToolsRFFI;
-import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
-import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
-
-/**
- * Operations that can be, at least partially, implemented in Java are implemented, other operations
- * throw {@link RError}.
- */
-public class Managed_RFFIFactory extends RFFIFactory implements RFFI {
-    @Override
-    protected RFFI createRFFI() {
-        return this;
-    }
-
-    @Override
-    public BaseRFFI getBaseRFFI() {
-        return new Managed_Base();
-    }
-
-    @Override
-    public LapackRFFI getLapackRFFI() {
-        return new Managed_LapackRFFI();
-    }
-
-    @Override
-    public RApplRFFI getRApplRFFI() {
-        return new RApplRFFI() {
-            @Override
-            public Dqrdc2Node createDqrdc2Node() {
-                throw unsupported("dqrdc");
-            }
-
-            @Override
-            public DqrcfNode createDqrcfNode() {
-                throw unsupported("dqrcf");
-            }
-
-            @Override
-            public DqrlsNode createDqrlsNode() {
-                throw unsupported("dqrls");
-            }
-        };
-    }
-
-    @Override
-    public StatsRFFI getStatsRFFI() {
-        return new StatsRFFI() {
-            @Override
-            public FactorNode createFactorNode() {
-                throw unsupported("factor");
-            }
-
-            @Override
-            public WorkNode createWorkNode() {
-                throw unsupported("work");
-            }
-        };
-    }
-
-    @Override
-    public ToolsRFFI getToolsRFFI() {
-        return new ToolsRFFI() {
-            @Override
-            public ParseRdNode createParseRdNode() {
-                throw unsupported("parseRD");
-            }
-        };
-    }
-
-    @Override
-    public CRFFI getCRFFI() {
-        return new CRFFI() {
-            @Override
-            public InvokeCNode createInvokeCNode() {
-                throw unsupported("invoke");
-            }
-        };
-    }
-
-    @Override
-    public CallRFFI getCallRFFI() {
-        return new CallRFFI() {
-            @Override
-            public InvokeCallNode createInvokeCallNode() {
-                throw unsupported("native code invocation");
-            }
-
-            @Override
-            public InvokeVoidCallNode createInvokeVoidCallNode() {
-                throw unsupported("native code invocation");
-            }
-        };
-    }
-
-    @Override
-    public UserRngRFFI getUserRngRFFI() {
-        return new UserRngRFFI() {
-            @Override
-            public UserRngRFFINode createUserRngRFFINode() {
-                throw unsupported("user defined RNG");
-            }
-        };
-    }
-
-    @Override
-    public PCRERFFI getPCRERFFI() {
-        return new Managed_PCRERFFI();
-    }
-
-    @Override
-    public ZipRFFI getZipRFFI() {
-        return new ZipRFFI() {
-            @Override
-            public CompressNode createCompressNode() {
-                throw unsupported("zip compression");
-            }
-
-            @Override
-            public UncompressNode createUncompressNode() {
-                throw unsupported("zip decompression");
-            }
-        };
-    }
-
-    @Override
-    public DLLRFFI getDLLRFFI() {
-        return new DLLRFFI() {
-            @Override
-            public DLOpenNode createDLOpenNode() {
-                throw unsupported("DLL open");
-            }
-
-            @Override
-            public DLSymNode createDLSymNode() {
-                throw unsupported("createDLSym");
-            }
-
-            @Override
-            public DLCloseNode createDLCloseNode() {
-                throw unsupported("createDLClose");
-            }
-        };
-    }
-
-    @Override
-    public REmbedRFFI getREmbedRFFI() {
-        return new Managed_REmbedRFFI();
-    }
-
-    @Override
-    public MiscRFFI getMiscRFFI() {
-        return new MiscRFFI() {
-            @Override
-            public ExactSumNode createExactSumNode() {
-                throw unsupported("exactsum");
-            }
-        };
-    }
-
-    @Override
-    public ContextState newContextState() {
-        return new ContextState() {
-            @Override
-            public ContextState initialize(RContext context) {
-                return this;
-            }
-        };
-    }
-
-    @TruffleBoundary
-    static RError unsupported(String name) {
-        throw RError.error(RError.NO_CALLER, Message.GENERIC, String.format("Feature '%s' is not supported by managed FFI, i.e. it requires running native code.", name));
-    }
-}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SA_TYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SA_TYPE.java
new file mode 100644
index 0000000000000000000000000000000000000000..703988a4d130c8cec6c56dfeafb61174978703e1
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SA_TYPE.java
@@ -0,0 +1,29 @@
+/*
+ * This material is distributed under the GNU General Public License
+ * Version 2. You may review the terms of this license at
+ * http://www.gnu.org/licenses/gpl-2.0.html
+ *
+ * Copyright (c) 1995-2015, The R Core Team
+ * Copyright (c) 2003, The R Foundation
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates
+ *
+ * All rights reserved.
+ */
+package com.oracle.truffle.r.runtime.gnur;
+
+public enum SA_TYPE {
+    DEFAULT("default"),
+    NOSAVE("no"),
+    SAVE("yes"),
+    SAVEASK("ask");
+
+    private String name;
+
+    SA_TYPE(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
index 9aa6e79d3426372eac3b29810ce4fb1e4b684449..146301963b7405eaf7e9c06776afcd32f287cfea 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java
@@ -11,9 +11,6 @@
  */
 package com.oracle.truffle.r.runtime.gnur;
 
-import java.util.HashMap;
-import java.util.Map;
-
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RComplex;
@@ -98,21 +95,22 @@ public enum SEXPTYPE {
     public final int code;
     public final Class<?>[] fastRClasses;
 
+    private static final SEXPTYPE[] codeMap = new SEXPTYPE[501];
+
     SEXPTYPE(int code, Class<?>... fastRClasses) {
         this.code = code;
         this.fastRClasses = fastRClasses;
     }
 
-    private static final Map<Integer, SEXPTYPE> codeMap = new HashMap<>();
-
     static {
         for (SEXPTYPE type : SEXPTYPE.values()) {
-            SEXPTYPE.codeMap.put(type.code, type);
+            assert type.code >= 0 && type.code < codeMap.length;
+            codeMap[type.code] = type;
         }
     }
 
     public static SEXPTYPE mapInt(int type) {
-        return codeMap.get(type);
+        return codeMap[type];
     }
 
     /**
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java
index 8c91575ef9aa6eeb2b24945ca3b2e4999fa84c9d..10873939fb769c27447c3eec8d029e32b7f7a662 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.instrument;
 
 import java.io.PrintStream;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.WeakHashMap;
@@ -203,8 +204,8 @@ public final class InstrumentationState implements RContext.ContextState {
     }
 
     @TruffleBoundary
-    public void putDebugListener(SourceSection ss, ExecutionEventListener listener) {
-        debugListenerMap.put(ss, listener);
+    public void putDebugListener(SourceSection sourceSection, ExecutionEventListener listener) {
+        debugListenerMap.put(sourceSection, listener);
     }
 
     @TruffleBoundary
@@ -215,6 +216,11 @@ public final class InstrumentationState implements RContext.ContextState {
 
     }
 
+    @TruffleBoundary
+    public Collection<ExecutionEventListener> getDebugListeners() {
+        return debugListenerMap.values();
+    }
+
     @TruffleBoundary
     public ExecutionEventListener getDebugListener(SourceSection ss) {
         return debugListenerMap.get(ss);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerInstrument.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerInstrument.java
new file mode 100644
index 0000000000000000000000000000000000000000..3237a99b260e4bb22c8ab79d99a8e7e38f1c1110
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerInstrument.java
@@ -0,0 +1,127 @@
+/*
+ * 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.runtime.instrument.memprof;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.instrumentation.AllocationEvent;
+import com.oracle.truffle.api.instrumentation.AllocationEventFilter;
+import com.oracle.truffle.api.instrumentation.AllocationListener;
+import com.oracle.truffle.api.instrumentation.EventBinding;
+import com.oracle.truffle.api.instrumentation.EventContext;
+import com.oracle.truffle.api.instrumentation.ExecutionEventNode;
+import com.oracle.truffle.api.instrumentation.ExecutionEventNodeFactory;
+import com.oracle.truffle.api.instrumentation.Instrumenter;
+import com.oracle.truffle.api.instrumentation.SourceSectionFilter;
+import com.oracle.truffle.api.instrumentation.StandardTags;
+import com.oracle.truffle.api.instrumentation.TruffleInstrument;
+import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration;
+import com.oracle.truffle.api.source.SourceSection;
+
+@Registration(name = "MemAllocProfiler", id = MemAllocProfilerInstrument.ID)
+public class MemAllocProfilerInstrument extends TruffleInstrument {
+
+    public static final String ID = "mem-alloc-profiler";
+
+    private EventBinding<MemAllocEventFactory> allocationEventBinding;
+
+    @Override
+    protected void onCreate(TruffleInstrument.Env env) {
+        env.registerService(this);
+
+        Instrumenter instrumenter = env.getInstrumenter();
+        MemAllocEventFactory eventFactory = new MemAllocEventFactory(env);
+        SourceSectionFilter.Builder builder = SourceSectionFilter.newBuilder();
+        SourceSectionFilter filter = builder.tagIs(StandardTags.StatementTag.class).build();
+        instrumenter.attachFactory(filter, eventFactory);
+        allocationEventBinding = instrumenter.attachAllocationListener(AllocationEventFilter.newBuilder().build(), eventFactory);
+
+        env.registerService(eventFactory.memAllocStacks);
+    }
+
+    @Override
+    protected void onDispose(Env env) {
+        allocationEventBinding.dispose();
+    }
+
+    public static class MemAllocEventFactory implements ExecutionEventNodeFactory, AllocationListener {
+
+        protected final Env env;
+        protected final MemAllocProfilerStacks memAllocStacks = MemAllocProfilerStacks.getInstance();
+
+        protected MemAllocEventFactory(final Env env) {
+            this.env = env;
+        }
+
+        @Override
+        @TruffleBoundary
+        public void onEnter(AllocationEvent event) {
+        }
+
+        @Override
+        @TruffleBoundary
+        public void onReturnValue(AllocationEvent event) {
+            memAllocStacks.reportAllocation(event.getNewSize() - event.getOldSize());
+        }
+
+        public MemAllocProfilerStacks getStacks() {
+            return memAllocStacks;
+        }
+
+        public void dispose() {
+            memAllocStacks.clear();
+        }
+
+        @Override
+        public ExecutionEventNode create(final EventContext ec) {
+            return new ExecutionEventNode() {
+
+                @Override
+                protected void onEnter(VirtualFrame frame) {
+                    pushEntry();
+                }
+
+                @Override
+                public void onReturnValue(VirtualFrame vFrame, Object result) {
+                    popEntry();
+                }
+
+                @Override
+                protected void onReturnExceptional(VirtualFrame frame, Throwable exception) {
+                    popEntry();
+                }
+
+                @TruffleBoundary
+                private void pushEntry() {
+                    SourceSection src = ec.getInstrumentedSourceSection();
+                    memAllocStacks.push(ec.getInstrumentedNode().getRootNode().getName(), src);
+                }
+
+                @TruffleBoundary
+                private void popEntry() {
+                    memAllocStacks.pop();
+                }
+            };
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerPaths.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerPaths.java
new file mode 100644
index 0000000000000000000000000000000000000000..a9c9ad8d76cbd464094addeb94fe030679562c81
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerPaths.java
@@ -0,0 +1,406 @@
+/*
+ * 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.runtime.instrument.memprof;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
+
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.source.SourceSection;
+
+public final class MemAllocProfilerPaths {
+    private final AtomicLong version = new AtomicLong();
+    private final AtomicInteger idGen = new AtomicInteger();
+    private final Map<Integer, Entry> entryMap = new ConcurrentHashMap<>();
+    private volatile Entry root = new Entry(this, null, "", null);
+
+    private MemAllocProfilerPaths hsView;
+    private long hsViewVersion;
+
+    /**
+     * Clear the model.
+     */
+    public synchronized void clear() {
+        idGen.set(0);
+        entryMap.clear();
+        root = new Entry(this, null, "", null);
+    }
+
+    /**
+     *
+     * @param id the id of the allocation entry
+     * @return the allocation entry
+     */
+    public Entry getEntry(int id) {
+        return entryMap.get(id);
+    }
+
+    /**
+     * @return the root entry.
+     */
+    public Entry getRootEntry() {
+        return root;
+    }
+
+    public TruffleObject toTruffleObject() {
+        return JavaInterop.asTruffleObject(this);
+    }
+
+    public static MemAllocProfilerPaths fromTruffleObject(TruffleObject to) {
+        return JavaInterop.asJavaObject(MemAllocProfilerPaths.class, to);
+    }
+
+    /**
+     * Store the snapshot of the current paths hierarchy.
+     *
+     * @param name the snapshot name
+     * @return the snapshot
+     */
+    public MemAllocProfilerPaths getOrMakeSnapshot(String name) {
+        return clonePaths();
+    }
+
+    public synchronized MemAllocProfilerPaths toHS() {
+        long curVer = version.get();
+        if (curVer == hsViewVersion && hsView != null) {
+            return hsView;
+        }
+        hsViewVersion = curVer;
+        hsView = invert().groupBySrcSection();
+        return hsView;
+    }
+
+    @SuppressWarnings("unused")
+    synchronized MemAllocProfilerPaths clonePaths() {
+        MemAllocProfilerPaths clonedPaths = new MemAllocProfilerPaths();
+        new Entry(clonedPaths, null, root);
+        return clonedPaths;
+    }
+
+    MemAllocProfilerPaths invert() {
+        List<Entry> inverted = new ArrayList<>();
+        MemAllocProfilerPaths targetPaths = new MemAllocProfilerPaths();
+        for (Entry entry : entryMap.values()) {
+            inverted.add(entry.invert(targetPaths));
+        }
+        return targetPaths;
+    }
+
+    MemAllocProfilerPaths groupBySrcSection() {
+        MemAllocProfilerPaths targetPaths = new MemAllocProfilerPaths();
+
+        List<Entry> tops = new ArrayList<>();
+        for (Entry synthSubRoot : root.children.values()) {
+            tops.addAll(synthSubRoot.children.values());
+        }
+
+        groupBySrcSection(targetPaths, targetPaths.root, tops);
+        return targetPaths;
+    }
+
+    private void groupBySrcSection(MemAllocProfilerPaths targetPaths, Entry newParent, Collection<Entry> nonGroupedEntries) {
+        Map<SourceSection, List<Entry>> entriesBySection = new HashMap<>();
+
+        for (Entry nonGroupedEntry : nonGroupedEntries) {
+            List<Entry> group = entriesBySection.get(nonGroupedEntry.sourceSection);
+            if (group == null) {
+                group = new ArrayList<>();
+                entriesBySection.put(nonGroupedEntry.sourceSection, group);
+            }
+            group.add(nonGroupedEntry);
+        }
+
+        for (Map.Entry<SourceSection, List<Entry>> mapEntry : entriesBySection.entrySet()) {
+            List<Entry> nonGroupedChildren = new ArrayList<>();
+            Entry reducedEntry = null;
+            for (Entry entryForSameSect : mapEntry.getValue()) {
+                if (reducedEntry == null) {
+                    reducedEntry = new Entry(targetPaths, newParent, entryForSameSect.name, entryForSameSect.sourceSection);
+                }
+                reducedEntry.stats.add(entryForSameSect.stats);
+                nonGroupedChildren.addAll(entryForSameSect.children.values());
+            }
+            assert reducedEntry != null;
+            groupBySrcSection(targetPaths, reducedEntry, nonGroupedChildren);
+        }
+    }
+
+    /**
+     * Traverse the allocations hierarchy. This method is usually used by profiling tools for
+     * displaying the allocations.
+     *
+     * @param startEntry the start entry from which the traversal begins. It can be null to denote
+     *            the absolute root.
+     * @param consumer the consumer receiving the current stack (i.e. the path of entries to the
+     *            root entry)
+     * @param childrenEntriesComparator the comparator used to sort children
+     * @param levels the maximum number of hierarchy levels to traverse
+     * @param prependParentEntries include the parent entries of the root entry
+     */
+    public void traverse(Entry startEntry, Consumer<Deque<Entry>> consumer, Comparator<Entry> childrenEntriesComparator, int levels, boolean prependParentEntries) {
+        Entry se = startEntry;
+        if (se == null) {
+            se = root;
+        }
+        traverseEntry(se, consumer, childrenEntriesComparator, levels, prependParentEntries);
+    }
+
+    private void traverseEntry(Entry rootEntry, Consumer<Deque<Entry>> consumer, Comparator<Entry> childrenEntriesComparator, int levels, boolean prependParentEntries) {
+        ArrayDeque<Entry> stack = new ArrayDeque<>();
+        if (prependParentEntries) {
+            Entry e = rootEntry;
+            while (e != null) {
+                stack.addLast(e);
+                e = e.parent;
+            }
+        } else {
+            stack.push(rootEntry);
+        }
+        traverseStack(stack, consumer, childrenEntriesComparator, levels);
+    }
+
+    private void traverseStack(Deque<Entry> stack, Consumer<Deque<Entry>> consumer, Comparator<Entry> childrenEntriesComparator, int levels) {
+        if (levels <= 0) {
+            return;
+        }
+
+        consumer.accept(stack);
+        Collection<Entry> children = stack.peek().children.values();
+        Collection<Entry> sortedChildren;
+
+        if (childrenEntriesComparator != null) {
+            sortedChildren = new TreeSet<>(childrenEntriesComparator);
+            sortedChildren.addAll(children);
+        } else {
+            sortedChildren = children;
+        }
+
+        for (Entry childEntry : sortedChildren) {
+            stack.push(childEntry);
+            traverseStack(stack, consumer, childrenEntriesComparator, levels - 1);
+            stack.pop();
+        }
+    }
+
+    public static final class Entry {
+        // private static final SourceSection UNAVAILABLE_SECTION =
+        // Source.newBuilder("").name("unavailable").mimeType("").build().createUnavailableSection();
+
+        final MemAllocProfilerPaths paths;
+        final int id;
+        final String name;
+        final SourceSection sourceSection;
+        final Entry parent;
+        final Map<SourceSection, Entry> children = new ConcurrentHashMap<>();
+        final Stats stats = new Stats() {
+
+            @Override
+            public void set(long allocated, long count) {
+                synchronized (paths) {
+                    super.set(allocated, count);
+                    paths.version.incrementAndGet();
+                }
+            }
+        };
+
+        Entry(MemAllocProfilerPaths paths, Entry parent, String name, SourceSection sourceSection) {
+            this.paths = paths;
+            synchronized (paths) {
+                this.id = paths.idGen.getAndIncrement();
+                this.parent = parent;
+                this.name = name;
+                this.sourceSection = sourceSection == null ? Source.newBuilder("").name(name).mimeType("").build().createUnavailableSection() : sourceSection;
+                this.paths.entryMap.put(id, this);
+                if (parent != null) {
+                    parent.children.put(this.sourceSection, this);
+                }
+            }
+        }
+
+        @SuppressWarnings("unused")
+        Entry(MemAllocProfilerPaths paths, Entry parent, Entry original) {
+            this.paths = paths;
+            this.parent = parent;
+            assert parent == null || parent.paths == paths;
+            this.id = original.id;
+            this.name = original.name;
+            this.sourceSection = original.sourceSection;
+            this.paths.entryMap.put(id, this);
+            this.stats.add(original.stats);
+
+            if (parent != null) {
+                parent.children.put(sourceSection, this);
+            } else {
+                paths.root = this;
+            }
+
+            for (Entry origChild : original.children.values()) {
+                new Entry(paths, this, origChild);
+            }
+        }
+
+        public int getId() {
+            return id;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public SourceSection getSourceSection() {
+            return sourceSection;
+        }
+
+        public Entry getParent() {
+            return parent;
+        }
+
+        public Map<SourceSection, Entry> getChildren() {
+            return children;
+        }
+
+        public synchronized Entry[] getChildrenAsArray() {
+            return children.values().toArray(new Entry[children.size()]);
+        }
+
+        public Stats getStats() {
+            return stats;
+        }
+
+        public long getAllocatedAggr() {
+            long a = stats.allocated;
+            for (Entry childEntry : children.values()) {
+                a += childEntry.getAllocatedAggr();
+            }
+            return a;
+        }
+
+        public long getCountAggr() {
+            long a = stats.count;
+            for (Entry childEntry : children.values()) {
+                a += childEntry.getCountAggr();
+            }
+            return a;
+        }
+
+        public long getAllocated() {
+            return stats.allocated;
+        }
+
+        public long getCount() {
+            return stats.count;
+        }
+
+        Entry invert(MemAllocProfilerPaths targetPaths) {
+            return invert(targetPaths, new Entry(targetPaths, targetPaths.root, "", null), stats);
+        }
+
+        private Entry invert(MemAllocProfilerPaths targetPaths, Entry newParent, Stats rootStat) {
+            if (this == paths.root) {
+                return targetPaths.root;
+            }
+            Entry ie = new Entry(targetPaths, newParent, name, sourceSection);
+            if (parent.parent != null) {
+                Entry invertedParent = parent.invert(targetPaths, ie, rootStat);
+                ie.children.put(parent.sourceSection, invertedParent);
+            } else {
+                // Move the stats from the inverted node to its lowest child (which corresponds to
+                // the root in the original hierarchy). This way the stats of a parent entry in the
+                // hot-spot paths will be the aggregation of the children stats, i.e. the same fact
+                // as in the stacks paths.
+                ie.stats.add(rootStat);
+            }
+            return ie;
+        }
+
+        Entry merge(MemAllocProfilerPaths targetPaths, Entry other) {
+            Entry merged = new Entry(targetPaths, this.parent, this.name, this.sourceSection);
+            merged.children.putAll(this.children);
+            merged.children.putAll(other.children);
+            merged.stats.add(this.stats);
+            merged.stats.add(other.stats);
+            return merged;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("{name: %s, alloc: %s, count: %s}", name, stats.allocated, stats.count);
+        }
+    }
+
+    /**
+     * The summary allocation statistic.
+     */
+    public static class Stats {
+        private volatile long allocated;
+        private volatile long count;
+
+        /**
+         * @return the allocated memory in bytes
+         */
+        public final long getAllocated() {
+            return this.allocated;
+        }
+
+        /**
+         * @return the number of allocations
+         */
+        public final long getCount() {
+            return count;
+        }
+
+        /**
+         * Set the allocated memory in bytes and allocations count.
+         */
+        public void set(long allocated, long count) {
+            this.allocated = allocated;
+            this.count = count;
+        }
+
+        final void clear() {
+            set(0, 0);
+        }
+
+        final void add(long alloc, long cnt) {
+            set(this.allocated + alloc, this.count + cnt);
+        }
+
+        final void add(Stats other) {
+            add(other.allocated, other.count);
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerStacks.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerStacks.java
new file mode 100644
index 0000000000000000000000000000000000000000..2a4ee643bf26c8511908cfd87a0870dba7e03700
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/memprof/MemAllocProfilerStacks.java
@@ -0,0 +1,143 @@
+/*
+ * 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.runtime.instrument.memprof;
+
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentLinkedDeque;
+
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerPaths.Entry;
+import com.oracle.truffle.r.runtime.instrument.memprof.MemAllocProfilerPaths.Stats;
+import com.oracle.truffle.api.source.SourceSection;
+
+/**
+ * This class represents the hierarchical model of memory allocations. It is designed as a
+ * singleton, since it is assumed that there is at most one profiling session at any moment.
+ */
+public final class MemAllocProfilerStacks {
+
+    private static final MemAllocProfilerStacks instance = new MemAllocProfilerStacks();
+
+    final MemAllocProfilerPaths stackPaths = new MemAllocProfilerPaths();
+    final ConcurrentHashMap<Thread, Deque<Entry>> stacks = new ConcurrentHashMap<>();
+    final MemAllocProfilerPaths.Stats globalStats = new MemAllocProfilerPaths.Stats();
+
+    private MemAllocProfilerStacks() {
+
+    }
+
+    /**
+     * @return the single instance of the model
+     */
+    public static MemAllocProfilerStacks getInstance() {
+        return instance;
+    }
+
+    /**
+     * Clear the model.
+     */
+    public synchronized void clear() {
+        stackPaths.clear();
+        globalStats.clear();
+        stacks.clear();
+    }
+
+    /**
+     *
+     * @return the stack paths
+     */
+    public MemAllocProfilerPaths getStackPaths() {
+        return stackPaths;
+    }
+
+    /**
+     *
+     * @param id the id of the allocation entry
+     * @return the allocation entry
+     */
+    public Entry getEntry(int id) {
+        return stackPaths.getEntry(id);
+    }
+
+    /**
+     * @return the global (overall) allocations statistic
+     */
+    public Stats getGlobalStats() {
+        return globalStats;
+    }
+
+    void push(String name, SourceSection section) {
+        Deque<Entry> stack = getStackForThread();
+        Entry parentEntry = stack.peek();
+        Entry entry = parentEntry.children.get(section);
+        if (entry == null) {
+            entry = new Entry(stackPaths, parentEntry, name, section);
+        }
+        stack.push(entry);
+    }
+
+    private Deque<Entry> getStackForThread() {
+        return stacks.computeIfAbsent(Thread.currentThread(), (t) -> {
+            ConcurrentLinkedDeque<Entry> stk = new ConcurrentLinkedDeque<>();
+            Entry stackRoot = new Entry(stackPaths, stackPaths.getRootEntry(), "<" + Thread.currentThread().getName() + ">", null);
+            stk.add(stackRoot);
+            return stk;
+        });
+    }
+
+    void pop() {
+        Deque<Entry> stack = stacks.get(Thread.currentThread());
+        if (stack != null) {
+            // The stacks map might get cleared during the preceding execution of the instrumented
+            // node or its child node. Typically it happens if there is a function in a guest
+            // language turning off the profiler.
+            stack.pop();
+        }
+    }
+
+    void reportAllocation(long size) {
+        Deque<Entry> stack = stacks.get(Thread.currentThread());
+        if (stack != null) {
+            Entry entry = stack.peek();
+            globalStats.add(size, 1);
+            entry.stats.add(size, 1);
+        }
+    }
+
+    public static final class AlocatedAggrComparator implements Comparator<Entry> {
+
+        private final boolean desc;
+
+        public AlocatedAggrComparator(boolean desc) {
+            this.desc = desc;
+        }
+
+        @Override
+        public int compare(Entry e1, Entry e2) {
+            Long a1 = e1.getAllocatedAggr();
+            Long a2 = e2.getAllocatedAggr();
+            return desc ? a2.compareTo(a1) : a1.compareTo(a2);
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java
new file mode 100644
index 0000000000000000000000000000000000000000..5642fa86b7857bc1780b2f765ce375f571841be6
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/Foreign2R.java
@@ -0,0 +1,126 @@
+/*
+ * 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.runtime.interop;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+@ImportStatic({RRuntime.class})
+public abstract class Foreign2R extends RBaseNode {
+
+    @Child private Foreign2R recursive;
+    @Child private Node isBoxed;
+    @Child private Node unbox;
+
+    public static Foreign2R createForeign2R() {
+        return Foreign2RNodeGen.create();
+    }
+
+    public abstract Object execute(Object obj);
+
+    @Specialization
+    public byte doBoolean(boolean obj) {
+        return RRuntime.asLogical(obj);
+    }
+
+    @Specialization
+    public int doByte(byte obj) {
+        return ((Byte) obj).intValue();
+    }
+
+    @Specialization
+    public int doShort(short obj) {
+        return ((Short) obj).intValue();
+    }
+
+    @Specialization
+    public double doLong(long obj) {
+        return (((Long) obj).doubleValue());
+    }
+
+    @Specialization
+    public double doFloat(float obj) {
+        return (((Float) obj).doubleValue());
+    }
+
+    @Specialization
+    public String doChar(char obj) {
+        return ((Character) obj).toString();
+    }
+
+    @Specialization(guards = "isNull(obj)")
+    public RNull doNull(@SuppressWarnings("unused") Object obj) {
+        return RNull.instance;
+    }
+
+    @Specialization(guards = "isForeignObject(obj)")
+    public Object doUnbox(TruffleObject obj) {
+        /*
+         * For the time being, we have to ask "IS_BOXED" all the time (instead of simply trying
+         * UNBOX first), because some TruffleObjects return bogus values from UNBOX when IS_BOXED is
+         * false.
+         */
+        if (isBoxed == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            isBoxed = insert(Message.IS_BOXED.createNode());
+        }
+        if (ForeignAccess.sendIsBoxed(isBoxed, obj)) {
+            if (unbox == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                unbox = insert(Message.UNBOX.createNode());
+            }
+            try {
+                Object unboxed = ForeignAccess.sendUnbox(unbox, obj);
+                if (recursive == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    recursive = insert(Foreign2RNodeGen.create());
+                }
+                return recursive.execute(unboxed);
+            } catch (UnsupportedMessageException e) {
+                CompilerDirectives.transferToInterpreter();
+                throw RInternalError.shouldNotReachHere(e, "object does not support UNBOX message even though IS_BOXED == true: " + obj.getClass().getSimpleName());
+            }
+        }
+        return obj;
+    }
+
+    @Fallback
+    public Object doObject(Object obj) {
+        return obj;
+    }
+
+    protected boolean isNull(Object o) {
+        return o == null;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java
new file mode 100644
index 0000000000000000000000000000000000000000..ebf2d491225124af8bb65854e424c342c044ae02
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/ForeignArray2R.java
@@ -0,0 +1,337 @@
+/*
+ * 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.runtime.interop;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.ImportStatic;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ArityException;
+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.interop.java.JavaInterop;
+import com.oracle.truffle.api.nodes.Node;
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RNull;
+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.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+@ImportStatic({Message.class, RRuntime.class})
+public abstract class ForeignArray2R extends RBaseNode {
+
+    @Child protected Node hasSize = Message.HAS_SIZE.createNode();
+    @Child private Foreign2R foreign2R;
+    @Child private ForeignArray2R foreignArray2R;
+    @Child private Node read;
+    @Child private Node isNull;
+    @Child private Node isBoxed;
+    @Child private Node unbox;
+
+    public static ForeignArray2R createForeignArray2R() {
+        return ForeignArray2RNodeGen.create();
+    }
+
+    public abstract Object execute(Object obj, boolean recursive);
+
+    @Specialization(guards = {"isForeignArray(obj)"})
+    @TruffleBoundary
+    public RAbstractVector doArray(TruffleObject obj, boolean recursive,
+                    @Cached("GET_SIZE.createNode()") Node getSize) {
+        try {
+            CollectedElements ce = new CollectedElements();
+            collectArrayElements(ce, obj, recursive, getSize);
+            if (ce.elements.isEmpty()) {
+                return RDataFactory.createList();
+            }
+
+            return asAbstractVector(ce);
+        } catch (UnsupportedMessageException | UnknownIdentifierException e) {
+            throw error(RError.Message.GENERIC, "error while converting array: " + e.getMessage());
+        }
+    }
+
+    @Specialization(guards = "isJavaIterable(obj)")
+    @TruffleBoundary
+    protected RAbstractVector doJavaIterable(TruffleObject obj, boolean recursive,
+                    @Cached("createExecute(0).createNode()") Node execute) {
+
+        try {
+            CollectedElements ce = new CollectedElements();
+            ce = getIterableElements(ce, obj, recursive, execute);
+            return asAbstractVector(ce);
+        } catch (UnsupportedMessageException | UnknownIdentifierException | UnsupportedTypeException | ArityException e) {
+            throw error(RError.Message.GENERIC, "error while casting external object to list: " + e.getMessage());
+        }
+    }
+
+    @Fallback
+    public Object doObject(Object obj, @SuppressWarnings("unused") boolean recursive) {
+        return obj;
+    }
+
+    private void collectArrayElements(CollectedElements ce, TruffleObject obj, boolean recursive, Node getSize) throws UnsupportedMessageException, UnknownIdentifierException {
+        int size = (int) ForeignAccess.sendGetSize(getSize, obj);
+        if (size == 0) {
+            return;
+        }
+        for (int i = 0; i < size; i++) {
+            if (read == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                read = insert(Message.READ.createNode());
+            }
+            Object element = ForeignAccess.sendRead(read, obj, i);
+            if (recursive && (isForeignArray(element, hasSize) || isJavaIterable(element))) {
+                recurse(ce, element);
+            } else {
+                ce.elements.add(element2R(element, ce));
+            }
+        }
+    }
+
+    private CollectedElements getIterableElements(CollectedElements ce, TruffleObject obj, boolean recursive, Node execute)
+                    throws UnknownIdentifierException, ArityException, UnsupportedMessageException, UnsupportedTypeException {
+        if (read == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            read = insert(Message.READ.createNode());
+        }
+        TruffleObject itFunction = (TruffleObject) ForeignAccess.sendRead(read, obj, "iterator");
+        TruffleObject it = (TruffleObject) ForeignAccess.sendExecute(execute, itFunction);
+        TruffleObject hasNextFunction = (TruffleObject) ForeignAccess.sendRead(read, it, "hasNext");
+
+        while ((boolean) ForeignAccess.sendExecute(execute, hasNextFunction)) {
+            TruffleObject nextFunction = (TruffleObject) ForeignAccess.sendRead(read, it, "next");
+            Object element = ForeignAccess.sendExecute(execute, nextFunction);
+            if (recursive && (isJavaIterable(element) || isForeignArray(element, hasSize))) {
+                recurse(ce, element);
+            } else {
+                ce.elements.add(element2R(element, ce));
+            }
+        }
+        return ce;
+    }
+
+    private void recurse(CollectedElements ce, Object element) {
+        if (foreignArray2R == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            foreignArray2R = insert(createForeignArray2R());
+        }
+        RAbstractVector result = (RAbstractVector) foreignArray2R.execute(element, true);
+        for (int i = 0; i < result.getLength(); i++) {
+            Object value = result.getDataAtAsObject(i);
+            ce.elements.add(value);
+        }
+        ce.typeCheck.checkVector(result);
+    }
+
+    private Object element2R(Object value, CollectedElements ce) throws UnsupportedMessageException {
+        Object unboxedValue = value;
+        if (unboxedValue instanceof TruffleObject) {
+            if (isNull == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                isNull = insert(Message.IS_NULL.createNode());
+            }
+            if (ForeignAccess.sendIsNull(isNull, (TruffleObject) unboxedValue)) {
+                unboxedValue = RNull.instance;
+            } else {
+                if (isBoxed == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    isBoxed = insert(Message.IS_BOXED.createNode());
+                }
+                if (ForeignAccess.sendIsBoxed(isBoxed, (TruffleObject) unboxedValue)) {
+                    if (unbox == null) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        unbox = insert(Message.UNBOX.createNode());
+                    }
+                    unboxedValue = ForeignAccess.sendUnbox(unbox, (TruffleObject) unboxedValue);
+                }
+            }
+        }
+        ce.typeCheck.checkForeign(unboxedValue);
+
+        if (foreign2R == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            foreign2R = insert(Foreign2RNodeGen.create());
+        }
+        return foreign2R.execute(unboxedValue);
+    }
+
+    /**
+     * Converts the elements collected from a foreign array or java iterable into a vector or list.
+     */
+    public static RAbstractVector asAbstractVector(CollectedElements ce) {
+        InteropTypeCheck.RType type = ce.typeCheck.getType();
+        if (type == null) {
+            return RDataFactory.createList(ce.elements.toArray(new Object[ce.elements.size()]));
+        }
+        int size = ce.elements.size();
+        boolean complete = true;
+        switch (type) {
+            case BOOLEAN:
+                byte[] bytes = new byte[size];
+                for (int i = 0; i < size; i++) {
+                    bytes[i] = ((Number) ce.elements.get(i)).byteValue();
+                    complete &= RRuntime.isNA(bytes[i]);
+                }
+                return RDataFactory.createLogicalVector(bytes, complete);
+            case DOUBLE:
+                double[] doubles = new double[size];
+                for (int i = 0; i < size; i++) {
+                    doubles[i] = ((Number) ce.elements.get(i)).doubleValue();
+                    complete &= RRuntime.isNA(doubles[i]);
+                }
+                return RDataFactory.createDoubleVector(doubles, complete);
+            case INTEGER:
+                int[] ints = new int[size];
+                for (int i = 0; i < size; i++) {
+                    ints[i] = ((Number) ce.elements.get(i)).intValue();
+                    complete &= RRuntime.isNA(ints[i]);
+                }
+                return RDataFactory.createIntVector(ints, complete);
+            case STRING:
+                String[] strings = new String[size];
+                for (int i = 0; i < size; i++) {
+                    strings[i] = String.valueOf(ce.elements.get(i));
+                    complete &= RRuntime.isNA(strings[i]);
+                }
+                return RDataFactory.createStringVector(strings, complete);
+            default:
+                assert false;
+        }
+
+        // type != null but no vector created - how comes?
+        assert false : "did not handle properly: " + type;
+        return RDataFactory.createList(ce.elements.toArray(new Object[ce.elements.size()]));
+    }
+
+    protected boolean isForeignArray(Object obj) {
+        return RRuntime.isForeignObject(obj) && ForeignAccess.sendHasSize(hasSize, (TruffleObject) obj);
+    }
+
+    protected boolean isForeignVector(Object obj) {
+        return isJavaIterable(obj) || isForeignArray(obj, hasSize);
+    }
+
+    public static boolean isForeignArray(Object obj, Node hasSize) {
+        return RRuntime.isForeignObject(obj) && ForeignAccess.sendHasSize(hasSize, (TruffleObject) obj);
+    }
+
+    public static boolean isJavaIterable(Object obj) {
+        return RRuntime.isForeignObject(obj) && JavaInterop.isJavaObject(Iterable.class, (TruffleObject) obj);
+    }
+
+    public static boolean isForeignVector(Object obj, Node hasSize) {
+        return isJavaIterable(obj) || isForeignArray(obj, hasSize);
+    }
+
+    public static class InteropTypeCheck {
+        public enum RType {
+            BOOLEAN,
+            DOUBLE,
+            INTEGER,
+            STRING;
+        }
+
+        private RType type = null;
+        private boolean sameRType = true;
+
+        public void checkForeign(Object value) {
+            if (value instanceof Boolean) {
+                setType(RType.BOOLEAN);
+            } else if (value instanceof Byte || value instanceof Integer || value instanceof Short) {
+                setType(RType.INTEGER);
+            } else if (value instanceof Double || value instanceof Float || value instanceof Long) {
+                setType(RType.DOUBLE);
+            } else if (value instanceof Character || value instanceof String) {
+                setType(RType.STRING);
+            } else {
+                this.type = null;
+                sameRType = false;
+            }
+        }
+
+        public void checkVector(RAbstractVector value) {
+            if (value instanceof RAbstractLogicalVector) {
+                setType(RType.BOOLEAN);
+            } else if (value instanceof RAbstractIntVector) {
+                setType(RType.INTEGER);
+            } else if (value instanceof RAbstractDoubleVector) {
+                setType(RType.DOUBLE);
+            } else if (value instanceof RAbstractStringVector) {
+                setType(RType.STRING);
+            } else {
+                this.type = null;
+                sameRType = false;
+            }
+        }
+
+        private void setType(RType check) {
+            if (sameRType && this.type == null) {
+                this.type = check;
+            } else if (this.type != check) {
+                this.type = null;
+                sameRType = false;
+            }
+        }
+
+        public RType getType() {
+            return sameRType ? type : null;
+        }
+    }
+
+    public static class CollectedElements {
+        private InteropTypeCheck typeCheck = new InteropTypeCheck();
+        private List<Object> elements = new ArrayList<>();
+
+        public InteropTypeCheck getTypeCheck() {
+            return typeCheck;
+        }
+
+        public void setTypeCheck(InteropTypeCheck typeCheck) {
+            this.typeCheck = typeCheck;
+        }
+
+        public List<Object> getElements() {
+            return elements;
+        }
+
+        public void setElements(List<Object> elements) {
+            this.elements = elements;
+        }
+
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/R2Foreign.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/R2Foreign.java
new file mode 100644
index 0000000000000000000000000000000000000000..84139962e0c9a827b4d07e0f93614741b74ea5e4
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/interop/R2Foreign.java
@@ -0,0 +1,124 @@
+/*
+ * 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.runtime.interop;
+
+import com.oracle.truffle.api.dsl.Fallback;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropByte;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropChar;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropFloat;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropLong;
+import com.oracle.truffle.r.runtime.data.RInteropScalar.RInteropShort;
+import com.oracle.truffle.r.runtime.data.RRaw;
+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.RAbstractLogicalVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector;
+import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+public abstract class R2Foreign extends RBaseNode {
+
+    public abstract Object execute(Object obj);
+
+    @Specialization
+    public boolean doByte(byte obj) {
+        return RRuntime.fromLogical(obj);
+    }
+
+    @Specialization()
+    public double doDouble(double vec) {
+        return vec;
+    }
+
+    @Specialization()
+    public int doInt(int vec) {
+        return vec;
+    }
+
+    @Specialization()
+    public String doString(String vec) {
+        return vec;
+    }
+
+    @Specialization()
+    public byte doRaw(RRaw vec) {
+        return vec.getValue();
+    }
+
+    @Specialization(guards = "vec.getLength() == 1")
+    public double doDoubleVector(RAbstractDoubleVector vec) {
+        return vec.getDataAt(0);
+    }
+
+    @Specialization(guards = "vec.getLength() == 1")
+    public int doIntVector(RAbstractIntVector vec) {
+        return vec.getDataAt(0);
+    }
+
+    @Specialization(guards = "vec.getLength() == 1")
+    public boolean doLogicalVector(RAbstractLogicalVector vec) {
+        return vec.getDataAt(0) == RRuntime.LOGICAL_TRUE;
+    }
+
+    @Specialization(guards = "vec.getLength() == 1")
+    public byte doRawVector(RAbstractRawVector vec) {
+        return vec.getDataAt(0).getValue();
+    }
+
+    @Specialization(guards = "vec.getLength() == 1")
+    public String doStringVector(RAbstractStringVector vec) {
+        return vec.getDataAt(0);
+    }
+
+    @Specialization
+    public byte doInteroptByte(RInteropByte obj) {
+        return obj.getValue();
+    }
+
+    @Specialization
+    public char doInteroptChar(RInteropChar obj) {
+        return obj.getValue();
+    }
+
+    @Specialization
+    public float doInteroptFloat(RInteropFloat obj) {
+        return obj.getValue();
+    }
+
+    @Specialization
+    public long doInteroptLong(RInteropLong obj) {
+        return obj.getValue();
+    }
+
+    @Specialization
+    public short doInteroptShort(RInteropShort obj) {
+        return obj.getValue();
+    }
+
+    @Fallback
+    public static Object doObject(Object obj) {
+        return obj;
+    }
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Choose.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Choose.java
index 6dc04a9255387cc41f8b9a905923b71dbbbd870c..2f721295ac66a33f2d87ab2941bae1fe1aafcafb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Choose.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Choose.java
@@ -15,6 +15,7 @@ package com.oracle.truffle.r.runtime.nmath;
 import static com.oracle.truffle.r.runtime.nmath.GammaFunctions.lgammafn;
 import static com.oracle.truffle.r.runtime.nmath.GammaFunctions.lgammafnSign;
 
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.RError.Message;
 
 // transcribed from nmath/choose.c
@@ -26,6 +27,7 @@ public class Choose {
         return -Math.log(n + 1.) - LBeta.lbeta(n - k + 1., k + 1.);
     }
 
+    @TruffleBoundary
     public static double choose(double n, double ka) {
         double k = ka;
         if (Double.isNaN(n) || Double.isNaN(ka)) {
@@ -76,6 +78,7 @@ public class Choose {
         return Math.exp(lfastchoose(n, k));
     }
 
+    @TruffleBoundary
     public static double lchoose(double n, double kIn) {
         double k = RMath.forceint(kIn);
         /* NaNs propagated correctly */
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
index 99bed23f0f6583742e665a737cadaddb883f6125..f9fea752a258a036dd7fd1d9a5b3036059e36f9e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/EvaluatedArgumentsVisitor.java
@@ -79,7 +79,7 @@ public final class EvaluatedArgumentsVisitor extends RSyntaxVisitor<Info> {
     private static final Set<String> wellKnownFunctions = new HashSet<>(Arrays.asList("c", "$", "@", "[", "[[", "any", "dim", "dimnames", "rownames", "colnames", "is.null", "list", "names", "return",
                     "print", "length", "rep", "inherits", "min", "max", "matrix", "table", "is.array", "is.element", "is.character", "exp", "all", "pmin", "pmax", "as.numeric", "proc.time",
                     "as.integer", "as.character", "as.matrix", ".Call", "sum", "order", "rev", "integer", "double", "as.numeric", "as.list", "as.integer", ".Call", ".FastR", "unname", "log", "lgamma",
-                    "sin", "cos", "tan", "exp", "log", "expm1", "sinh", "sinpi", "cosh", "cospi", "tanh", "tanpi", "asin", "asinh", "acos", "acosh", "atan", "atanh", "<-", "+", "-",
+                    "sin", "cos", "tan", "exp", "log", "expm1", "sinh", "sinpi", "cosh", "cospi", "tanh", "tanpi", "asin", "asinh", "acos", "acosh", "atan", "atanh", "+", "-",
                     "*", "/", "%%", "^", ":", ">=", ">", "<=", "<", "==", "!=", "||", "|", "&&", "&", "!", "%o%", "%*%", "%/%", "%in%", "{", "for", "while", "repeat", "if", "attributes", "attr"));
 
     private EvaluatedArgumentsVisitor() {
@@ -122,7 +122,26 @@ public final class EvaluatedArgumentsVisitor extends RSyntaxVisitor<Info> {
                     }
                 }
             }
-            if (wellKnownFunctions.contains(symbol)) {
+            if (symbol.equals("<-")) {
+                Info info = Info.createNew();
+                assert arguments.length == 2;
+                RSyntaxElement current = arguments[0];
+                if (arguments[0] instanceof RSyntaxLookup) {
+                    info.maybeAssignedNames.add(((RSyntaxLookup) arguments[0]).getIdentifier());
+                } else {
+                    info.addBefore(accept(arguments[0]));
+                    while (current instanceof RSyntaxCall) {
+                        current = ((RSyntaxCall) current).getSyntaxArguments()[0];
+                    }
+                    if (current instanceof RSyntaxLookup) {
+                        info.evaluatedNames.add(((RSyntaxLookup) current).getIdentifier());
+                    } else {
+                        return Info.ANY;
+                    }
+                }
+                info.addBefore(accept(arguments[1]));
+                return info;
+            } else if (wellKnownFunctions.contains(symbol)) {
                 Info info = Info.createNew();
                 switch (symbol) {
                     case "||":
@@ -135,24 +154,6 @@ public final class EvaluatedArgumentsVisitor extends RSyntaxVisitor<Info> {
                             info.addBefore(accept(arguments[0]));
                         }
                         return info;
-                    case "<-":
-                        assert arguments.length == 2;
-                        RSyntaxElement current = arguments[0];
-                        if (arguments[0] instanceof RSyntaxLookup) {
-                            info.maybeAssignedNames.add(((RSyntaxLookup) arguments[0]).getIdentifier());
-                        } else {
-                            info.addBefore(accept(arguments[0]));
-                            while (current instanceof RSyntaxCall) {
-                                current = ((RSyntaxCall) current).getSyntaxArguments()[0];
-                            }
-                            if (current instanceof RSyntaxLookup) {
-                                info.evaluatedNames.add(((RSyntaxLookup) current).getIdentifier());
-                            } else {
-                                return Info.ANY;
-                            }
-                        }
-                        info.addBefore(accept(arguments[1]));
-                        return info;
                     case "repeat":
                         assert arguments.length == 1;
                         return accept(arguments[0]);
@@ -244,4 +245,25 @@ public final class EvaluatedArgumentsVisitor extends RSyntaxVisitor<Info> {
         }
         return false;
     }
+
+    /**
+     * If any of the arguments has assignment call in it, we fallback to unoptimized promises.
+     */
+    public static boolean hasAssignmentCall(RSyntaxElement node) {
+        if (node instanceof RSyntaxCall) {
+            RSyntaxCall call = (RSyntaxCall) node;
+            RSyntaxElement lhs = call.getSyntaxLHS();
+            if (lhs instanceof RSyntaxLookup) {
+                if (((RSyntaxLookup) lhs).getIdentifier().equals("<-")) {
+                    return true;
+                }
+                for (RSyntaxElement arg : call.getSyntaxArguments()) {
+                    if (hasAssignmentCall(arg)) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
index daf76f959261c863f07ff7b965c87c8d9b4687e3..b5ca21981bfe53d4b6a49a9e5651c54fe5a52bd6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RBaseNode.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.r.runtime.RError.RErrorException;
 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.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RExpression;
@@ -211,6 +212,10 @@ public abstract class RBaseNode extends Node {
         }
     }
 
+    protected final TruffleRLanguage getRLanguage() {
+        return getRootNode().getLanguage(RContext.getTruffleRLanguage());
+    }
+
     protected static boolean isRAbstractContainer(Object value) {
         return value instanceof RAbstractContainer;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
index 7ae457924a12626dfd83a539a3b19ebbea093ab6..8fcd0952d9242aa7c254c254d48d719c99a0e8d6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RCodeBuilder.java
@@ -30,6 +30,8 @@ import java.util.List;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 
 /**
  * Implementers of this interface can be used to generate a representation of an R closure.
@@ -156,12 +158,12 @@ public interface RCodeBuilder<T> {
      * names - if it is non-null, it represents the left hand side that this function is assigned
      * to.
      */
-    T function(SourceSection source, List<Argument<T>> arguments, T body, Object assignedTo);
+    T function(TruffleRLanguage language, SourceSection source, List<Argument<T>> arguments, T body, Object assignedTo);
 
     /**
      * Creates a new call target from a given function expression literal.
      */
-    RootCallTarget rootFunction(SourceSection source, List<Argument<T>> arguments, T body, String name);
+    RootCallTarget rootFunction(TruffleRLanguage language, SourceSection source, List<Argument<T>> arguments, T body, String name);
 
     void setContext(CodeBuilderContext context);
 
@@ -203,7 +205,7 @@ public interface RCodeBuilder<T> {
                 if (element.getSyntaxBody() == element)
                     return (T) element;
                 ArrayList<Argument<T>> params = createArguments(element.getSyntaxSignature(), element.getSyntaxArgumentDefaults());
-                return function(element.getLazySourceSection(), params, accept(element.getSyntaxBody()), element.getSyntaxDebugName());
+                return function(RContext.getInstance().getLanguage(), element.getLazySourceSection(), params, accept(element.getSyntaxBody()), element.getSyntaxDebugName());
             }
         }.accept(original);
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxFunction.java
index 0539766d5a960249d716461c4a4d59062ae389e7..55fc97d8d9602d4165b6bbae4f926d3825e2de70 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxFunction.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxFunction.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -22,7 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.nodes;
 
-import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 
 /**
@@ -39,45 +38,4 @@ public interface RSyntaxFunction extends RSyntaxElement {
 
     String getSyntaxDebugName();
 
-    /**
-     * Helper function: creates a synthetic RSyntaxFunction.
-     */
-    static RSyntaxFunction createDummyFunction(SourceSection originalSource, ArgumentsSignature signature, RSyntaxElement[] arguments, RSyntaxElement body, String debugName) {
-        return new RSyntaxFunction() {
-            @Override
-            public SourceSection getLazySourceSection() {
-                return originalSource;
-            }
-
-            @Override
-            public SourceSection getSourceSection() {
-                return originalSource;
-            }
-
-            @Override
-            public ArgumentsSignature getSyntaxSignature() {
-                return signature;
-            }
-
-            @Override
-            public RSyntaxElement[] getSyntaxArgumentDefaults() {
-                return arguments;
-            }
-
-            @Override
-            public RSyntaxElement getSyntaxBody() {
-                return body;
-            }
-
-            @Override
-            public void setSourceSection(SourceSection src) {
-                // ignored
-            }
-
-            @Override
-            public String getSyntaxDebugName() {
-                return debugName;
-            }
-        };
-    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNode.java
index 98c4d2bad33d311394b65ca2139534dceb4dad2a..237803da857b684bfbc1b2f33f907c232bf164ce 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxNode.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
@@ -100,4 +100,14 @@ public interface RSyntaxNode extends RSyntaxElement {
     public default <T> T accept(final IRSyntaxNodeVisitor<T> visitor) {
         return visitor.visit(this);
     }
+
+    static boolean isInternal(SourceSection sourceSection) {
+        if (sourceSection == RSyntaxNode.INTERNAL) {
+            return true;
+        } else if (sourceSection == RSyntaxNode.LAZY_DEPARSE) {
+            return false;
+        } else {
+            return sourceSection == null || sourceSection.getSource().isInternal();
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapperFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapperFactory.java
index b385fc6fe9e9e4f4e5d4c02a47eafeed9e53ae18..de50cdebb746e6df003362d6becab0266bca2c69 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapperFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/instrumentation/RNodeWrapperFactory.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.instrumentation.ProbeNode;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.nodes.NodeCost;
 import com.oracle.truffle.api.nodes.NodeInfo;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
@@ -97,6 +98,11 @@ public final class RNodeWrapperFactory implements InstrumentableFactory<RNode> {
         public RSyntaxNode getRSyntaxNode() {
             return delegate.asRSyntaxNode();
         }
+
+        @Override
+        public SourceSection getSourceSection() {
+            return delegate.getSourceSection();
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
index 094a55ae51703b3f4a25cb90fd857b078be8d3a4..1b9ed88d1a860aac112f5e491bb8f9a2131b792b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java
@@ -16,7 +16,7 @@ import static com.oracle.truffle.r.runtime.RDispatch.OPS_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.RRuntime.INT_NA;
 import static com.oracle.truffle.r.runtime.RRuntime.isFinite;
 import static com.oracle.truffle.r.runtime.RRuntime.isNAorNaN;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.api.CompilerDirectives;
@@ -44,31 +44,31 @@ public abstract class BinaryArithmetic extends Operation {
 
     /* Fake RBuiltins to unify the binary operations */
 
-    @RBuiltin(name = "+", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "+", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class AddBuiltin {
     }
 
-    @RBuiltin(name = "-", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "-", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class SubtractBuiltin {
     }
 
-    @RBuiltin(name = "/", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "/", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class DivBuiltin {
     }
 
-    @RBuiltin(name = "%/%", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "%/%", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class IntegerDivBuiltin {
     }
 
-    @RBuiltin(name = "%%", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "%%", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class ModBuiltin {
     }
 
-    @RBuiltin(name = "*", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "*", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class MultiplyBuiltin {
     }
 
-    @RBuiltin(name = "^", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "^", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class PowBuiltin {
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
index 12212196eb77623d5deb391293db982acead89fe..9184991c3f776d94877dd14dd289c2bcea468af7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryCompare.java
@@ -23,7 +23,7 @@
 package com.oracle.truffle.r.runtime.ops;
 
 import static com.oracle.truffle.r.runtime.RDispatch.OPS_GROUP_GENERIC;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.r.runtime.RError;
@@ -36,27 +36,27 @@ import com.oracle.truffle.r.runtime.data.RComplex;
 public abstract class BinaryCompare extends BooleanOperation {
 
     /* Fake RBuiltins to unify the compare operations */
-    @RBuiltin(name = "==", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "==", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class EqualBuiltin {
     }
 
-    @RBuiltin(name = "!=", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "!=", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class NotEqualBuiltin {
     }
 
-    @RBuiltin(name = ">=", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = ">=", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class GreaterEqualBuiltin {
     }
 
-    @RBuiltin(name = ">", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = ">", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class GreaterBuiltin {
     }
 
-    @RBuiltin(name = "<=", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "<=", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class LessEqualBuiltin {
     }
 
-    @RBuiltin(name = "<", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "<", kind = PRIMITIVE, parameterNames = {"", ""}, alwaysSplit = true, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class LessBuiltin {
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
index ef9b7f15c4db0cf6214be8aed4e17b16fa1facd1..0686194d1026889dcccd3c935dfad63e5250feab 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryLogic.java
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.runtime.ops;
 
 import static com.oracle.truffle.r.runtime.RDispatch.OPS_GROUP_GENERIC;
 import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
-import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
+import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE_ARITHMETIC;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 
 import com.oracle.truffle.r.runtime.RError;
@@ -48,11 +48,11 @@ public abstract class BinaryLogic extends BooleanOperation {
     public static class NonVectorOrBuiltin {
     }
 
-    @RBuiltin(name = "&", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "&", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class AndBuiltin {
     }
 
-    @RBuiltin(name = "|", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE)
+    @RBuiltin(name = "|", kind = PRIMITIVE, parameterNames = {"", ""}, dispatch = OPS_GROUP_GENERIC, behavior = PURE_ARITHMETIC)
     public static class OrBuiltin {
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/Operation.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/Operation.java
index 96ad234f0340a3f0d7b856877dc6c551c1a829a6..475484aa6cb034290bb28759ac3de978ed7cd2c6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/Operation.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/Operation.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
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.runtime.ops;
 
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
+import com.oracle.truffle.r.runtime.ReturnException;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 
 public class Operation extends RBaseNode {
@@ -45,6 +46,12 @@ public class Operation extends RBaseNode {
     }
 
     public static RuntimeException handleException(Throwable e) {
-        throw e instanceof RError ? (RError) e : RInternalError.shouldNotReachHere(e, "only RErrors should be thrown by arithmetic ops");
+        if (e instanceof RError) {
+            throw (RError) e;
+        } else if (e instanceof ReturnException) {
+            throw (ReturnException) e;
+        } else {
+            throw RInternalError.shouldNotReachHere(e, "only RErrors or ReturnExceptions should be thrown by arithmetic ops");
+        }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
index 924015da662ec4140f5a4e1379c837ac914571ee..f32b5bd1895888e51be17e5273436b3f63572c36 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java
@@ -7,16 +7,22 @@
  * Copyright (c) 1998, Ross Ihaka
  * Copyright (c) 1998-2012, The R Core Team
  * Copyright (c) 2005, The R Foundation
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
 package com.oracle.truffle.r.runtime.ops;
 
+import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RError.Message;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 
+/**
+ * Base class for the implementation of unary arithmetic operations. This covers functions like "+",
+ * "-", "sqrt", and many more.
+ */
 public abstract class UnaryArithmetic extends Operation {
 
     public static final UnaryArithmeticFactory NEGATE = Negate::new;
@@ -26,24 +32,62 @@ public abstract class UnaryArithmetic extends Operation {
         super(false, false);
     }
 
+    /**
+     * The lowest type with which this operation will be executed. E.g., if this is double, then
+     * integer arguments will be coerced to double before performing the actual operation.
+     */
+    public RType getMinPrecedence() {
+        return RType.Double;
+    }
+
+    /**
+     * Specifies the error that will be raised for invalid argument types.
+     */
+    public Message getArgumentError() {
+        return RError.Message.NON_NUMERIC_MATH;
+    }
+
+    /**
+     * Determines, for a given argument type (after coercion according to
+     * {@link #getMinPrecedence()}), the type of the return value. This is mainly intended to
+     * support operations that return double values for complex arguments.
+     */
     public RType calculateResultType(RType argumentType) {
         return argumentType;
     }
 
-    public abstract int op(byte op);
+    public int op(@SuppressWarnings("unused") byte op) {
+        throw new UnsupportedOperationException();
+    }
 
-    public abstract int op(int op);
+    public int op(@SuppressWarnings("unused") int op) {
+        throw new UnsupportedOperationException();
+    }
 
-    public abstract double op(double op);
+    public double op(@SuppressWarnings("unused") double op) {
+        throw new UnsupportedOperationException();
+    }
 
-    public abstract RComplex op(double re, double im);
+    public RComplex op(double re, double im) {
+        // default: perform operation on real and imaginary part
+        return RDataFactory.createComplex(op(re), op(im));
+    }
 
-    @SuppressWarnings("unused")
-    public double opd(double re, double im) {
+    public double opd(@SuppressWarnings("unused") double re, @SuppressWarnings("unused") double im) {
         throw new UnsupportedOperationException();
     }
 
-    public static class Negate extends UnaryArithmetic {
+    public static final class Negate extends UnaryArithmetic {
+
+        @Override
+        public RType getMinPrecedence() {
+            return RType.Integer;
+        }
+
+        @Override
+        public Message getArgumentError() {
+            return RError.Message.INVALID_ARG_UNARY;
+        }
 
         @Override
         public int op(int op) {
@@ -59,14 +103,19 @@ public abstract class UnaryArithmetic extends Operation {
         public int op(byte op) {
             return -(int) op;
         }
+    }
+
+    public static final class Plus extends UnaryArithmetic {
 
         @Override
-        public RComplex op(double re, double im) {
-            return RDataFactory.createComplex(op(re), op(im));
+        public RType getMinPrecedence() {
+            return RType.Integer;
         }
-    }
 
-    public static class Plus extends UnaryArithmetic {
+        @Override
+        public Message getArgumentError() {
+            return RError.Message.INVALID_ARG_UNARY;
+        }
 
         @Override
         public int op(int op) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
index e2e074001a610d9986a58019244841194b560ed8..eecc1c27b5f9536182fffd46fdddde09a55d3c1b 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
@@ -410,7 +410,7 @@ public class RRNG {
     public static void putRNGState() {
         int[] seeds = currentGenerator().getSeeds();
         seeds[0] = currentKind().ordinal() + 100 * currentNormKind().ordinal();
-        RIntVector vector = RDataFactory.createIntVector(seeds, RDataFactory.COMPLETE_VECTOR);
+        RIntVector vector = RDataFactory.createIntVector(seeds, RDataFactory.INCOMPLETE_VECTOR);
         REnvironment.globalEnv().safePut(RANDOM_SEED, vector.makeSharedPermanent());
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
index 27203104d213c47c8406464d4daef8f9a6c816e3..3e0cbf8fc85f520efcc9df5b8a3ac0da82f7036c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
@@ -25,9 +25,9 @@ package com.oracle.truffle.r.runtime.rng.user;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
-import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.RootNode;
+import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -36,6 +36,7 @@ import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
+import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.rng.RRNG.Kind;
 import com.oracle.truffle.r.runtime.rng.RandomNumberGenerator;
 
@@ -76,11 +77,23 @@ public final class UserRNG implements RandomNumberGenerator {
     private int nSeeds = 0;
 
     private abstract static class UserRNGRootNodeAdapter extends RootNode {
-        @Child protected UserRngRFFI.UserRngRFFINode userRngRFFINode = RFFIFactory.getRFFI().getUserRngRFFI().createUserRngRFFINode();
+        @Child protected UserRngRFFI.InitNode initNode = RFFIFactory.getUserRngRFFI().createInitNode();
+        @Child protected UserRngRFFI.RandNode randNode = RFFIFactory.getUserRngRFFI().createRandNode();
+        @Child protected UserRngRFFI.NSeedNode nSeedNode = RFFIFactory.getUserRngRFFI().createNSeedNode();
+        @Child protected UserRngRFFI.SeedsNode seedsNode = RFFIFactory.getUserRngRFFI().createSeedsNode();
 
-        @SuppressWarnings("deprecation")
         protected UserRNGRootNodeAdapter() {
-            super(RContext.getRRuntimeASTAccess().getTruffleRLanguage(), null, new FrameDescriptor());
+            /*
+             * TODO: Ideally, we wouldn't need to use the generic lookup here, but rather pass along
+             * the language object. However, given the current structure of the RNG code, this is
+             * not practical.
+             */
+            super(RContext.getInstance().getLanguage());
+        }
+
+        @Override
+        public SourceSection getSourceSection() {
+            return RSyntaxNode.INTERNAL;
         }
     }
 
@@ -91,12 +104,12 @@ public final class UserRNG implements RandomNumberGenerator {
             Function function = (Function) args[0];
             switch (function) {
                 case Init:
-                    userRngRFFINode.init((int) args[1]);
+                    initNode.execute((int) args[1]);
                     return RNull.instance;
                 case NSeed:
-                    return userRngRFFINode.nSeed();
+                    return nSeedNode.execute();
                 case Seedloc:
-                    userRngRFFINode.seeds((int[]) args[1]);
+                    seedsNode.execute((int[]) args[1]);
                     return RNull.instance;
                 default:
                     throw RInternalError.shouldNotReachHere();
@@ -108,7 +121,7 @@ public final class UserRNG implements RandomNumberGenerator {
 
         @Override
         public Object execute(VirtualFrame frame) {
-            return userRngRFFINode.rand();
+            return randNode.execute();
         }
     }
 
diff --git a/com.oracle.truffle.r.test.native/packages/pkg-filelist b/com.oracle.truffle.r.test.native/packages/pkg-filelist
index 55e8fe1d119cba8985cc07155a0b23dbb05b4079..b9b4ec844e03cf8b86fba09a32144d08358196c9 100644
--- a/com.oracle.truffle.r.test.native/packages/pkg-filelist
+++ b/com.oracle.truffle.r.test.native/packages/pkg-filelist
@@ -1,3 +1,2 @@
 vanilla
-tests4
 testrffi
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
index 93443593a81e7a51e33ea5635caad97d4aff06e2..3a42a04a2271889f441a4a896c8f6c49fe69d050 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/R/testrffi.R
@@ -2,7 +2,7 @@
 	library.dynam.unload("testrffi", libpath)
 
 rffi.dotCModifiedArguments <- function(data) {
-	.C("dotCModifiedArguments", length(data), as.integer(data), as.double(data), as.logical(data))
+	.C("dotCModifiedArguments", length(data), as.integer(data), as.double(data), as.logical(data), as.character(data))
 }
 
 rffi.addInt <- function(a, b) {
@@ -153,6 +153,26 @@ rffi.LENGTH <- function(x) {
 	.Call("test_LENGTH", x)
 }
 
+rffi.inlined_length <- function(x) {
+    .Call("test_inlined_length", x)
+}
+
 rffi.coerceVector <- function(x, mode) {
 	.Call("test_coerceVector", x, mode)
 }
+
+rffi.ATTRIB <- function(x) {
+    .Call('test_ATTRIB', x);
+}
+
+rffi.getStringNA <- function() {
+    .Call("test_stringNA")
+}
+
+rffi.captureDotsWithSingleElement <- function(env) {
+    .Call('test_captureDotsWithSingleElement', env)
+}
+
+rffi.evalAndNativeArrays <- function(vec, expr, env) {
+    .Call('test_evalAndNativeArrays', vec, expr, env)
+}
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
index cfddf3c96f7a168ff11332d2e75925e448986e4d..4323f77fb08e4282b0d30fa345257ef0d94160a2 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/init.c
@@ -26,7 +26,7 @@
 #include "testrffi.h"
 
 static const R_CMethodDef CEntries[]  = {
-    {"dotCModifiedArguments", (DL_FUNC) &dotCModifiedArguments, 4},
+    {"dotCModifiedArguments", (DL_FUNC) &dotCModifiedArguments, 5},
     {NULL, NULL, 0}
 };
 
@@ -71,7 +71,12 @@ static const R_CallMethodDef CallEntries[] = {
         CALLDEF(test_CAR, 1),
         CALLDEF(test_CDR, 1),
         CALLDEF(test_LENGTH, 1),
+        CALLDEF(test_inlined_length, 1),
         CALLDEF(test_coerceVector, 2),
+        CALLDEF(test_ATTRIB, 1),
+        CALLDEF(test_stringNA, 0),
+        CALLDEF(test_captureDotsWithSingleElement, 1),
+        CALLDEF(test_evalAndNativeArrays, 3),
         {NULL, NULL, 0}
 };
 
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
index 364653bd0d88d9e00c2bf5d8f42d489068749663..9f92cbc5addbde7e7dba94d0bc74f37546fa3194 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.c
@@ -30,7 +30,7 @@
 #include <Rinterface.h>
 #include "testrffi.h"
 
-void dotCModifiedArguments(int* len, int* idata, double* rdata, int* ldata) {
+void dotCModifiedArguments(int* len, int* idata, double* rdata, int* ldata, char** cdata) {
     for (int i = 0; i < len[0]; i++) {
 	idata[i] ++;
     }
@@ -38,7 +38,13 @@ void dotCModifiedArguments(int* len, int* idata, double* rdata, int* ldata) {
 	rdata[i] *= 0.2;
     }
     for (int i = 0; i < len[0]; i++) {
-	ldata[i] = ldata[i] == 0 ? 1 : 0;
+    ldata[i] = ldata[i] == 0 ? 1 : 0;
+    }
+    for (int i = 0; i < len[0]; i++) {
+        for (int j = 0; cdata[i][j] != 0; j++) {
+            char c = cdata[i][j];
+            cdata[i][j] = (c >= '0' && c <= '9') ? c - '0' + 'a' : 'r';
+        }
     }
 }
 
@@ -318,8 +324,110 @@ SEXP test_LENGTH(SEXP x) {
 	return ScalarInteger(LENGTH(x));
 }
 
+SEXP test_inlined_length(SEXP x) {
+    return ScalarInteger(length(x));
+}
+
 SEXP test_coerceVector(SEXP x, SEXP mode) {
     int intMode = INTEGER_VALUE(mode);
     return Rf_coerceVector(x, intMode);
 }
 
+SEXP test_ATTRIB(SEXP x) {
+    return ATTRIB(x);
+}
+
+SEXP test_stringNA(void) {
+    SEXP x = allocVector(STRSXP, 1);
+    SET_STRING_ELT(x, 0, NA_STRING);
+    return x;
+}
+
+// This function is expected to be called only with environment that has single
+// promise value in the '...' variable and this is asserted inside this function.
+// The return value is list with the promises' expression and environment.
+SEXP test_captureDotsWithSingleElement(SEXP env) {
+    SEXP dots = findVarInFrame3(env, R_DotsSymbol, TRUE);
+    int n_dots = length(dots);
+    if (n_dots != 1) {
+        printf("Error: test_captureDotsWithSingleElement expectes single promise in ...\n");
+        return R_NilValue;
+    }
+    SEXP promise = CAR(dots);
+    if (TYPEOF(promise) != PROMSXP) {
+        printf("Error: test_captureDotsWithSingleElement expectes a promise in ...\n");
+        return R_NilValue;
+    }
+    SEXP info = PROTECT(allocVector(VECSXP, 2));
+    SET_VECTOR_ELT(info, 0, R_PromiseExpr(promise));
+    SET_VECTOR_ELT(info, 1, PRENV(promise));
+    UNPROTECT(1);
+    return info;
+}
+
+SEXP test_evalAndNativeArrays(SEXP vec, SEXP expr, SEXP env) {
+    SEXP symbolValue;
+    int *idata;
+    double *ddata;
+    unsigned char *bdata;
+    // note: we want to evaluate PROTECT(symbolValue = Rf_eval(expr, env)); after we take the pointer to data...
+    switch (TYPEOF(vec)) {
+        case INTSXP:
+            idata = INTEGER(vec);
+            PROTECT(symbolValue = Rf_eval(expr, env));
+            idata[0] = 42;
+            idata[1] = Rf_asInteger(symbolValue);
+            break;
+        case REALSXP:
+            ddata = REAL(vec);
+            PROTECT(symbolValue = Rf_eval(expr, env));
+            ddata[0] = 42;
+            ddata[1] = Rf_asReal(symbolValue);
+            break;
+        case RAWSXP:
+            bdata = RAW(vec);
+            PROTECT(symbolValue = Rf_eval(expr, env));
+            bdata[0] = 42;
+            bdata[1] = Rf_asInteger(symbolValue);  // there is no asRaw, we expect to get symbol with integer value
+            break;
+        case LGLSXP:
+            idata = LOGICAL(vec);
+            PROTECT(symbolValue = Rf_eval(expr, env));
+            idata[0] = 1;
+            idata[1] = Rf_asLogical(symbolValue);
+            break;
+        default:
+            printf("Error: unexpected type");
+    }
+
+    // max of the vector could now be 42/TRUE or symbolValue
+    SEXP maxSymbol, call, maxVec;
+    int uprotectCount = 1;
+    if (TYPEOF(vec) != RAWSXP) {
+        // note: max does not support raws
+        PROTECT(maxSymbol = install("max"));
+        PROTECT(call = lang2(maxSymbol, vec));
+        PROTECT(maxVec = eval(call, R_GlobalEnv));
+        uprotectCount = 4;
+    }
+
+    switch (TYPEOF(vec)) {
+        case INTSXP:
+            idata[length(vec) - 1] = Rf_asInteger(maxVec);
+            break;
+        case REALSXP:
+            ddata[length(vec) - 1] = Rf_asReal(maxVec);
+            break;
+        case RAWSXP:
+            bdata[length(vec) - 1] = 42;
+            break;
+        case LGLSXP:
+            idata[length(vec) - 1] = Rf_asLogical(maxVec);
+            break;
+        default:
+            printf("Error: unexpected type");
+    }
+
+    UNPROTECT(uprotectCount);
+    return vec;
+}
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
index 1787b056454851783af719ead163b9b21f1aab60..6b55ae486c6e05d3c3f7a044025d11d8909fba7c 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/src/testrffi.h
@@ -20,7 +20,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-extern void dotCModifiedArguments(int* len, int* idata, double* rdata, int* ldata);
+extern void dotCModifiedArguments(int* len, int* idata, double* rdata, int* ldata, char** cdata);
 
 extern SEXP addInt(SEXP a, SEXP b);
 
@@ -86,5 +86,14 @@ extern SEXP test_CDR(SEXP x);
 
 extern SEXP test_LENGTH(SEXP x);
 
+extern SEXP test_inlined_length(SEXP x);
+
 extern SEXP test_coerceVector(SEXP x, SEXP mode);
 
+extern SEXP test_ATTRIB(SEXP);
+
+extern SEXP test_stringNA(void);
+
+extern SEXP test_captureDotsWithSingleElement(SEXP env);
+
+extern SEXP test_evalAndNativeArrays(SEXP vec, SEXP expr, SEXP env);
diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
index 92cf03a236a35b0bf896ef8fd97be859486a0817..3a8138ae628d02b5991bf4a9829e902b08d9a51a 100644
--- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
+++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/tests/simpleTests.R
@@ -21,4 +21,58 @@ rffi.isRString("hello")
 rffi.isRString(NULL)
 rffi.interactive()
 x <- 1; rffi.findvar("x", globalenv())
-x <- "12345"; rffi.char_length(x)
\ No newline at end of file
+x <- "12345"; rffi.char_length(x)
+
+strVec <- rffi.getStringNA();
+stopifnot(anyNA(strVec))
+
+x <- list(1)
+attr(x, 'myattr') <- 'hello';
+attrs <- rffi.ATTRIB(x)
+stopifnot(attrs[[1]] == 'hello')
+
+# loess invokes loess_raw native function passing in string value as argument and that is what we test here.
+loess(dist ~ speed, cars);
+
+# code snippet that simulates work with promises ala rlang package
+tmp <- c(1,2,4)
+some_unique_name <- TRUE
+foo <- function(...) { tmp <- 'this is not the right tmp'; bar(); }
+bar <- function() rffi.captureDotsWithSingleElement(parent.frame())
+promiseInfo <- foo(tmp)
+stopifnot('some_unique_name' %in% ls(promiseInfo[[2]]))
+eval(promiseInfo[[1]], promiseInfo[[2]])
+
+# fiddling the pointers to the native arrays: we get data pointer to the first SEXP argument (vec),
+# then put value 42/TRUE directly into it at index 0,
+# value of symbol 'myvar' through Rf_eval at index 1,
+# value of Rf_eval('max(vec)') at the last index (note that the upcall now should take max from the updated vector!)
+env <- new.env()
+env$myvar <- 44L;
+rffi.evalAndNativeArrays(c(1L, 2L, 3L, 4L, 5L), as.symbol('myvar'), env);
+
+env$myvar <- 3.14
+rffi.evalAndNativeArrays(c(1.1, 2.2, 3), as.symbol('myvar'), env);
+
+env$myvar <- T
+rffi.evalAndNativeArrays(c(F, F, F, F), as.symbol('myvar'), env);
+
+env$myvar <- 20L
+rffi.evalAndNativeArrays(as.raw(c(1, 3, 2)), as.symbol('myvar'), env);
+
+# legth tests
+env <- new.env(); env$a <- 42; env$b <- 44;
+rffi.inlined_length(env)
+rffi.inlined_length(c(1,2,3))
+rffi.inlined_length(list(a = 1, b = 42))
+rffi.inlined_length(as.pairlist(c(1,2,3,4,5)))
+expr <- expression(x + y, 3)
+rffi.inlined_length(expr)
+rffi.inlined_length(expr[[1]])
+
+# fails in FastR because DotCall class cannot recognize that the RArgsValuesAndNames
+# are not meant to be extracted into individual arguments, but instead send as is
+# to the native function as SEXP
+#
+# foo <-function(...) rffi.inlined_length(get('...'))
+# foo(a = 1, b = 2, c = 3, d = 42)
diff --git a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R
index 998abefbd13e9fd764476c6c084d42f0004d6695..cd580631c528abfc41606374b13578cf6cf7ddff 100644
--- a/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R
+++ b/com.oracle.truffle.r.test.native/packages/tests4/tests4/tests/allocation5.R
@@ -1,8 +1,11 @@
 # test from Hadley Wickham's book
-stopifnot(require(methods))
-stopifnot(require(tests4))
 
-setClass("Person", representation(name = "character", age = "numeric"))
-setClass("Employee", representation(boss = "Person"), contains = "Person")
-hadley <- new("Person", name = "Hadley")
-slot(hadley, "age")
+# temporarily disabled
+
+#stopifnot(require(methods))
+#stopifnot(require(tests4))
+
+#setClass("Person", representation(name = "character", age = "numeric"))
+#setClass("Employee", representation(boss = "Person"), contains = "Person")
+#hadley <- new("Person", name = "Hadley")
+#slot(hadley, "age")
diff --git a/com.oracle.truffle.r.test.native/urand/Makefile b/com.oracle.truffle.r.test.native/urand/Makefile
index 1dc8f430e262e9e052f97a98fbc7c35263b9e711..0b933a804a7ff010bfb3c8db1b2ceefdcfd19756 100644
--- a/com.oracle.truffle.r.test.native/urand/Makefile
+++ b/com.oracle.truffle.r.test.native/urand/Makefile
@@ -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
@@ -25,6 +25,7 @@ ifeq ($(TOPDIR),)
     TOPDIR = $(abspath ..)
 endif
 
+FASTR_R_HOME := $(abspath $(TOPDIR)/..)
 NATIVE_PROJECT = $(subst test.native,native,$(TOPDIR))
 
 ifneq ($(MAKECMDGOALS),clean)
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileTreeWalker.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileTreeWalker.java
new file mode 100644
index 0000000000000000000000000000000000000000..f3a20fc44a270b3f601d8fddb761032ae252d033
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/FileTreeWalker.java
@@ -0,0 +1,180 @@
+/*
+ * 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.packages.analyzer;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.attribute.FileTime;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.LinkedList;
+import java.util.logging.Logger;
+
+import com.oracle.truffle.r.test.packages.analyzer.detectors.DiffDetector;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.InstallationProblemDetector;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.RErrorDetector;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.RInternalErrorDetector;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.SegfaultDetector;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.SymbolLookupErrorDetector;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.UnsupportedSpecializationDetector;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackage;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+import com.oracle.truffle.r.test.packages.analyzer.parser.LogFileParseException;
+import com.oracle.truffle.r.test.packages.analyzer.parser.LogFileParser;
+import com.oracle.truffle.r.test.packages.analyzer.parser.LogFileParser.LogFile;
+
+public class FileTreeWalker {
+    private static final Logger LOGGER = Logger.getLogger(FileTreeWalker.class.getName());
+
+    private Collection<LogFileParseException> parseErrors;
+
+    /** List of test run directories that were candidates for analysis. */
+    private Collection<Path> consideredTestRuns;
+
+    public Collection<RPackage> ftw(Path root, Date sinceDate, String glob) throws IOException {
+
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(root, glob)) {
+            reset();
+            Collection<RPackage> pkgs = new LinkedList<>();
+            for (Path p : stream) {
+                if (Files.isDirectory(p)) {
+                    Collection<RPackage> pkgVersions = visitPackageRoot(p, sinceDate);
+                    pkgs.addAll(pkgVersions);
+                }
+            }
+            LOGGER.info("Total number of analysis candidates: " + consideredTestRuns.size());
+            return pkgs;
+        }
+    }
+
+    private void reset() {
+        parseErrors = new ArrayList<>();
+        consideredTestRuns = new ArrayList<>();
+    }
+
+    protected Collection<RPackage> visitPackageRoot(Path pkgRoot, Date sinceDate) throws IOException {
+        String pkgName = pkgRoot.getFileName().toString();
+
+        Collection<RPackage> pkgs = new LinkedList<>();
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgRoot)) {
+            for (Path p : stream) {
+                if (Files.isDirectory(p)) {
+                    pkgs.add(visitPackageVersion(p, pkgName, sinceDate));
+                }
+            }
+        }
+        return pkgs;
+    }
+
+    protected RPackage visitPackageVersion(Path pkgVersionDir, String pkgName, Date sinceDate) {
+        String pkgVersion = pkgVersionDir.getFileName().toString();
+        RPackage pkg = new RPackage(pkgName, pkgVersion);
+        LOGGER.info("Found package " + pkg);
+
+        Collection<RPackageTestRun> runs = new LinkedList<>();
+        try (DirectoryStream<Path> stream = Files.newDirectoryStream(pkgVersionDir)) {
+            for (Path p : stream) {
+                if (Files.isDirectory(p)) {
+                    RPackageTestRun testRun = visitTestRun(p, pkg, sinceDate);
+                    if (testRun != null) {
+                        runs.add(testRun);
+                    }
+                }
+            }
+            pkg.setTestRuns(runs);
+        } catch (IOException e) {
+            LOGGER.severe("Error while reading package root of \"" + pkgName + "\"");
+        }
+
+        return pkg;
+    }
+
+    protected RPackageTestRun visitTestRun(Path testRunDir, RPackage pkg, Date sinceDate) {
+        int testRun = Integer.parseInt(testRunDir.getFileName().toString());
+        LOGGER.info("Visiting test run " + testRun + " of package " + pkg);
+        try {
+            RPackageTestRun pkgTestRun = new RPackageTestRun(pkg, testRun);
+            Path logFile = testRunDir.resolve(pkg.getName() + ".log");
+            FileTime lastModifiedTime = Files.getLastModifiedTime(logFile);
+            if (isNewerThan(lastModifiedTime, sinceDate)) {
+                Collection<Problem> problems = parseLogFile(logFile, pkgTestRun);
+                consideredTestRuns.add(testRunDir);
+                pkgTestRun.setProblems(problems);
+                return pkgTestRun;
+            } else {
+                LOGGER.info(String.format("Skipping package test run %s because it is too old (%s must be newer than %s)", pkgTestRun, lastModifiedTime, sinceDate));
+            }
+        } catch (IOException e) {
+            LOGGER.severe(String.format("Error while parsing test run %d of package \"%s-%s\": %s", testRun,
+                            pkg.getName(), pkg.getVersion(), e.getMessage()));
+        } catch (LogFileParseException e) {
+            LOGGER.severe(String.format("Error while parsing test run %d of package \"%s-%s\": %s", testRun,
+                            pkg.getName(), pkg.getVersion(), e.getMessage()));
+            parseErrors.add(e);
+        }
+        return null;
+    }
+
+    private static boolean isNewerThan(FileTime lastModifiedTime, Date sinceDate) {
+        Date lastModDate = new Date(lastModifiedTime.toMillis());
+        return sinceDate.compareTo(lastModDate) <= 0;
+    }
+
+    private static Collection<Problem> parseLogFile(Path logFile, RPackageTestRun pkgTestRun) throws IOException {
+        LOGGER.info("Parsing log file " + logFile);
+
+        LogFileParser lfParser = new LogFileParser(logFile, pkgTestRun);
+        lfParser.addDetector(InstallationProblemDetector.INSTANCE);
+        lfParser.addDetector(SegfaultDetector.INSTANCE);
+        lfParser.addDetector(RErrorDetector.INSTANCE);
+        lfParser.addDetector(UnsupportedSpecializationDetector.INSTANCE);
+        lfParser.addDetector(RInternalErrorDetector.INSTANCE);
+        lfParser.addTestResultDetector(DiffDetector.INSTANCE);
+        lfParser.addDetector(SymbolLookupErrorDetector.INSTANCE);
+
+        LogFile parseLogFile = lfParser.parseLogFile();
+        Collection<Problem> problems = parseLogFile.collectProblems();
+        pkgTestRun.setSuccess(parseLogFile.isSuccess());
+        pkgTestRun.setLogFile(parseLogFile.getPath());
+
+        // log problems
+        LOGGER.fine("Overall test result: " + (pkgTestRun.isSuccess() ? "OK" : "FAILED"));
+        for (Problem problem : problems) {
+            LOGGER.fine(problem.toString());
+        }
+
+        return problems;
+    }
+
+    public Collection<LogFileParseException> getParseErrors() {
+        return parseErrors;
+    }
+
+    public Collection<Path> getConsideredTestRuns() {
+        return consideredTestRuns;
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/Location.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/Location.java
new file mode 100644
index 0000000000000000000000000000000000000000..ba4b19ed1d8c8bf08645123cfc3b48077ef4201e
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/Location.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.test.packages.analyzer;
+
+import java.nio.file.Path;
+import java.util.Objects;
+
+public class Location {
+    public final Path file;
+    public final int lineNr;
+
+    public Location(Path file, int lineNr) {
+        this.file = Objects.requireNonNull(file);
+        assert lineNr >= 0;
+        this.lineNr = lineNr;
+    }
+
+    @Override
+    public String toString() {
+        return file + "(" + (lineNr + 1) + ")";
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((file == null) ? 0 : file.hashCode());
+        result = prime * result + lineNr;
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        Location other = (Location) obj;
+        if (lineNr != other.lineNr) {
+            return false;
+        }
+        if (file == null) {
+            if (other.file != null) {
+                return false;
+            }
+        } else if (!file.equals(other.file)) {
+            return false;
+        }
+        return true;
+    }
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/PTAMain.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/PTAMain.java
new file mode 100644
index 0000000000000000000000000000000000000000..f60d22af3eff08353b486d7392c4732ffd09b77a
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/PTAMain.java
@@ -0,0 +1,284 @@
+/*
+ * 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.packages.analyzer;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.FileHandler;
+import java.util.logging.Level;
+import java.util.logging.LogManager;
+import java.util.logging.Logger;
+import java.util.logging.SimpleFormatter;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.truffle.r.test.packages.analyzer.dump.HTMLDumper;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackage;
+
+/**
+ * Main class of the package analysis tool.<br>
+ * <p>
+ * Expected directory structure: <code>
+ * root<br>
+ * -+-- packageName<br>
+ * ----+- version<br>
+ * ------+- testRunNumber<br>
+ * --------+- packageName.log<br>
+ * --------+- testfiles<br>
+ * ----------+- diff<br>
+ * ----------+- fastr<br>
+ * ----------+- gnu<br>
+ * </code>
+ * </p>
+ */
+public class PTAMain {
+
+    // must be before the logger is created to take effect
+    static {
+        System.setProperty("java.util.logging.SimpleFormatter.format", "%4$s: %5$s [%1$tc]%n");
+    }
+
+    private static final Logger LOGGER = Logger.getLogger(PTAMain.class.getName());
+    private static final String LOG_FILE_NAME = "pta.log";
+
+    public static void main(String[] args) throws IOException {
+        OptionsParser parser = new OptionsParser();
+        parser.registerOption("help");
+        parser.registerOption("outDir", "html");
+        parser.registerOption("glob", "*");
+        parser.registerOption("since", "last2weeks");
+        parser.registerOption("console");
+        parser.registerOption("verbose");
+
+        String[] remainingArgs = parser.parseOptions(args);
+        if (parser.has("help")) {
+            printHelpAndExit();
+        }
+
+        if (remainingArgs.length != 1) {
+            System.err.println("Unknown arguments: " + Arrays.toString(remainingArgs));
+            printHelpAndExit();
+        }
+
+        configureLogger(parser);
+
+        Date sinceDate = parseSinceDate(parser);
+        LOGGER.info("Considering only test runs since: " + sinceDate);
+
+        Path outDir = Paths.get(parser.get("outDir"));
+        ftw(Paths.get(remainingArgs[0]), outDir, sinceDate, parser.get("glob"));
+    }
+
+    private static void ftw(Path root, Path outDir, Date sinceDate, String glob) {
+        HTMLDumper htmlDumper = new HTMLDumper(outDir);
+
+        // fail early
+        try {
+            if (!htmlDumper.createAndCheckOutDir()) {
+                LOGGER.severe("Cannot write to output directory: " + outDir);
+                System.exit(1);
+            }
+        } catch (IOException e) {
+            LOGGER.severe(String.format("Cannot create output directory: %s ", e.getMessage()));
+            System.exit(1);
+        }
+
+        try {
+            FileTreeWalker walker = new FileTreeWalker();
+            Collection<RPackage> pkgs = walker.ftw(root, sinceDate, glob);
+            htmlDumper.dump(pkgs, walker.getParseErrors());
+        } catch (IOException e) {
+            LOGGER.severe("Error while traversing package test directory: " + e.getMessage());
+        }
+    }
+
+    private static final Pattern REL_SINCE_PATTERN = Pattern.compile("last(\\d+)(days?|weeks?|months?)");
+
+    private static Date parseSinceDate(OptionsParser parser) {
+        String sinceDateStr = parser.get("since");
+
+        Matcher matcher = REL_SINCE_PATTERN.matcher(sinceDateStr);
+
+        if (matcher.matches()) {
+            int amount = Integer.parseInt(matcher.group(1));
+            String unit = matcher.group(2);
+
+            GregorianCalendar cal = new GregorianCalendar();
+            switch (unit) {
+                case "day":
+                case "days":
+                    cal.add(Calendar.DATE, -amount);
+                    break;
+                case "week":
+                case "weeks":
+                    cal.add(Calendar.WEEK_OF_YEAR, -amount);
+                    break;
+                case "month":
+                case "months":
+                    cal.add(Calendar.MONTH, -amount);
+                    break;
+                default:
+                    throw new RuntimeException("Invalid unit: " + unit);
+            }
+
+            return cal.getTime();
+        }
+
+        try {
+            return new SimpleDateFormat("MM-dd-yyyy").parse(sinceDateStr);
+        } catch (ParseException e) {
+            LOGGER.severe("Invalid date: " + e.getMessage());
+            System.exit(1);
+        }
+        // should never be reached
+        return null;
+    }
+
+    private static void configureLogger(OptionsParser parser) throws IOException {
+        LogManager.getLogManager().reset();
+        Logger rootLogger = Logger.getLogger("");
+        ConsoleHandler consoleHandler = new ConsoleHandler();
+
+        Level defaultLogLevel = Level.INFO;
+        if (parser.has("verbose")) {
+            defaultLogLevel = Level.ALL;
+        }
+        rootLogger.setLevel(defaultLogLevel);
+
+        System.setProperty("java.util.logging.SimpleFormatter.format", "%4$s: %5$s [%1$tc]%n");
+        if (parser.has("console")) {
+            consoleHandler.setLevel(defaultLogLevel);
+        } else {
+            // set log level of console handlers to SEVERE
+            consoleHandler.setLevel(Level.SEVERE);
+            FileHandler fileHandler = new FileHandler(LOG_FILE_NAME);
+            fileHandler.setLevel(defaultLogLevel);
+            fileHandler.setFormatter(new SimpleFormatter());
+            rootLogger.addHandler(fileHandler);
+        }
+        rootLogger.addHandler(consoleHandler);
+    }
+
+    private static final String LF = System.lineSeparator();
+
+    private static void printHelpAndExit() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("USAGE: ").append(PTAMain.class.getSimpleName()).append(" [OPTIONS] ROOT").append(LF);
+        sb.append(LF);
+        sb.append("OPTIONS:").append(LF);
+        sb.append("    --help\t\tShow this help page").append(LF);
+        sb.append("    --since SPEC\tOnly consider package tests satisfying the specified age (default: \"last2weeks\").").append(LF);
+        sb.append("    \t\t\tSPEC is either an absolute date in format MM-dd-yyyy or relative in format:").append(LF);
+        sb.append("    \t\t\tlast<n>(days|weeks|months).").append(LF);
+        sb.append("    --glob GLOB\t\tGlob-style directory filter for packages to consider (default: \"*\").").append(LF);
+        sb.append("    --outDir PATH\tPath to directory for HTML output (default: \"html\").").append(LF);
+        sb.append("    --console\t\tPrint output to console (by default, only errors are printed).").append(LF);
+        System.out.println(sb.toString());
+        System.exit(1);
+    }
+
+    private static class OptionsParser {
+
+        private Map<String, String> options = new HashMap<>();
+        private Map<String, Option> registered = new HashMap<>();
+
+        public String[] parseOptions(String[] args) {
+            int i = 0;
+            while (i < args.length) {
+                String key = args[i];
+                if (key.startsWith("--") && registered.containsKey(getBareName(key))) {
+                    Option option = registered.get(getBareName(key));
+                    String value = null;
+                    if (option.hasValue) {
+                        value = getOptionArg(args, i);
+                        ++i;
+                    }
+                    options.put(getBareName(key), value);
+                } else {
+                    break;
+                }
+                ++i;
+            }
+            return Arrays.copyOfRange(args, i, args.length);
+        }
+
+        private static String getBareName(String key) {
+            if (key.startsWith("--")) {
+                return key.substring(2);
+
+            }
+            throw new RuntimeException("Invalid option name: " + key);
+        }
+
+        private static String getOptionArg(String[] args, int keyIndex) {
+            if (keyIndex + 1 < args.length) {
+                return args[keyIndex + 1];
+            }
+            throw new RuntimeException("Missing value for option: " + args[keyIndex]);
+        }
+
+        public boolean has(String key) {
+            return options.containsKey(key);
+        }
+
+        public String get(String key) {
+            if (has(key)) {
+                return options.get(key);
+            }
+            if (registered.containsKey(key)) {
+                return registered.get(key).defaultValue;
+            }
+            throw new RuntimeException("Unknown option: " + key);
+        }
+
+        public void registerOption(String optionName, String defaultValue) {
+            registered.put(optionName, new Option(true, defaultValue));
+        }
+
+        public void registerOption(String optionName) {
+            registered.put(optionName, new Option(false, null));
+        }
+
+        private static class Option {
+            final boolean hasValue;
+            final String defaultValue;
+
+            protected Option(boolean hasValue, String defaultValue) {
+                this.hasValue = hasValue;
+                this.defaultValue = defaultValue;
+            }
+
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/Problem.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/Problem.java
new file mode 100644
index 0000000000000000000000000000000000000000..3bf0e1a8a929b80befb777cb3f2549263a47816b
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/Problem.java
@@ -0,0 +1,142 @@
+/*
+ * 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.packages.analyzer;
+
+import java.util.Comparator;
+import java.util.Objects;
+
+import com.oracle.truffle.r.test.packages.analyzer.detectors.Detector;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackage;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+/**
+ * Abstract class denoting any kind of problem occurred during a package test.
+ */
+public abstract class Problem {
+
+    private final RPackageTestRun pkgTestRun;
+    private final Location location;
+    private final Detector<?> detector;
+
+    protected Problem(RPackageTestRun pkg, Detector<?> detector, Location location) {
+        this.pkgTestRun = Objects.requireNonNull(pkg);
+        this.location = Objects.requireNonNull(location);
+        this.detector = Objects.requireNonNull(detector);
+    }
+
+    public RPackage getPackage() {
+        return pkgTestRun.getPackage();
+    }
+
+    public RPackageTestRun getPackageTestRun() {
+        return pkgTestRun;
+    }
+
+    public Location getLocation() {
+        return location;
+    }
+
+    public Detector<?> getDetector() {
+        return detector;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((location == null) ? 0 : location.hashCode());
+        result = prime * result + ((getSummary() == null) ? 0 : getSummary().hashCode());
+        result = prime * result + ((getDetails() == null) ? 0 : getDetails().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        Problem other = (Problem) obj;
+        if (!Objects.equals(location, other.location)) {
+            return false;
+        }
+        if (!Objects.equals(getSummary(), other.getSummary())) {
+            return false;
+        }
+        if (!Objects.equals(getDetails(), other.getDetails())) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Returns a one-line summary of the problem (e.g.
+     * <q>RuntimeException occurred</q>).
+     */
+    public abstract String getSummary();
+
+    /**
+     * Returns detailed content of the problem excluding the summary (e.g. a stack trace).
+     */
+    public abstract String getDetails();
+
+    public abstract int getSimilarityTo(Problem other);
+
+    public abstract boolean isSimilarTo(Problem other);
+
+    public Comparator<Problem> getSimilarityComparator() {
+        return (a, b) -> a.isSimilarTo(b) ? 0 : 1;
+    }
+
+    private static int min(int a, int b, int c) {
+        return Math.min(Math.min(a, b), c);
+    }
+
+    public static int computeLevenshteinDistance(CharSequence lhs, CharSequence rhs) {
+        int[][] distance = new int[lhs.length() + 1][rhs.length() + 1];
+
+        for (int i = 0; i <= lhs.length(); i++) {
+            distance[i][0] = i;
+        }
+        for (int j = 1; j <= rhs.length(); j++) {
+            distance[0][j] = j;
+        }
+
+        for (int i = 1; i <= lhs.length(); i++) {
+            for (int j = 1; j <= rhs.length(); j++) {
+                distance[i][j] = min(
+                                distance[i - 1][j] + 1,
+                                distance[i][j - 1] + 1,
+                                distance[i - 1][j - 1] + ((lhs.charAt(i - 1) == rhs.charAt(j - 1)) ? 0 : 1));
+            }
+        }
+
+        return distance[lhs.length()][rhs.length()];
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/Detector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/Detector.java
new file mode 100644
index 0000000000000000000000000000000000000000..b71512b5e51415511a5add23996e8ed1c71343a0
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/Detector.java
@@ -0,0 +1,65 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.LinkedList;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public abstract class Detector<T> {
+
+    /** Semantics: If a child reports an error for a particular location, the parent doesn't. */
+    protected Detector<?> parent;
+
+    protected final Collection<Detector<?>> children = new LinkedList<>();
+
+    public Detector(Detector<?> parent) {
+        this.parent = parent;
+        if (parent != null) {
+            parent.children.add(this);
+        }
+    }
+
+    public Detector<?> getParent() {
+        return parent;
+    }
+
+    public Collection<Detector<?>> getChildren() {
+        return children;
+    }
+
+    public abstract String getName();
+
+    /**
+     * @param pkgTestRun The package test run any problems should be associated with.
+     * @param startLineLocation The location of the first line, i.e., of body[0], or
+     *            <code>null</code> if body is empty.
+     * @param body The content to analyze (e.g. a list of lines in a file).
+     * @return A list of detected problems (must not be {@code null}).
+     */
+    public abstract Collection<Problem> detect(RPackageTestRun pkgTestRun, Location startLineLocation, T body);
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/DiffDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/DiffDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..8cd40a6d7176a75ebbad84e15cd8e042eaf1f5a9
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/DiffDetector.java
@@ -0,0 +1,114 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Objects;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+import com.oracle.truffle.r.test.packages.analyzer.parser.DiffParser.ChangeCommand;
+import com.oracle.truffle.r.test.packages.analyzer.parser.DiffParser.DiffChunk;
+
+public class DiffDetector extends Detector<List<DiffChunk>> {
+
+    public static final DiffDetector INSTANCE = new DiffDetector();
+
+    protected DiffDetector() {
+        super(null);
+    }
+
+    protected DiffDetector(Detector<?> parent) {
+        super(parent);
+    }
+
+    @Override
+    public String getName() {
+        return "Diff detector";
+    }
+
+    @Override
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLineLocation, List<DiffChunk> body) {
+        Collection<Problem> problems = new LinkedList<>();
+        for (DiffChunk diffChunk : body) {
+            String summary;
+            if (isMinorDifference(diffChunk)) {
+                summary = "Minor difference in test output";
+            } else {
+                summary = "Major difference in test output";
+            }
+            problems.add(new DiffProblem(pkg, this, diffChunk.getLocation(), summary, diffChunk));
+        }
+        return problems;
+    }
+
+    /**
+     * TODO In general, one-line changes can be classified as minor differences.
+     */
+    private static boolean isMinorDifference(DiffChunk diffChunk) {
+        ChangeCommand cmd = diffChunk.getChangeCommand();
+        return cmd.cmd == 'c' && cmd.lFrom == cmd.rFrom && cmd.lTo == -1 && cmd.rTo == -1;
+    }
+
+    public static class DiffProblem extends Problem {
+
+        private final String summary;
+        private final DiffChunk diffChunk;
+
+        protected DiffProblem(RPackageTestRun pkg, DiffDetector detector, Location location, String summary, DiffChunk diffChunk) {
+            super(pkg, detector, location);
+            this.summary = Objects.requireNonNull(summary);
+            this.diffChunk = Objects.requireNonNull(diffChunk);
+        }
+
+        @Override
+        public String getSummary() {
+            return summary;
+        }
+
+        @Override
+        public String getDetails() {
+            return diffChunk.getChangeCommand().toString();
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s: %s", diffChunk.getLocation(), summary);
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return other.getClass() == DiffProblem.class && summary.equals(other.getSummary());
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            return isSimilarTo(other) ? 0 : 1;
+        }
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/DummyDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/DummyDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9c7e2a50775cd3b65c2f9f2db737a552e29f617
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/DummyDetector.java
@@ -0,0 +1,50 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public final class DummyDetector extends Detector<Void> {
+
+    public static final DummyDetector INSTANCE = new DummyDetector();
+
+    private DummyDetector() {
+        super(null);
+    }
+
+    @Override
+    public String getName() {
+        return "Dummy detector";
+    }
+
+    @Override
+    public Collection<Problem> detect(RPackageTestRun pkgTestRun, Location startLineLocation, Void body) {
+        return Collections.emptyList();
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/InstallationProblemDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/InstallationProblemDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..b63d31b1d5a274a6fcc4bee78685afc50b058885
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/InstallationProblemDetector.java
@@ -0,0 +1,100 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public class InstallationProblemDetector extends LineDetector {
+
+    public static final InstallationProblemDetector INSTANCE = new InstallationProblemDetector();
+
+    protected InstallationProblemDetector() {
+    }
+
+    private final Pattern pattern = Pattern.compile("\\h*installation of package ‘.*’ had non-zero exit status\\h*");
+
+    @Override
+    public String getName() {
+        return "Package installation problems detector";
+    }
+
+    @Override
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+        int lineNr = startLocation.lineNr;
+        for (String line : body) {
+            Matcher matcher = pattern.matcher(line);
+            if (matcher.matches()) {
+                return Collections.singletonList(new PackageInstallationProblem(pkg, this, new Location(startLocation.file, lineNr), line));
+            }
+            ++lineNr;
+        }
+        return Collections.emptyList();
+    }
+
+    public static class PackageInstallationProblem extends Problem {
+
+        private final String message;
+
+        public PackageInstallationProblem(RPackageTestRun pkg, InstallationProblemDetector detector, Location location, String message) {
+            super(pkg, detector, location);
+            this.message = message;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s: Installation failed in '%s'; message: %s", getLocation(), getPackage().getName(),
+                            message);
+        }
+
+        @Override
+        public String getSummary() {
+            return String.format("Installation failed in package '%s'", getPackage().getName());
+        }
+
+        @Override
+        public String getDetails() {
+            return message;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            if (other.getClass() == PackageInstallationProblem.class) {
+                return Problem.computeLevenshteinDistance(getDetails().trim(), other.getDetails().trim());
+            }
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return getSimilarityTo(other) < 3;
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/LineDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/LineDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..a035f5eb1be6b1c0e38f41c051f60c5423894fc0
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/LineDetector.java
@@ -0,0 +1,36 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.List;
+
+public abstract class LineDetector extends Detector<List<String>> {
+
+    protected LineDetector() {
+        super(null);
+    }
+
+    protected LineDetector(Detector<?> parent) {
+        super(parent);
+    }
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RErrorDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RErrorDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..6f304037442499e61d0c18c2ed1673139cc08996
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RErrorDetector.java
@@ -0,0 +1,121 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public class RErrorDetector extends LineDetector {
+
+    public static final RErrorDetector INSTANCE = new RErrorDetector();
+
+    private static final Pattern PATTERN = Pattern.compile("(.*\\s)?Error( in (?<CALLSTR>[^:]*(\\(.*\\))?) )?: (?<MSG>.*)");
+
+    protected RErrorDetector() {
+    }
+
+    @Override
+    public String getName() {
+        return "R error detector";
+    }
+
+    @Override
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+
+        Collection<Problem> problems = new LinkedList<>();
+        assert body.isEmpty() || startLocation != null;
+        int lineOffset = startLocation != null ? startLocation.lineNr : 0;
+
+        int i = -1;
+        Iterator<String> it = body.iterator();
+        while (it.hasNext()) {
+            String line = it.next();
+            ++i;
+            Matcher matcher = PATTERN.matcher(line);
+            if (matcher.matches()) {
+                String callString = matcher.group("CALLSTR");
+                String message = matcher.group("MSG");
+                if (message.trim().isEmpty() && it.hasNext()) {
+                    // message could be in the next line
+                    message = it.next();
+                    ++i;
+                }
+                problems.add(new RErrorProblem(pkg, this, new Location(startLocation.file, i + lineOffset), callString, message));
+            }
+        }
+
+        return problems;
+    }
+
+    public static class RErrorProblem extends Problem {
+
+        private final String callString;
+        private final String message;
+
+        protected RErrorProblem(RPackageTestRun pkg, RErrorDetector detector, Location location, String callString, String message) {
+            super(pkg, detector, location);
+            this.callString = callString;
+            this.message = message;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%s: RError in '%s' (msg = '%s'), args)", getLocation(), getPackage().getName(), message);
+        }
+
+        @Override
+        public String getSummary() {
+            if (callString != null) {
+                return "Error in " + callString + "";
+            }
+            return "Error";
+        }
+
+        @Override
+        public String getDetails() {
+            return message;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            if (other.getClass() == RErrorProblem.class) {
+                return Problem.computeLevenshteinDistance(getDetails().trim(), other.getDetails().trim());
+            }
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return Problem.computeLevenshteinDistance(getDetails().trim(), other.getDetails().trim()) < 10;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RInternalErrorDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RInternalErrorDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..56b5e78cedd8a748cc08ebf527e7f1632dedea1d
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/RInternalErrorDetector.java
@@ -0,0 +1,107 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public class RInternalErrorDetector extends LineDetector {
+
+    public static final RInternalErrorDetector INSTANCE = new RInternalErrorDetector();
+
+    private static final String P = "com.oracle.truffle.r.runtime.RInternalError: ";
+
+    protected RInternalErrorDetector() {
+    }
+
+    @Override
+    public String getName() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+        Collection<Problem> problems = new LinkedList<>();
+        assert body.isEmpty() || startLocation != null;
+        int lineNr = startLocation != null ? startLocation.lineNr : 0;
+        for (String line : body) {
+            int indexOf = line.indexOf(P);
+            if (indexOf != -1) {
+                String message = line.substring(indexOf + P.length());
+                problems.add(new RInternalErrorProblem(pkg, this, new Location(startLocation.file, lineNr), message));
+            }
+            ++lineNr;
+        }
+        return problems;
+    }
+
+    public static class RInternalErrorProblem extends Problem {
+
+        private final String message;
+
+        protected RInternalErrorProblem(RPackageTestRun pkg, RInternalErrorDetector detector, Location location, String message) {
+            super(pkg, detector, location);
+            this.message = message;
+        }
+
+        public String getMessage() {
+            return message;
+        }
+
+        @Override
+        public String toString() {
+            return getLocation() + ": RInternalError: " + message;
+        }
+
+        @Override
+        public String getSummary() {
+            return "RInternalError";
+        }
+
+        @Override
+        public String getDetails() {
+            return message;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            if (other.getClass() == RInternalErrorProblem.class) {
+                return Problem.computeLevenshteinDistance(getDetails().trim(), other.getDetails().trim());
+            }
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return getSimilarityTo(other) < 10;
+        }
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SegfaultDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SegfaultDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..f23d7933a922ec8d504301440eaf8c36fcc8a9d7
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SegfaultDetector.java
@@ -0,0 +1,114 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public class SegfaultDetector extends LineDetector {
+    public static final SegfaultDetector INSTANCE = new SegfaultDetector();
+
+    private static final String SIGSEGV_START = "# A fatal error has been detected by the Java Runtime Environment:";
+
+    protected SegfaultDetector() {
+    }
+
+    @Override
+    public String getName() {
+        return "Segfault detector";
+    }
+
+    @Override
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+        StringBuilder segfaultMessage = new StringBuilder();
+        boolean collect = false;
+        assert body.isEmpty() || startLocation != null;
+        int lineNr = startLocation != null ? startLocation.lineNr : 0;
+        boolean takeNextLine = false;
+        for (String line : body) {
+            if (line.contains(SIGSEGV_START)) {
+                collect = true;
+            }
+            if (collect) {
+                if (takeNextLine) {
+                    segfaultMessage.append(line);
+                    takeNextLine = false;
+                }
+                if (line.contains("Problematic frame")) {
+                    takeNextLine = true;
+                } else if (!line.contains("#")) {
+                    break;
+                }
+            }
+            ++lineNr;
+        }
+        if (collect) {
+            return Collections.singleton(new SegfaultProblem(pkg, this, new Location(startLocation.file, lineNr), segfaultMessage.toString()));
+        }
+        return Collections.emptyList();
+    }
+
+    public static class SegfaultProblem extends Problem {
+
+        private final String message;
+
+        protected SegfaultProblem(RPackageTestRun pkg, SegfaultDetector detector, Location location, String message) {
+            super(pkg, detector, location);
+            this.message = message;
+        }
+
+        @Override
+        public String toString() {
+            return getLocation() + ": SIGSEGV in " + getPackage();
+        }
+
+        @Override
+        public String getSummary() {
+            return ": SIGSEGV in " + getPackage();
+        }
+
+        @Override
+        public String getDetails() {
+            return message;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            if (other.getClass() == SegfaultProblem.class) {
+                return Problem.computeLevenshteinDistance(getDetails().trim(), other.getDetails().trim());
+            }
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return getSimilarityTo(other) < 100;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SymbolLookupErrorDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SymbolLookupErrorDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..bd218894e024d78ada9a40a34694e06cf24f472c
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/SymbolLookupErrorDetector.java
@@ -0,0 +1,103 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public final class SymbolLookupErrorDetector extends LineDetector {
+
+    public static final SymbolLookupErrorDetector INSTANCE = new SymbolLookupErrorDetector();
+
+    private static final Pattern PATTERN = Pattern.compile("(.*): symbol lookup error: (.*): (?<MSG>.*)");
+
+    private SymbolLookupErrorDetector() {
+    }
+
+    @Override
+    public String getName() {
+        return "Symbol lookup error detector";
+    }
+
+    @Override
+    public Collection<Problem> detect(RPackageTestRun pkgTestRun, Location startLocation, List<String> body) {
+        Collection<Problem> problems = new LinkedList<>();
+        int lineNr = startLocation != null ? startLocation.lineNr : 0;
+        for (String line : body) {
+            Matcher matcher = PATTERN.matcher(line);
+            if (matcher.matches()) {
+                String message = matcher.group("MSG");
+                problems.add(new SymbolLookupErrorProblem(pkgTestRun, this, new Location(startLocation.file, lineNr), message));
+
+            }
+            ++lineNr;
+        }
+        return problems;
+    }
+
+    public static class SymbolLookupErrorProblem extends Problem {
+
+        private final String message;
+
+        protected SymbolLookupErrorProblem(RPackageTestRun pkg, SymbolLookupErrorDetector detector, Location location, String message) {
+            super(pkg, detector, location);
+            this.message = message;
+        }
+
+        @Override
+        public String toString() {
+            return getLocation() + ": symbol lookup error " + message;
+        }
+
+        @Override
+        public String getSummary() {
+            return "symbol lookup error";
+        }
+
+        @Override
+        public String getDetails() {
+            return message;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            if (other.getClass() == SymbolLookupErrorProblem.class) {
+                return Problem.computeLevenshteinDistance(getDetails().trim(), other.getDetails().trim());
+            }
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return getSimilarityTo(other) < 30;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/UnsupportedSpecializationDetector.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/UnsupportedSpecializationDetector.java
new file mode 100644
index 0000000000000000000000000000000000000000..99f270940e23845ce25a4c3b260b9f278ca748d4
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/detectors/UnsupportedSpecializationDetector.java
@@ -0,0 +1,108 @@
+/*
+ * 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.packages.analyzer.detectors;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public class UnsupportedSpecializationDetector extends LineDetector {
+
+    public static final UnsupportedSpecializationDetector INSTANCE = new UnsupportedSpecializationDetector();
+
+    private static final Pattern PATTERN = Pattern.compile(
+                    "com\\.oracle\\.truffle\\.r\\.runtime\\.RInternalError: com\\.oracle\\.truffle\\.api\\.dsl\\.UnsupportedSpecializationException: (?<MSG>.*)");
+
+    protected UnsupportedSpecializationDetector() {
+        super(RInternalErrorDetector.INSTANCE);
+    }
+
+    @Override
+    public String getName() {
+        return "UnsupportedSpecializationException detector";
+    }
+
+    @Override
+    public Collection<Problem> detect(RPackageTestRun pkg, Location startLocation, List<String> body) {
+        Collection<Problem> problems = new LinkedList<>();
+        String message = null;
+        assert body.isEmpty() || startLocation != null;
+        int lineNr = startLocation != null ? startLocation.lineNr : 0;
+        int problemStartLine = lineNr;
+        for (String line : body) {
+            Matcher matcher = PATTERN.matcher(line);
+            if (matcher.find()) {
+                message = matcher.group("MSG");
+                problemStartLine = lineNr;
+                problems.add(new UnsupportedSpecializationProblem(pkg, this, new Location(startLocation.file, problemStartLine), message));
+            }
+            ++lineNr;
+        }
+        return problems;
+    }
+
+    private static class UnsupportedSpecializationProblem extends Problem {
+
+        protected UnsupportedSpecializationProblem(RPackageTestRun pkg, UnsupportedSpecializationDetector detector, Location location, String message) {
+            super(pkg, detector, location);
+            this.message = message;
+        }
+
+        public final String message;
+
+        @Override
+        public String toString() {
+            return getLocation() + ": com.oracle.truffle.api.dsl.UnsupportedSpecializationException: " + message;
+        }
+
+        @Override
+        public String getSummary() {
+            return "UnsupportedSpecializationException";
+        }
+
+        @Override
+        public String getDetails() {
+            return message;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            if (other.getClass() == UnsupportedSpecializationProblem.class) {
+                return Problem.computeLevenshteinDistance(getDetails().trim(), other.getDetails().trim());
+            }
+            return Integer.MAX_VALUE;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return getSimilarityTo(other) < 5;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/AbstractDumper.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/AbstractDumper.java
new file mode 100644
index 0000000000000000000000000000000000000000..ec3bb6b686896ce0c2ef93e48cf4442dda189a91
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/AbstractDumper.java
@@ -0,0 +1,146 @@
+/*
+ * 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.packages.analyzer.dump;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.Detector;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackage;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+import com.oracle.truffle.r.test.packages.analyzer.parser.LogFileParseException;
+
+public abstract class AbstractDumper {
+
+    public abstract void dump(Collection<RPackage> problems, Collection<LogFileParseException> collection);
+
+    protected Map<Class<? extends Problem>, List<Problem>> groupByType(Collection<Problem> problems) {
+        return problems.stream().collect(Collectors.groupingBy(p -> p.getClass()));
+    }
+
+    protected Map<RPackage, List<Problem>> groupByPkg(Collection<Problem> problems) {
+        return problems.stream().collect(Collectors.groupingBy(p -> p.getPackageTestRun().getPackage()));
+    }
+
+    protected Map<RPackageTestRun, List<Problem>> groupByTestRuns(Collection<RPackageTestRun> allTestRuns, Collection<Problem> problems) {
+        Map<RPackageTestRun, List<Problem>> groupedByTestRun = problems.stream().collect(Collectors.groupingBy(p -> p.getPackageTestRun()));
+        // insert test runs don't having any problems
+        for (RPackageTestRun testRun : allTestRuns) {
+            if (!groupedByTestRun.containsKey(testRun)) {
+                groupedByTestRun.put(testRun, Collections.emptyList());
+            }
+        }
+        return groupedByTestRun;
+    }
+
+    protected Map<ProblemContent, List<Problem>> groupByProblemContent(Collection<Problem> problems) {
+        return problems.stream().collect(Collectors.groupingBy(p -> new ProblemContent(p)));
+    }
+
+    protected static Collection<Problem> eliminateRedundantProblems(Collection<Problem> problems) {
+        // build detector hierarchy
+        Set<Detector<?>> collect = problems.stream().map(p -> p.getDetector()).collect(Collectors.toSet());
+        Map<Detector<?>, Collection<Detector<?>>> hierarchy = new HashMap<>();
+        for (Detector<?> detector : collect) {
+            hierarchy.put(detector, collectChildrenRecursive(detector));
+        }
+
+        Map<Detector<?>, List<Problem>> collect2 = problems.stream().collect(Collectors.groupingBy(p -> p.getDetector()));
+
+        List<Problem> cleaned = problems.stream().filter(p -> isIncluded(p, hierarchy, collect2)).collect(Collectors.toList());
+        assert new HashSet<>(cleaned).size() == cleaned.size();
+        return cleaned;
+    }
+
+    /**
+     * Returns {@code false} if any of the problem detector's children has reported a problem in the
+     * same location. Returns {@code true} otherwise.
+     */
+    private static boolean isIncluded(Problem p, Map<Detector<?>, Collection<Detector<?>>> hierarchy, Map<Detector<?>, List<Problem>> problemsTable) {
+        Collection<Detector<?>> children = hierarchy.get(p.getDetector());
+        for (Detector<?> childDetector : children) {
+            if (problemsTable.containsKey(childDetector)) {
+                for (Problem childProblem : problemsTable.get(childDetector)) {
+                    if (childProblem.getLocation().equals(p.getLocation())) {
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    private static Collection<Detector<?>> collectChildrenRecursive(Detector<?> detector) {
+        Collection<Detector<?>> all = new LinkedList<>();
+        all.addAll(detector.getChildren());
+        detector.getChildren().stream().forEach(c -> all.addAll(collectChildrenRecursive(c)));
+        return all;
+    }
+
+    protected static class ProblemContent {
+
+        final Problem representitive;
+
+        protected ProblemContent(Problem representitive) {
+            this.representitive = representitive;
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + ((representitive == null) ? 0 : representitive.getClass().hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            ProblemContent other = (ProblemContent) obj;
+            return representitive.isSimilarTo(other.representitive);
+        }
+
+        @Override
+        public String toString() {
+            return representitive.toString();
+        }
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/HTMLBuilder.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/HTMLBuilder.java
new file mode 100644
index 0000000000000000000000000000000000000000..b98cb6973e2b3ce507e375f6b7f7f83f2a81787b
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/HTMLBuilder.java
@@ -0,0 +1,202 @@
+/*
+ * 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.packages.analyzer.dump;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * A simple class for building and dumping HTML files.
+ */
+public class HTMLBuilder {
+
+    private PrintWriter pw;
+    private Tag root;
+
+    public HTMLBuilder(PrintWriter pw) {
+        this.pw = pw;
+    }
+
+    protected void dumpPrologue() {
+
+        pw.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">");
+    }
+
+    public Tag html(Tag... children) {
+        if (root != null) {
+            throw new RuntimeException("HTML root tag already used!");
+        }
+        return (root = generic("html", children));
+    }
+
+    public Tag head(Tag... children) {
+        return generic("head", children);
+    }
+
+    public Tag title(String title) {
+        return generic("title", title);
+    }
+
+    public Tag body(Tag... children) {
+        return generic("body", null, children);
+    }
+
+    public Tag table(Tag... children) {
+        return generic("table", children);
+    }
+
+    public Tag tr(Tag... children) {
+        return generic("tr", children);
+    }
+
+    public Tag th(String content) {
+        return generic("th", content);
+    }
+
+    public Tag th(Tag... children) {
+        return generic("th", children);
+    }
+
+    public Tag td(String content) {
+        return generic("td", content);
+    }
+
+    public Tag td(Tag... children) {
+        return generic("td", children);
+    }
+
+    public Tag a(String href, String content) {
+        Tag a = generic("a", content);
+        a.addAttribute("href", href);
+        return a;
+    }
+
+    public Tag h1(String content) {
+        return generic("h1", content);
+    }
+
+    public Tag h2(String content) {
+        return generic("h2", content);
+    }
+
+    public Tag q(String content) {
+        return generic("q", content);
+    }
+
+    public Tag p(String content) {
+        return generic("p", content);
+    }
+
+    public Tag p(Tag... children) {
+        return generic("p", children);
+    }
+
+    public Tag generic(String key, String content, Tag... children) {
+        return new Tag(key, content, Arrays.stream(children).collect(Collectors.toList()));
+    }
+
+    public Tag generic(String key, Tag... children) {
+        return generic(key, null, children);
+    }
+
+    public Tag generic(String key, String content) {
+        return new Tag(key, content);
+    }
+
+    public String escape(String text) {
+        return text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;").replace("\t", "    ").replace(" ", "&#8203;&nbsp;&#8203;").replace("\n", "<br />").replace("\r\n", "<br />");
+    }
+
+    /**
+     * Recursively dumps all generated tags starting at the root tag.
+     */
+    public void dump() {
+        if (root == null) {
+            throw new RuntimeException("no HTML root tag generated");
+        }
+        dumpPrologue();
+        visit(root);
+    }
+
+    private void visit(Tag t) {
+
+        pw.println(t.getOpening());
+        if (t.content != null) {
+            pw.print(t.content);
+        } else {
+            t.children.stream().forEach(child -> visit(child));
+        }
+        pw.println(t.getClosing());
+    }
+
+    public static class Tag {
+
+        private String name;
+        private String content;
+        private Map<String, String> attributes = new HashMap<>();
+        private List<Tag> children = new LinkedList<>();
+
+        protected Tag(String name) {
+            this.name = name;
+        }
+
+        protected Tag(String name, String content) {
+            this.name = name;
+            this.content = content;
+        }
+
+        protected Tag(String name, String content, List<Tag> children) {
+            this.name = name;
+            this.content = content;
+            this.children = children;
+        }
+
+        String getOpening() {
+            StringBuilder sb = new StringBuilder();
+            sb.append('<').append(name);
+            for (String key : attributes.keySet()) {
+                sb.append(' ').append(key).append("=\"").append(attributes.get(key)).append('"');
+            }
+            sb.append('>');
+            return sb.toString();
+        }
+
+        String getClosing() {
+            return "</" + name + ">";
+        }
+
+        public void addChild(Tag child) {
+            children.add(child);
+        }
+
+        public void addAttribute(String key, String value) {
+            attributes.put(key, value);
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/HTMLDumper.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/HTMLDumper.java
new file mode 100644
index 0000000000000000000000000000000000000000..02cd6e6ad887cdae0ec8637a9ddd0436283c2c4e
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/dump/HTMLDumper.java
@@ -0,0 +1,258 @@
+/*
+ * 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.packages.analyzer.dump;
+
+import static java.nio.file.StandardOpenOption.CREATE;
+import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING;
+import static java.nio.file.StandardOpenOption.WRITE;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.dump.HTMLBuilder.Tag;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackage;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+import com.oracle.truffle.r.test.packages.analyzer.parser.LogFileParseException;
+
+public class HTMLDumper extends AbstractDumper {
+
+    private static final String TITLE = "FastR Package Test Dashboard";
+    private Path destDir;
+
+    public HTMLDumper(Path destDir) {
+        this.destDir = Objects.requireNonNull(destDir);
+    }
+
+    /**
+     * Creates the output directory if it does not exists and checks if the directory is writable.
+     * This method may throw an {@link IOException} if it cannot create the directory.
+     */
+    public boolean createAndCheckOutDir() throws IOException {
+        if (!Files.exists(destDir)) {
+            Files.createDirectories(destDir);
+        }
+        // test creating a file in the output directory
+        Path testFile = destDir.resolve("test.html");
+        Files.createFile(testFile);
+        Files.deleteIfExists(testFile);
+        return true;
+    }
+
+    @Override
+    public void dump(Collection<RPackage> packages, Collection<LogFileParseException> parseErrors) {
+        try {
+            createAndCheckOutDir();
+            dumpIndexFile(packages, parseErrors);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private void dumpIndexFile(Collection<RPackage> packages, Collection<LogFileParseException> parseErrors) {
+        Path indexFile = destDir.resolve("index.html");
+
+        try (BufferedWriter bw = Files.newBufferedWriter(indexFile, CREATE, TRUNCATE_EXISTING, WRITE)) {
+            HTMLBuilder builder = new HTMLBuilder(new PrintWriter(bw));
+
+            Collection<Problem> allProblems = collectAllProblems(packages);
+            Collection<RPackageTestRun> allTestRuns = collectTestRuns(packages);
+
+            allProblems = eliminateRedundantProblems(allProblems);
+
+            Tag errorDistributionTable = generateTypeDistributionTable(builder, groupByType(allProblems));
+            Tag pkgDistributionTable = generateTestRunDistributionTable(indexFile, builder, groupByTestRuns(allTestRuns, allProblems));
+            Tag distrinctProblemDistributionTable = generateDistinctProblemDistribution(builder, groupByProblemContent(allProblems));
+
+            builder.html(builder.head(builder.title(TITLE)), builder.body(
+                            builder.h1(TITLE),
+                            builder.p("Total number of analysis candidates: " + allTestRuns.size()),
+                            builder.p(builder.a(generateParseErrorsList(parseErrors), "Test runs failed to analyze: " + parseErrors.size())),
+                            builder.h2("Distribution by Problem Type"), errorDistributionTable,
+                            builder.h2("Distribution by Package Test Run"), pkgDistributionTable,
+                            builder.h2("Distinct Problem Distribution"), distrinctProblemDistributionTable));
+            builder.dump();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    private static Collection<RPackageTestRun> collectTestRuns(Collection<RPackage> pkgs) {
+        Collection<RPackageTestRun> problems = new ArrayList<>();
+        for (RPackage pkg : pkgs) {
+            for (RPackageTestRun run : pkg.getTestRuns()) {
+                problems.add(run);
+            }
+        }
+        return problems;
+    }
+
+    private static Collection<Problem> collectAllProblems(Collection<RPackage> pkgs) {
+        Collection<Problem> problems = new ArrayList<>();
+        for (RPackage pkg : pkgs) {
+            for (RPackageTestRun run : pkg.getTestRuns()) {
+                problems.addAll(run.getProblems());
+            }
+        }
+        return problems;
+    }
+
+    private Tag generateTestRunDistributionTable(Path indexFile, HTMLBuilder builder, Map<RPackageTestRun, List<Problem>> groupByTestRun) {
+        List<RPackageTestRun> collect = groupByTestRun.keySet().stream().sorted((a, b) -> Integer.compare(groupByTestRun.get(b).size(), groupByTestRun.get(a).size())).collect(Collectors.toList());
+
+        Tag table = builder.table(builder.tr(
+                        builder.th("Package"),
+                        builder.th("Test Run"),
+                        builder.th("Result"),
+                        builder.th("Problem Count")));
+        table.addAttribute("border", "1");
+
+        for (RPackageTestRun testRun : collect) {
+            int n = groupByTestRun.get(testRun).size();
+            String pkgFileName;
+            if (n > 0) {
+                pkgFileName = dumpTableFile(testRun.getPackage().toString() + "_" + testRun.getNumber() + ".html", testRun.toString(), testRun, groupByTestRun);
+            } else {
+                Path relativeLocation = indexFile.relativize(testRun.getLogFile());
+                relativeLocation = relativeLocation.subpath(1, relativeLocation.getNameCount());
+                pkgFileName = relativeLocation.toString();
+            }
+
+            Tag tableRow = builder.tr(
+                            builder.td(builder.a(pkgFileName, testRun.getPackage().toString())),
+                            builder.td(Integer.toString(testRun.getNumber())),
+                            builder.td(testRun.isSuccess() ? "OK" : "FAILED"),
+                            builder.td(Integer.toString(n)));
+            if (testRun.isSuccess() && n > 0) {
+                tableRow.addAttribute("bgcolor", "#fdae61");
+            }
+            table.addChild(tableRow);
+        }
+        return table;
+    }
+
+    private Tag generateDistinctProblemDistribution(HTMLBuilder builder, Map<ProblemContent, List<Problem>> groupByPkg) {
+        List<ProblemContent> collect = groupByPkg.keySet().stream().sorted((a, b) -> Integer.compare(groupByPkg.get(b).size(), groupByPkg.get(a).size())).collect(Collectors.toList());
+
+        Tag table = builder.table(builder.tr(
+                        builder.th("Problem"),
+                        builder.th("Problem Count"),
+                        builder.th("Representitive Message")));
+        table.addAttribute("border", "1");
+
+        int i = 0;
+        for (ProblemContent problem : collect) {
+            String pkgFileName = dumpTableFile("problem" + i + ".html", problem.toString(), problem, groupByPkg);
+            ++i;
+
+            int n = groupByPkg.get(problem).size();
+            Tag tableRow = builder.tr(
+                            builder.td(builder.a(pkgFileName, problem.representitive.getSummary())),
+                            builder.td(Integer.toString(n)),
+                            builder.td(problem.representitive.getDetails()));
+            table.addChild(tableRow);
+        }
+        return table;
+    }
+
+    private Tag generateTypeDistributionTable(HTMLBuilder builder, Map<Class<? extends Problem>, List<Problem>> groupByType) {
+        List<Class<? extends Problem>> collect = groupByType.keySet().stream().sorted((a, b) -> Integer.compare(groupByType.get(b).size(), groupByType.get(a).size())).collect(Collectors.toList());
+
+        Tag table = builder.table();
+        table.addAttribute("border", "1");
+        for (Class<? extends Problem> type : collect) {
+            String problemClassFileName = dumpTableFile(type.getSimpleName() + ".html", type.getName(), type, groupByType);
+            table.addChild(builder.tr(
+                            builder.td(builder.a(problemClassFileName, type.getSimpleName())),
+                            builder.td(Integer.toString(groupByType.get(type).size()))));
+        }
+        return table;
+    }
+
+    private <T> String dumpTableFile(String htmlFileName, String title, T key, Map<T, List<Problem>> groupingTable) {
+
+        Path problemClassFile = destDir.resolve(htmlFileName);
+        try (BufferedWriter bw = Files.newBufferedWriter(problemClassFile, CREATE, TRUNCATE_EXISTING, WRITE)) {
+            HTMLBuilder builder = new HTMLBuilder(new PrintWriter(bw));
+
+            Tag table = generateProblemTable(problemClassFile, key, groupingTable, builder);
+
+            builder.html(builder.head(builder.title(title)), builder.body(table));
+            builder.dump();
+
+            return problemClassFile.getFileName().toString();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private static <T> Tag generateProblemTable(Path file, T key, Map<T, List<Problem>> groupingTable, HTMLBuilder builder) {
+        Tag table = builder.table();
+        table.addAttribute("border", "1");
+        for (Problem p : groupingTable.get(key)) {
+            Location loc = p.getLocation();
+            Path relativeLocation = file.relativize(loc.file);
+            // remove nearest path element because relativizing also considers file names
+            relativeLocation = relativeLocation.subpath(1, relativeLocation.getNameCount());
+            table.addChild(builder.tr(
+                            builder.td(builder.a(relativeLocation.toString() + "#" + loc.lineNr, loc.toString())),
+                            builder.td(builder.escape(p.getSummary())),
+                            builder.td(builder.escape(p.getDetails()))));
+        }
+        return table;
+    }
+
+    private String generateParseErrorsList(Collection<LogFileParseException> parseErrors) throws IOException {
+
+        Path problemClassFile = destDir.resolve("failedToAnalyze.html");
+        try (BufferedWriter bw = Files.newBufferedWriter(problemClassFile, CREATE, TRUNCATE_EXISTING, WRITE)) {
+            HTMLBuilder builder = new HTMLBuilder(new PrintWriter(bw));
+            Tag table = builder.table(builder.tr(
+                            builder.th("Package Test Run"),
+                            builder.th("Location"),
+                            builder.th("Message")));
+            table.addAttribute("border", "1");
+            for (LogFileParseException e : parseErrors) {
+                table.addChild(builder.tr(
+                                builder.td(e.getTestRun().toString()),
+                                builder.td(e.getLocation().toString()),
+                                builder.td(e.getMessage())));
+            }
+            builder.html(builder.head(builder.title("Test Runs Failed to Analyze")), builder.body(table));
+            builder.dump();
+        }
+        return problemClassFile.getFileName().toString();
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/model/RPackage.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/model/RPackage.java
new file mode 100644
index 0000000000000000000000000000000000000000..66b1ef6c51956e369c5a7f42385df57047399ff8
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/model/RPackage.java
@@ -0,0 +1,110 @@
+/*
+ * 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.packages.analyzer.model;
+
+import java.nio.file.Path;
+import java.util.Collection;
+
+/**
+ * Represents a tested R package in a specific version.
+ */
+public class RPackage {
+
+    private final String name;
+    private final String version;
+    private Path location;
+    private Collection<RPackageTestRun> testRuns;
+
+    public RPackage(String name, String version) {
+        this.name = name;
+        this.version = version;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public Path getLocation() {
+        return location;
+    }
+
+    public void setLocation(Path location) {
+        this.location = location;
+    }
+
+    public Collection<RPackageTestRun> getTestRuns() {
+        return testRuns;
+    }
+
+    public void setTestRuns(Collection<RPackageTestRun> testRuns) {
+        this.testRuns = testRuns;
+    }
+
+    @Override
+    public String toString() {
+        return name + "-" + version;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((version == null) ? 0 : version.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        RPackage other = (RPackage) obj;
+        if (name == null) {
+            if (other.name != null) {
+                return false;
+            }
+        } else if (!name.equals(other.name)) {
+            return false;
+        }
+        if (version == null) {
+            if (other.version != null) {
+                return false;
+            }
+        } else if (!version.equals(other.version)) {
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/model/RPackageTestRun.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/model/RPackageTestRun.java
new file mode 100644
index 0000000000000000000000000000000000000000..163159445a2e9890451aa77418b42ee239c9d368
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/model/RPackageTestRun.java
@@ -0,0 +1,123 @@
+/*
+ * 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.packages.analyzer.model;
+
+import java.nio.file.Path;
+import java.util.Collection;
+import java.util.Collections;
+
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+
+/**
+ * Represents one test run of a package.
+ */
+public class RPackageTestRun {
+
+    private Path logFile;
+    private final RPackage pkg;
+    private final int nr;
+    private Collection<Problem> problems;
+
+    /** The overall outcome of the package test run as reported. */
+    private boolean success;
+
+    public RPackageTestRun(RPackage pkg, int nr) {
+        this.pkg = pkg;
+        this.nr = nr;
+    }
+
+    public RPackage getPackage() {
+        return pkg;
+    }
+
+    public int getNumber() {
+        return nr;
+    }
+
+    public void setProblems(Collection<Problem> p) {
+        problems = p;
+    }
+
+    public Collection<Problem> getProblems() {
+        if (problems != null) {
+            return problems;
+        }
+        return Collections.emptyList();
+    }
+
+    public void setSuccess(boolean success) {
+        this.success = success;
+    }
+
+    public boolean isSuccess() {
+        return success;
+    }
+
+    @Override
+    public String toString() {
+        return pkg + "/" + nr;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + nr;
+        result = prime * result + ((pkg == null) ? 0 : pkg.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        RPackageTestRun other = (RPackageTestRun) obj;
+        if (nr != other.nr) {
+            return false;
+        }
+        if (pkg == null) {
+            if (other.pkg != null) {
+                return false;
+            }
+        } else if (!pkg.equals(other.pkg)) {
+            return false;
+        }
+        return true;
+    }
+
+    public void setLogFile(Path logFile) {
+        this.logFile = logFile;
+    }
+
+    public Path getLogFile() {
+        return logFile;
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/DiffParser.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/DiffParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c6a3ab3ec13100b4bf7753afbd8fe3237ce6b96
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/DiffParser.java
@@ -0,0 +1,293 @@
+/*
+ * 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.packages.analyzer.parser;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+
+public class DiffParser {
+
+    private final LogFileParser parent;
+
+    /**
+     * Diff change command pattern.<br>
+     * Format (EBNF): diffCmd = int [ ',' int ] ( 'a' | 'c' | 'd' ) int [ ',' int ].<br>
+     * <p>
+     * Capture Groups:<br>
+     * group(1) = left from line<br>
+     * group(3) = left to line<br>
+     * group(5) = right from line<br>
+     * group(7) = right to line<br>
+     * group("CMD") = command<br>
+     * </p>
+     */
+    public static final Pattern CHANGE_CMD_PATTERN = Pattern.compile("(\\d+)(,(\\d+))?(?<CMD>a|c|d)(\\d+)(,(\\d+))?");
+
+    protected DiffParser(LogFileParser parent) {
+        this.parent = parent;
+    }
+
+    private Location loc(int l) {
+        return new Location(parent.getLogFile().getPath(), l);
+    }
+
+    public List<DiffParser.DiffChunk> parseDiff() throws IOException {
+        List<DiffParser.DiffChunk> diffResult = new LinkedList<>();
+
+        for (;;) {
+            Matcher matcher = CHANGE_CMD_PATTERN.matcher(LogFileParser.trim(parent.getLookahead().text));
+            if (matcher.matches()) {
+                parent.consumeLine();
+
+                DiffParser.ChangeCommand changeCommand = parseCommand(matcher);
+                switch (changeCommand.cmd) {
+                    case 'a': {
+                        int rightStart = parent.getLookahead().lineNr;
+                        List<String> rLines = parseRight(changeCommand);
+                        diffResult.add(new DiffChunk(changeCommand, Collections.emptyList(), null, rLines, loc(rightStart)));
+                        break;
+                    }
+                    case 'c': {
+                        int leftStart = parent.getLookahead().lineNr;
+                        List<String> lLines = parseLeft(changeCommand);
+                        parent.expect("---");
+                        int rightStart = parent.getLookahead().lineNr;
+                        List<String> rLines = parseRight(changeCommand);
+                        diffResult.add(new DiffChunk(changeCommand, lLines, loc(leftStart), rLines, loc(rightStart)));
+                        break;
+                    }
+                    case 'd': {
+                        int leftStart = parent.getLookahead().lineNr;
+                        List<String> lLines = parseLeft(changeCommand);
+                        diffResult.add(new DiffChunk(changeCommand, lLines, loc(leftStart), Collections.emptyList(), null));
+                        break;
+                    }
+                    default:
+                        throw parent.parseError("Unknown diff command: ");
+                }
+            } else {
+                // no more diff chunks; exit loop
+                break;
+            }
+        }
+        return diffResult;
+    }
+
+    private List<String> parseRight(DiffParser.ChangeCommand parseCommand) throws IOException {
+        return parseSide(">", parseCommand.rFrom, parseCommand.rTo);
+    }
+
+    private List<String> parseLeft(DiffParser.ChangeCommand parseCommand) throws IOException {
+        return parseSide("<", parseCommand.lFrom, parseCommand.lTo);
+    }
+
+    private List<String> parseSide(String prefix, int from, int to) throws IOException {
+        List<String> lines = new LinkedList<>();
+        int len = to == -1 ? 1 : to - from + 1;
+        for (int i = 0; i < len; i++) {
+            parent.expect(prefix);
+            lines.add(LogFileParser.trim(LogFileParser.trim(parent.getCurLine().text).substring(prefix.length())));
+        }
+        return lines;
+    }
+
+    private ChangeCommand parseCommand(Matcher matcher) {
+        if (matcher.matches()) {
+            String cmdStr = matcher.group("CMD");
+            if (cmdStr.length() != 1) {
+                throw parent.parseError("Invalid diff change command: " + cmdStr);
+            }
+
+            char cmd = cmdStr.charAt(0);
+
+            String lFromStr = matcher.group(1);
+            String lToStr = matcher.group(3);
+            String rFromStr = matcher.group(5);
+            String rToStr = matcher.group(7);
+
+            return new ChangeCommand(atoi(lFromStr), atoi(lToStr), cmd, atoi(rFromStr), atoi(rToStr));
+        }
+        throw parent.parseError("Invalid diff change command: " + parent.getCurLine().text);
+    }
+
+    private static int atoi(String rToStr) {
+        if (rToStr != null && !rToStr.isEmpty()) {
+            return Integer.parseInt(rToStr);
+        }
+        return -1;
+    }
+
+    public static class DiffChunk {
+        private final DiffParser.ChangeCommand cmd;
+        private final List<String> left;
+        private final Location leftStart;
+        private final List<String> right;
+        private final Location rightStart;
+
+        protected DiffChunk(DiffParser.ChangeCommand cmd, List<String> left, Location leftStart, List<String> right, Location rightStart) {
+            this.cmd = cmd;
+            this.left = left;
+            this.right = right;
+            this.leftStart = leftStart;
+            this.rightStart = rightStart;
+        }
+
+        public DiffParser.ChangeCommand getChangeCommand() {
+            return cmd;
+        }
+
+        public List<String> getLeft() {
+            return left;
+        }
+
+        public List<String> getRight() {
+            return right;
+        }
+
+        public Path getLeftFile() {
+            return leftStart != null ? leftStart.file : null;
+        }
+
+        public int getLeftStartLine() {
+            return leftStart != null ? leftStart.lineNr : -1;
+        }
+
+        public Path getRightFile() {
+            return rightStart != null ? rightStart.file : null;
+        }
+
+        public int getRightStartLine() {
+            return rightStart != null ? rightStart.lineNr : -1;
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder sb = new StringBuilder();
+            sb.append(cmd).append(System.lineSeparator());
+            switch (cmd.cmd) {
+                case 'a':
+                    right.stream().forEach(r -> sb.append("> ").append(r).append(System.lineSeparator()));
+                    break;
+                case 'c':
+                    left.stream().forEach(l -> sb.append("< ").append(l).append(System.lineSeparator()));
+                    sb.append("---").append(System.lineSeparator());
+                    right.stream().forEach(r -> sb.append("> ").append(r).append(System.lineSeparator()));
+                    break;
+                case 'd':
+                    left.stream().forEach(l -> sb.append("< ").append(l).append(System.lineSeparator()));
+                    break;
+            }
+            return sb.toString();
+        }
+
+        public Location getLocation() {
+            if (leftStart != null) {
+                return leftStart;
+            }
+            assert rightStart != null;
+            return rightStart;
+        }
+    }
+
+    public static class ChangeCommand {
+
+        public final int lFrom;
+        public final int lTo;
+        public final char cmd;
+        public final int rFrom;
+        public final int rTo;
+
+        public ChangeCommand(int lFrom, int lTo, char cmd, int rFrom, int rTo) {
+            this.lFrom = lFrom;
+            this.lTo = lTo;
+            this.cmd = cmd;
+            this.rFrom = rFrom;
+            this.rTo = rTo;
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append(lFrom);
+            if (lTo != -1) {
+                sb.append(',').append(lTo);
+            }
+            sb.append(cmd).append(rFrom);
+            if (rTo != -1) {
+                sb.append(',').append(rTo);
+            }
+            return sb.toString();
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + cmd;
+            result = prime * result + lFrom;
+            result = prime * result + lTo;
+            result = prime * result + rFrom;
+            result = prime * result + rTo;
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            ChangeCommand other = (ChangeCommand) obj;
+            if (cmd != other.cmd) {
+                return false;
+            }
+            if (lFrom != other.lFrom) {
+                return false;
+            }
+            if (lTo != other.lTo) {
+                return false;
+            }
+            if (rFrom != other.rFrom) {
+                return false;
+            }
+            if (rTo != other.rTo) {
+                return false;
+            }
+            return true;
+        }
+
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParseException.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParseException.java
new file mode 100644
index 0000000000000000000000000000000000000000..c76f3756a2ed2d98f24c1c3ee933673c072e3193
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParseException.java
@@ -0,0 +1,50 @@
+/*
+ * 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.packages.analyzer.parser;
+
+import java.util.Objects;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+@SuppressWarnings("serial")
+public class LogFileParseException extends RuntimeException {
+
+    private final RPackageTestRun testRun;
+    private final Location location;
+
+    protected LogFileParseException(String message, RPackageTestRun testRun, Location location) {
+        super(message);
+        this.testRun = Objects.requireNonNull(testRun);
+        this.location = Objects.requireNonNull(location);
+    }
+
+    public RPackageTestRun getTestRun() {
+        return testRun;
+    }
+
+    public Location getLocation() {
+        return location;
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParser.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParser.java
new file mode 100644
index 0000000000000000000000000000000000000000..a54286695dbdfb5a01d3aaefbc190e74c8ef2016
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/parser/LogFileParser.java
@@ -0,0 +1,872 @@
+/*
+ * 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.packages.analyzer.parser;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.FileVisitor;
+import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.Detector;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.DummyDetector;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.LineDetector;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+import com.oracle.truffle.r.test.packages.analyzer.parser.DiffParser.DiffChunk;
+
+public class LogFileParser {
+
+    private static final Logger LOGGER = Logger.getLogger(LogFileParser.class.getName());
+
+    private RPackageTestRun pkg;
+    private BufferedReader reader;
+    private Line curLine;
+    private Line la;
+    private final Map<String, Collection<LineDetector>> detectorsTable = new HashMap<>();
+    private final Collection<LineDetector> anyDetectors = new ArrayList<>();
+    private final Collection<Detector<List<DiffChunk>>> testResultDetectors = new ArrayList<>();
+    private LogFile logFile;
+
+    private int lineNr = 0;
+
+    public LogFileParser(Path logFile, RPackageTestRun pkgTestRun) {
+        this.pkg = pkgTestRun;
+        this.logFile = new LogFile(logFile);
+    }
+
+    public void addDetector(Token hook, LineDetector detector) {
+        Objects.requireNonNull(detector);
+        Collection<LineDetector> registered = this.detectorsTable.get(hook);
+        if (registered == null) {
+            registered = new LinkedList<>();
+            this.detectorsTable.put(hook.name(), registered);
+        }
+        registered.add(detector);
+    }
+
+    public void addDetector(LineDetector detector) {
+        anyDetectors.add(Objects.requireNonNull(detector));
+    }
+
+    public void addTestResultDetector(Detector<List<DiffChunk>> detector) {
+        testResultDetectors.add(Objects.requireNonNull(detector));
+    }
+
+    public LogFile parseLogFile() throws IOException {
+        try (BufferedReader r = Files.newBufferedReader(logFile.path)) {
+            this.reader = r;
+            consumeLine();
+
+            Section installTest0 = parseInstallTest();
+            logFile.addSection(installTest0);
+            if (!installTest0.isSuccess()) {
+                return logFile;
+            }
+            Section installTest1 = parseInstallTest();
+            logFile.addSection(installTest1);
+            if (installTest1.isSuccess()) {
+                logFile.addSection(parseCheckResults());
+            }
+            TestResult overallResult = parseOverallStatus();
+            logFile.setSuccess(overallResult.toBoolean());
+
+            // In the end, a recursive diff is executed which might produce error messages.
+            collectBody();
+            expectEOF();
+        } finally {
+            this.reader = null;
+        }
+        return logFile;
+    }
+
+    private TestResult parseOverallStatus() throws IOException {
+        expect(Token.TEST_STATUS);
+        consumeLine();
+        return parseStatus(trim(curLine.text).substring((getPkgName() + ": ").length()));
+    }
+
+    private static boolean isEOF(Line l) {
+        return l.text == null;
+    }
+
+    void expectEOF() throws IOException {
+        consumeLine();
+        if (!isEOF(curLine)) {
+            throw new LogFileParseException("Expected end of file but was " + curLine.text, pkg, getCurrentLocation());
+        }
+    }
+
+    private Section parseCheckResults() throws IOException {
+        expect(Token.BEGIN_CHECKING);
+
+        Section checkResults = new Section(logFile, Token.BEGIN_CHECKING.linePrefix, curLine.lineNr);
+        checkResults.problems = new LinkedList<>();
+
+        boolean findGnurFailFiles = false;
+        Set<Path> ignoreFiles = new HashSet<>();
+
+        for (;;) {
+            if (la.text.contains(Token.FAIL_OUTPUT_GNUR.linePrefix)) {
+                consumeLine();
+                findGnurFailFiles = true;
+            } else if (la.text.contains(Token.FAIL_OUTPUT_FASTR.linePrefix)) {
+                consumeLine();
+                // Ignore this case because we will scan for ".fail" files in FastR's test output
+                // dir anyway.
+            } else if (la.text.contains(Token.MISSING_OUTPUT_FILE.linePrefix)) {
+                consumeLine();
+                int idx = curLine.text.indexOf(Token.MISSING_OUTPUT_FILE.linePrefix);
+                String fileNameStr = curLine.text.substring(idx + Token.MISSING_OUTPUT_FILE.linePrefix.length()).trim();
+                checkResults.problems.add(new MissingOutputFileProblem(pkg, DummyDetector.INSTANCE, getCurrentLocation(), fileNameStr));
+            } else if (la.text.contains(Token.CONTENT_MALFORMED.linePrefix)) {
+                consumeLine();
+                int idx = curLine.text.indexOf(Token.CONTENT_MALFORMED.linePrefix);
+                String fileNameStr = curLine.text.substring(idx + Token.CONTENT_MALFORMED.linePrefix.length()).trim();
+                checkResults.problems.add(new ContentMalformedProblem(pkg, DummyDetector.INSTANCE, getCurrentLocation(), fileNameStr));
+            } else if (la.text.contains(Token.OUTPUT_MISMATCH_FASTR.linePrefix)) {
+                consumeLine();
+                // extract file name of output file
+                // format: <pkg name>: FastR output mismatch: <out file name>
+                int idx = curLine.text.indexOf(Token.OUTPUT_MISMATCH_FASTR.linePrefix);
+                String fileNameStr = curLine.text.substring(idx + Token.OUTPUT_MISMATCH_FASTR.linePrefix.length()).trim();
+                Path outputFile = logFile.path.resolveSibling(Paths.get("testfiles", "fastr", fileNameStr));
+
+                // report the problem
+                checkResults.problems.add(new OutputMismatchProblem(pkg, DummyDetector.INSTANCE, getCurrentLocation(), fileNameStr));
+
+                if (Files.isReadable(outputFile)) {
+                    ignoreFiles.add(outputFile);
+                    checkResults.problems.addAll(applyDetectors(Token.OUTPUT_MISMATCH_FASTR, outputFile, 0, Files.readAllLines(outputFile)));
+                } else {
+                    // try to find the file anywhere in the test run directory (there were some
+                    // cases)
+                    Optional<Path> findFirst = null;
+                    try {
+                        findFirst = Files.find(logFile.path.getParent(), 3, (path, attr) -> path.getFileName().equals(outputFile.getFileName())).findFirst();
+                        if (findFirst.isPresent()) {
+                            ignoreFiles.add(findFirst.get());
+                            checkResults.problems.addAll(applyDetectors(Token.OUTPUT_MISMATCH_FASTR, findFirst.get(), 0, Files.readAllLines(findFirst.get())));
+                        }
+                    } catch (NoSuchFileException e) {
+                    }
+                    if (findFirst == null || !findFirst.isPresent()) {
+                        LOGGER.warning("Cannot read output file " + outputFile);
+
+                        // consume any lines to be able to continue
+                        collectBody(Token.END_CHECKING);
+                    }
+                }
+
+                checkResults.setSuccess(false);
+            } else {
+                break;
+            }
+        }
+
+        // Compute a set of files to ignore for analysis because the tests producing the files also
+        // failed in GnuR.
+        if (findGnurFailFiles) {
+            Path gnurTestOutputDir = logFile.path.resolveSibling("testfiles/gnur");
+            Path fastrTestOutputDir = logFile.path.resolveSibling("testfiles/fastr");
+            Stream<Path> failFiles = Files.find(gnurTestOutputDir, 5, (path, attr) -> path.getFileName().toString().endsWith(".fail"));
+            ignoreFiles.addAll(failFiles.map(p -> fastrTestOutputDir.resolve(gnurTestOutputDir.relativize(p))).collect(Collectors.toSet()));
+        }
+
+        scanTestOutputFiles(checkResults, p -> !ignoreFiles.contains(p));
+
+        expect(Token.END_CHECKING);
+        return checkResults;
+    }
+
+    Location getCurrentLocation() {
+        return new Location(logFile.path, curLine.lineNr);
+    }
+
+    private Section parseInstallTest() throws IOException {
+        expect(Token.BEGIN_INSTALL_TEST);
+        Section installTest = new Section(logFile, Token.BEGIN_INSTALL_TEST.linePrefix, curLine.lineNr);
+        boolean success = true;
+
+        String mode = trim(curLine.text).substring(Token.BEGIN_INSTALL_TEST.linePrefix.length());
+        if (!("FastR".equals(mode) || "GnuR".equals(mode))) {
+            throw parseError("Invalid mode: " + mode);
+        }
+        installTest.setMode(mode);
+
+        Section installationTask = parseInstallationTask();
+        installTest.addSection(installationTask);
+        if ("FastR".equals(mode)) {
+            installTest.setSuccess(parseInstallStatus().toBoolean() && success);
+
+        }
+        installTest.addSection(parseInstallSuggests());
+        Section testing = parseTesting();
+        installTest.addSection(testing);
+        installTest.setSuccess(testing.isSuccess() && success);
+        expect(Token.END_INSTALL_TEST);
+
+        return installTest;
+    }
+
+    private Section parseTesting() throws IOException {
+        expect(Token.BEGIN_PACKAGE_TESTS);
+
+        Section packageTests = new Section(logFile, Token.BEGIN_PACKAGE_TESTS.linePrefix, curLine.lineNr);
+
+        if (("install failed, not testing: " + getPkgName()).equals(trim(la.text))) {
+            consumeLine();
+            packageTests.setSuccess(false);
+        } else {
+            while (laMatches(Token.BEGIN_TESTING)) {
+                packageTests.addSection(parsePackageTest());
+            }
+            packageTests.setSuccess(true);
+        }
+        expect(Token.END_PACKAGE_TESTS);
+        return packageTests;
+    }
+
+    private Section parsePackageTest() throws IOException {
+        expect(Token.BEGIN_TESTING);
+        Section testing = new Section(logFile, Token.BEGIN_TESTING.linePrefix, curLine.lineNr);
+        testing.problems = new LinkedList<>();
+
+        // EXAMPLES
+        if (laMatches(Token.TESTING_EXAMPLES)) {
+            consumeLine();
+            testing.problems.addAll(applyDetectors(Token.TESTING_EXAMPLES, logFile.path, collectBody(Token.RUNNING_SPECIFIC_TESTS, Token.RUNNING_VIGNETTES, Token.END_TESTING)));
+        }
+
+        // SPECIFIC TESTS
+        if (laMatches(Token.RUNNING_SPECIFIC_TESTS)) {
+            consumeLine();
+
+            // e.g.: Running ‘runRUnitTests.R’
+            while (laMatches("Running ")) {
+                consumeLine();
+                // e.g.: comparing ‘test.read.xls.Rout’ to ‘test.read.xls.Rout.save’
+                if (laMatches("comparing ")) {
+                    consumeLine();
+
+                    // optional message: "files differ in number of lines:"
+                    if (laMatches("files differ in number of lines:")) {
+                        consumeLine();
+                    }
+
+                    // try to parse diff chunks
+                    List<DiffChunk> diffResult = new DiffParser(this).parseDiff();
+
+                    // apply detectors to diff chunks
+                    testing.problems.addAll(applyTestResultDetectors(diffResult));
+                    diffResult.stream().forEach(chunk -> {
+                        if (!chunk.getLeft().isEmpty()) {
+                            testing.problems.addAll(applyDetectors(Token.RUNNING_SPECIFIC_TESTS, chunk.getLeftFile(), chunk.getLeftStartLine(), chunk.getLeft()));
+                        }
+                        if (!chunk.getRight().isEmpty()) {
+                            testing.problems.addAll(applyDetectors(Token.RUNNING_SPECIFIC_TESTS, chunk.getRightFile(), chunk.getRightStartLine(), chunk.getRight()));
+                        }
+                    });
+
+                    // only if the output was equal, there will be "... OK"
+                    if (diffResult.isEmpty()) {
+                        int dotsIdx = curLine.text.lastIndexOf("...");
+                        parseStatus(trim(curLine.text.substring(dotsIdx + "...".length())));
+                    }
+                }
+            }
+        }
+
+        // VIGNETTES
+        if (laMatches(Token.RUNNING_VIGNETTES)) {
+            // e.g. Running vignettes for package ‘gdata’
+            consumeLine();
+
+            // e.g.: Running ‘mapLevels.Rnw’
+            if (laMatches("Running ")) {
+                consumeLine();
+            }
+            // TODO anything more to parse ?
+            testing.problems.addAll(applyDetectors(Token.RUNNING_VIGNETTES, logFile.path, collectBody(Token.END_TESTING)));
+        }
+
+        // consume any remaining lines to the end of this section
+        testing.problems.addAll(applyDetectors(Token.BEGIN_TESTING, logFile.path, collectBody(Token.END_TESTING)));
+        expect(Token.END_TESTING);
+        return testing;
+    }
+
+    private Section parseInstallationTask() throws IOException {
+        expect(Token.BEGIN_INSTALLATION);
+        Section installation = new Section(logFile, Token.BEGIN_INSTALLATION.linePrefix, curLine.lineNr);
+        Section processing = parseProcessingTask();
+        installation.addSection(processing);
+        expect(Token.END_INSTALLATION);
+        return installation;
+    }
+
+    private Section parseProcessingTask() throws IOException {
+        expect(Token.BEGIN_PROCESSING);
+        Section installation = new Section(logFile, Token.BEGIN_PROCESSING.linePrefix, curLine.lineNr);
+        installation.problems = applyDetectors(Token.BEGIN_PROCESSING, logFile.path, collectBody(Token.END_PROCESSING));
+        expect(Token.END_PROCESSING);
+        return installation;
+    }
+
+    private TestResult parseInstallStatus() throws IOException {
+        expect(Token.BEGIN_INSTALL_STATUS);
+        // pkgName: FAILED / OK
+        expect(getPkgName());
+        TestResult res = parseStatus(trim(curLine.text).substring((getPkgName() + ": ").length()));
+        expect(Token.END_INSTALL_STATUS);
+        return res;
+    }
+
+    private String getPkgName() {
+        return pkg.getPackage().getName();
+    }
+
+    private TestResult parseStatus(String substring) {
+        if (Token.OK.linePrefix.equals(substring.trim())) {
+            return TestResult.OK;
+        } else if (Token.FAILED.linePrefix.equals(substring.trim())) {
+            return TestResult.FAILED;
+        } else if (Token.INDETERMINATE.linePrefix.equals(substring.trim())) {
+            return TestResult.INDETERMINATE;
+        } else if (Token.UNKNOWN.linePrefix.equals(substring.trim())) {
+            return TestResult.UNKNOWN;
+        }
+        throw parseError("Unexpected status: " + substring);
+    }
+
+    private Section parseInstallSuggests() throws IOException {
+        expect(Token.BEGIN_SUGGESTS_INSTALL);
+        Section section = new Section(logFile, Token.BEGIN_SUGGESTS_INSTALL.linePrefix, curLine.lineNr);
+
+        // collect body of this section
+
+        Collection<Problem> problems = applyDetectors(Token.BEGIN_SUGGESTS_INSTALL, logFile.path, collectBody(Token.END_SUGGESTS_INSTALL));
+        section.problems = problems;
+
+        expect(Token.END_SUGGESTS_INSTALL);
+
+        return section;
+    }
+
+    private void scanTestOutputFiles(Section outputCheck, Predicate<Path> includeCheck) throws IOException {
+        if (outputCheck.problems == null) {
+            outputCheck.problems = new ArrayList<>();
+        }
+
+        Files.walkFileTree(logFile.path.resolveSibling("testfiles"), new FileVisitor<Path>() {
+
+            @Override
+            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+                // do not visit GnuR's test output subdirectory
+                if (dir.endsWith("gnur")) {
+                    return FileVisitResult.SKIP_SUBTREE;
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+                if (endsWith(file, ".Rout", ".fail") && includeCheck.test(file)) {
+                    outputCheck.problems.addAll(applyDetectors(Token.BEGIN_CHECKING, file, 0, Files.readAllLines(file)));
+                }
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
+                // ignore
+                return FileVisitResult.CONTINUE;
+            }
+
+            @Override
+            public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+                return FileVisitResult.CONTINUE;
+            }
+
+            private boolean endsWith(Path p, String... exts) {
+                for (String ext : exts) {
+                    if (p.getFileName().toString().endsWith(ext)) {
+                        return true;
+                    }
+                }
+                return false;
+            }
+        });
+    }
+
+    private Collection<Problem> applyDetectors(Token start, Path file, List<Line> body) {
+        if (!body.isEmpty()) {
+            Line firstLine = body.get(0);
+            List<String> strBody = body.stream().map(l -> l.text).collect(Collectors.toList());
+            return applyDetectors(start, file, firstLine.lineNr, strBody);
+        }
+        return new LinkedList<>();
+    }
+
+    private Collection<Problem> applyDetectors(Token start, Path file, int startLineNr, List<String> body) {
+        assert Files.isRegularFile(file);
+        Location startLocation = null;
+        if (!body.isEmpty()) {
+            assert startLineNr >= 0;
+            startLocation = new Location(file, startLineNr);
+        }
+        Map<LineDetector, Collection<Problem>> problems = new HashMap<>();
+        Collection<LineDetector> collection = detectorsTable.get(start.name());
+        if (collection != null) {
+            for (LineDetector detector : collection) {
+                Collection<Problem> detectedProblems = detector.detect(pkg, startLocation, body);
+                if (detectedProblems != null) {
+                    problems.put(detector, detectedProblems);
+                }
+            }
+        }
+        for (LineDetector detector : anyDetectors) {
+            Collection<Problem> detectedProblems = detector.detect(pkg, startLocation, body);
+            if (detectedProblems != null) {
+                problems.put(detector, detectedProblems);
+            }
+        }
+
+        return problems.values().stream().flatMap(p -> p.stream()).collect(Collectors.toList());
+    }
+
+    private Collection<Problem> applyTestResultDetectors(List<DiffChunk> diffChunk) {
+        return testResultDetectors.stream().map(detector -> detector.detect(pkg, null, diffChunk)).flatMap(l -> l.stream()).collect(Collectors.toList());
+    }
+
+    /**
+     * Collects all lines until the provided token (excluding the ending line).
+     */
+    private List<Line> collectBody(Token endSuggestsInstall) throws IOException {
+        List<Line> lines = new ArrayList<>();
+        while (!laMatches(endSuggestsInstall) && !isEOF(la)) {
+            consumeLine();
+            assert curLine.text != null;
+            lines.add(curLine);
+        }
+        return lines;
+    }
+
+    private List<Line> collectBody(Token... endSuggestsInstall) throws IOException {
+        List<Line> lines = new ArrayList<>();
+        while (!startsWithOneOf(endSuggestsInstall) && !isEOF(la)) {
+            consumeLine();
+            lines.add(curLine);
+        }
+        return lines;
+    }
+
+    private boolean startsWithOneOf(Token[] endSuggestsInstall) {
+        for (Token t : endSuggestsInstall) {
+            if (laMatches(t)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    boolean laMatches(Token expected) {
+        return laMatches(expected.linePrefix);
+    }
+
+    boolean laMatches(String prefix) {
+        return la.text != null && trim(la.text).startsWith(prefix);
+    }
+
+    void expect(Token expected) throws IOException {
+        expect(expected.linePrefix);
+    }
+
+    void expect(String linePrefix) throws IOException {
+        consumeLine();
+        if (isEOF(curLine) || !trim(curLine.text).startsWith(linePrefix)) {
+            throw parseError("Unexpected line " + (curLine.lineNr + 1) + " (expected \"" + linePrefix + "\" but was \"" + (isEOF(curLine) ? "<EOF>" : curLine.text) + "\"");
+        }
+    }
+
+    LogFileParseException parseError(String message) {
+        throw new LogFileParseException(message, pkg, getCurrentLocation());
+    }
+
+    void consumeLine() throws IOException {
+        curLine = la;
+        // skip empty lines
+        do {
+            la = new Line(lineNr++, reader.readLine());
+        } while (la != null && la.text != null && la.isEmpty());
+    }
+
+    LogFile getLogFile() {
+        return logFile;
+    }
+
+    Line getCurLine() {
+        return curLine;
+    }
+
+    Line getLookahead() {
+        return la;
+    }
+
+    static String trim(String l) {
+        return l != null ? l.trim() : null;
+    }
+
+    static class Line {
+        final int lineNr;
+        final String text;
+
+        protected Line(int lineNr, String text) {
+            this.lineNr = lineNr;
+            this.text = text;
+        }
+
+        public boolean isEmpty() {
+            return text != null && text.isEmpty();
+        }
+
+        @Override
+        public int hashCode() {
+            final int prime = 31;
+            int result = 1;
+            result = prime * result + lineNr;
+            result = prime * result + ((text == null) ? 0 : text.hashCode());
+            return result;
+        }
+
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj == null) {
+                return false;
+            }
+            if (getClass() != obj.getClass()) {
+                return false;
+            }
+            Line other = (Line) obj;
+            if (lineNr != other.lineNr) {
+                return false;
+            }
+            if (text == null) {
+                if (other.text != null) {
+                    return false;
+                }
+            } else if (!text.equals(other.text)) {
+                return false;
+            }
+            return true;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("%d: %s", lineNr, text);
+        }
+    }
+
+    public enum TestResult {
+        OK,
+        FAILED,
+        UNKNOWN,
+        INDETERMINATE;
+
+        boolean toBoolean() {
+            return OK.equals(this);
+        }
+    }
+
+    public enum Token {
+
+        BEGIN_INSTALL_TEST("BEGIN install/test with "),
+        END_INSTALL_TEST("END install/test with "),
+        BEGIN_CHECKING("BEGIN checking "),
+        END_CHECKING("END checking "),
+        TEST_STATUS("Test Status"),
+        BEGIN_INSTALLATION("BEGIN package installation"),
+        END_INSTALLATION("END package installation"),
+        BEGIN_PROCESSING("BEGIN processing: "),
+        END_PROCESSING("END processing: "),
+        BEGIN_INSTALL_STATUS("BEGIN install status"),
+        END_INSTALL_STATUS("END install status"),
+        BEGIN_SUGGESTS_INSTALL("BEGIN suggests install"),
+        END_SUGGESTS_INSTALL("END suggests install"),
+        BEGIN_PACKAGE_TESTS("BEGIN package tests"),
+        END_PACKAGE_TESTS("END package tests"),
+        INSTALL_FAILED("install failed, not testing: "),
+        BEGIN_TESTING("BEGIN testing: "),
+        END_TESTING("END testing: "),
+        TEST_TIME("TEST_TIME: "),
+        FAIL_OUTPUT_GNUR("GnuR test had .fail outputs"),
+        FAIL_OUTPUT_FASTR("FastR test had .fail outputs"),
+        MISSING_OUTPUT_FILE("FastR is missing output file:"),
+        CONTENT_MALFORMED("content malformed: "),
+        OUTPUT_MISMATCH_FASTR("FastR output mismatch: "),
+
+        TESTING_EXAMPLES("Testing examples for package"),
+        RUNNING_SPECIFIC_TESTS("Running specific tests for package"),
+        RUNNING_VIGNETTES("Running vignettes for package"),
+
+        FAILED("FAILED"),
+        INDETERMINATE("INDETERMINATE"),
+        UNKNOWN("UNKNOWN"),
+        OK("OK");
+
+        String linePrefix;
+
+        Token(String prefix) {
+            this.linePrefix = prefix;
+        }
+
+    }
+
+    public abstract static class AbstractSection {
+        private List<Section> sections = new LinkedList<>();
+        private boolean success;
+
+        public List<Section> getSections() {
+            return sections;
+        }
+
+        public void addSection(Section sub) {
+            sections.add(sub);
+        }
+
+        public abstract Collection<Problem> collectProblems();
+
+        public boolean isSuccess() {
+            return success;
+        }
+
+        public void setSuccess(boolean success) {
+            this.success = success;
+        }
+
+    }
+
+    public static class LogFile extends AbstractSection {
+        public LogFile(Path path) {
+            this.path = path;
+        }
+
+        private Path path;
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("LogFile ").append(path);
+            if (!getSections().isEmpty()) {
+                sb.append("(");
+                for (Section section : getSections()) {
+                    sb.append(section).append(", ");
+                }
+                sb.append(")");
+            }
+            return sb.toString();
+        }
+
+        @Override
+        public Collection<Problem> collectProblems() {
+            return getSections().stream().flatMap(s -> s.collectProblems().stream()).collect(Collectors.toList());
+        }
+
+        public Path getPath() {
+            return path;
+        }
+
+    }
+
+    public static class Section extends AbstractSection {
+        private String name;
+        private String mode;
+        private int startLine;
+        private AbstractSection parent;
+        Collection<Problem> problems;
+
+        protected Section(AbstractSection parent, String name, int startLine) {
+            this.parent = parent;
+            this.startLine = startLine;
+            this.name = name;
+        }
+
+        public AbstractSection getParent() {
+            return parent;
+        }
+
+        public String getMode() {
+            return mode;
+        }
+
+        public void setMode(String mode) {
+            this.mode = mode;
+        }
+
+        @Override
+        public String toString() {
+            return String.format("Section %s (start: %d, problems: %d)", name, startLine, problems != null ? problems.size() : 0);
+        }
+
+        @Override
+        public Collection<Problem> collectProblems() {
+            Collection<Problem> collected = new ArrayList<>();
+            if (problems != null) {
+                collected.addAll(problems);
+            }
+            for (Section child : getSections()) {
+                collected.addAll(child.collectProblems());
+            }
+            return collected;
+        }
+
+    }
+
+    public static class OutputMismatchProblem extends Problem {
+
+        private final String details;
+
+        protected OutputMismatchProblem(RPackageTestRun pkg, Detector<?> detector, Location location, String details) {
+            super(pkg, detector, location);
+            this.details = details;
+        }
+
+        @Override
+        public String getSummary() {
+            return Token.OUTPUT_MISMATCH_FASTR.linePrefix;
+        }
+
+        @Override
+        public String getDetails() {
+            return details;
+        }
+
+        @Override
+        public String toString() {
+            return getSummary() + details;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            return isSimilarTo(other) ? 0 : 1;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return other.getClass() == OutputMismatchProblem.class;
+        }
+    }
+
+    public static class MissingOutputFileProblem extends Problem {
+
+        private final String details;
+
+        protected MissingOutputFileProblem(RPackageTestRun pkg, Detector<?> detector, Location location, String details) {
+            super(pkg, detector, location);
+            this.details = details;
+        }
+
+        @Override
+        public String getSummary() {
+            return Token.MISSING_OUTPUT_FILE.linePrefix;
+        }
+
+        @Override
+        public String getDetails() {
+            return details;
+        }
+
+        @Override
+        public String toString() {
+            return getSummary() + details;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            return isSimilarTo(other) ? 0 : 1;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return other.getClass() == MissingOutputFileProblem.class;
+        }
+    }
+
+    public static class ContentMalformedProblem extends Problem {
+
+        private final String details;
+
+        protected ContentMalformedProblem(RPackageTestRun pkg, Detector<?> detector, Location location, String details) {
+            super(pkg, detector, location);
+            this.details = details;
+        }
+
+        @Override
+        public String getSummary() {
+            return Token.CONTENT_MALFORMED.linePrefix;
+        }
+
+        @Override
+        public String getDetails() {
+            return details;
+        }
+
+        @Override
+        public String toString() {
+            return getSummary() + details;
+        }
+
+        @Override
+        public int getSimilarityTo(Problem other) {
+            return isSimilarTo(other) ? 0 : 1;
+        }
+
+        @Override
+        public boolean isSimilarTo(Problem other) {
+            return other.getClass() == ContentMalformedProblem.class;
+        }
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/PatternTest.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/PatternTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..3084ee7d470bb57e8be9641eac558a0c21eaff4f
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/PatternTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.packages.analyzer.test;
+
+import java.util.regex.Matcher;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.packages.analyzer.parser.DiffParser;
+import com.oracle.truffle.r.test.packages.analyzer.parser.DiffParser.ChangeCommand;
+
+public class PatternTest {
+
+    private static void assertMatch(String s, ChangeCommand expected) {
+        Matcher matcher = DiffParser.CHANGE_CMD_PATTERN.matcher(s);
+
+        Assert.assertTrue(matcher.matches());
+
+        String cmdStr = matcher.group("CMD");
+        Assert.assertEquals(1, cmdStr.length());
+
+        char cmd = cmdStr.charAt(0);
+
+        String lFromStr = matcher.group(1);
+        String lToStr = matcher.group(3);
+        String rFromStr = matcher.group(5);
+        String rToStr = matcher.group(7);
+
+        Assert.assertEquals(expected, new ChangeCommand(atoi(lFromStr), atoi(lToStr), cmd, atoi(rFromStr), atoi(rToStr)));
+    }
+
+    private static int atoi(String rToStr) {
+        if (rToStr != null && !rToStr.isEmpty()) {
+            return Integer.parseInt(rToStr);
+        }
+        return -1;
+    }
+
+    @Test
+    public void testSingleDigitLine() {
+        assertMatch("1a1", new ChangeCommand(1, -1, 'a', 1, -1));
+        assertMatch("1c1", new ChangeCommand(1, -1, 'c', 1, -1));
+        assertMatch("1d1", new ChangeCommand(1, -1, 'd', 1, -1));
+    }
+
+    @Test
+    public void testMultipleDigitsLine() {
+        assertMatch("10a1", new ChangeCommand(10, -1, 'a', 1, -1));
+        assertMatch("100c1", new ChangeCommand(100, -1, 'c', 1, -1));
+        assertMatch("12345d1", new ChangeCommand(12345, -1, 'd', 1, -1));
+        assertMatch("1a10", new ChangeCommand(1, -1, 'a', 10, -1));
+        assertMatch("1c100", new ChangeCommand(1, -1, 'c', 100, -1));
+        assertMatch("1d12345", new ChangeCommand(1, -1, 'd', 12345, -1));
+    }
+
+    @Test
+    public void testRangeSingleDigit() {
+        assertMatch("1,2a1", new ChangeCommand(1, 2, 'a', 1, -1));
+        assertMatch("1,2a1,2", new ChangeCommand(1, 2, 'a', 1, 2));
+        assertMatch("1a1,2", new ChangeCommand(1, -1, 'a', 1, 2));
+    }
+
+    @Test
+    public void testRangeMultipleDigits() {
+        assertMatch("10,25a1", new ChangeCommand(10, 25, 'a', 1, -1));
+        assertMatch("10,25a10,25", new ChangeCommand(10, 25, 'a', 10, 25));
+        assertMatch("1a10,25", new ChangeCommand(1, -1, 'a', 10, 25));
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/RErrorDetectorTest.java b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/RErrorDetectorTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..9e295bb54b43f612cd0829ff2e1cc3c27be58587
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages.analyzer/src/com/oracle/truffle/r/test/packages/analyzer/test/RErrorDetectorTest.java
@@ -0,0 +1,196 @@
+/*
+ * 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.packages.analyzer.test;
+
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.packages.analyzer.Location;
+import com.oracle.truffle.r.test.packages.analyzer.Problem;
+import com.oracle.truffle.r.test.packages.analyzer.detectors.RErrorDetector;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackage;
+import com.oracle.truffle.r.test.packages.analyzer.model.RPackageTestRun;
+
+public class RErrorDetectorTest {
+
+    private static final RPackage pkg;
+    private static final RPackageTestRun pkgTestRun;
+
+    static {
+        pkg = new RPackage("fastr", "0.27");
+        pkg.setLocation(Paths.get("fastr"));
+        pkgTestRun = new RPackageTestRun(pkg, 1);
+    }
+
+    @Test
+    public void testMultiLine() {
+        List<String> lines = Arrays.asList(new String[]{"Error in check(options) : ",
+                        "ERROR: installing Rd objects failed for package ‘RUnit’"});
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error in check(options)", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("ERROR: installing Rd objects failed for package ‘RUnit’", findFirst.orElse(null).getDetails().trim());
+
+    }
+
+    @Test
+    public void testSingleLine0() {
+        List<String> lines = Collections.singletonList("Error in check(options) : invalid value for 'label' ");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error in check(options)", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("invalid value for 'label'", findFirst.orElse(null).getDetails().trim());
+
+    }
+
+    @Test
+    public void testSingleLine1() {
+        List<String> lines = Collections.singletonList("Error in check : invalid value for 'label' ");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error in check", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("invalid value for 'label'", findFirst.orElse(null).getDetails().trim());
+
+    }
+
+    @Test
+    public void testSingleLineMultipleColon() {
+        List<String> lines = Collections.singletonList("Error in check(options) : invalid value for 'label' : ");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error in check(options)", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("invalid value for 'label' :", findFirst.orElse(null).getDetails().trim());
+
+    }
+
+    @Test
+    public void testSingleLineWithoutCallstring0() {
+        List<String> lines = Collections.singletonList("Error: invalid value for 'label' ");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("invalid value for 'label'", findFirst.orElse(null).getDetails().trim());
+
+    }
+
+    @Test
+    public void testSingleLineWithoutCallstring1() {
+        List<String> lines = Collections.singletonList("Error: invalid value for 'label' : ");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("invalid value for 'label' :", findFirst.orElse(null).getDetails().trim());
+    }
+
+    @Test
+    public void testRInternalError0() {
+        List<String> lines = Collections.singletonList("RInternalError: invalid value for 'label'");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(0, detect.size());
+    }
+
+    @Test
+    public void testRInternalError1() {
+        List<String> lines = Collections.singletonList("> RInternalError: invalid value for 'label'");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(0, detect.size());
+    }
+
+    @Test
+    public void testRInternalError2() {
+        List<String> lines = Collections.singletonList("  RInternalError: invalid value for 'label'");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(0, detect.size());
+    }
+
+    @Test
+    public void testWithLinePrefix() {
+        List<String> lines = Collections.singletonList("> Error: invalid value for 'label'");
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("invalid value for 'label'", findFirst.orElse(null).getDetails().trim());
+    }
+
+    @Test
+    public void testCallstringWithNamesAndValues0() {
+        List<String> lines = Arrays.asList(new String[]{"Error in grep(pattern, all.names, value = TRUE) : ",
+                        "  invalid regular expression '*': Dangling meta character '*' near index 0"});
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error in grep(pattern, all.names, value = TRUE)", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("invalid regular expression '*': Dangling meta character '*' near index 0", findFirst.orElse(null).getDetails().trim());
+    }
+
+    @Test
+    public void testCallstringWithNamesAndValues1() {
+        List<String> lines = Arrays.asList(new String[]{"Error in grep(pattern, all.names, value = \":\") : ",
+                        "  invalid regular expression '*': Dangling meta character '*' near index 0"});
+
+        Collection<Problem> detect = RErrorDetector.INSTANCE.detect(pkgTestRun, loc(), lines);
+        Assert.assertEquals(1, detect.size());
+
+        Optional<Problem> findFirst = detect.stream().findFirst();
+        Assert.assertEquals("Error in grep(pattern, all.names, value = \":\")", findFirst.orElse(null).getSummary().trim());
+        Assert.assertEquals("invalid regular expression '*': Dangling meta character '*' near index 0", findFirst.orElse(null).getDetails().trim());
+    }
+
+    private static Location loc() {
+        return new Location(pkg.getLocation(), 0);
+    }
+
+}
diff --git a/com.oracle.truffle.r.test.packages/r/install.packages.R b/com.oracle.truffle.r.test.packages/r/install.packages.R
index 01facbd88a767347d392589cdeaedb117e837654..f0ae104d3972c796c7f1d1f7b5538e66f5df7ae1 100644
--- a/com.oracle.truffle.r.test.packages/r/install.packages.R
+++ b/com.oracle.truffle.r.test.packages/r/install.packages.R
@@ -114,6 +114,7 @@ usage <- function() {
 					  "[--install-dependents-first]",
 					  "[--run-mode mode]",
 					  "[--pkg-filelist file]",
+					  "[--find-top100]",
 					  "[--run-tests]",
 					  "[--testdir dir]",
 					  "[--print-ok-installs]",
@@ -124,7 +125,7 @@ usage <- function() {
 					  "[--alpha-daily]",
 					  "[--count-daily count]",
 					  "[--ok-only]",
-                      "[--pkg.pattern package-pattern] \n"))
+                      "[--pkg-pattern package-pattern] \n"))
 	quit(status=100)
 }
 
@@ -645,7 +646,7 @@ do.it <- function() {
 		for (pkgname in test.pkgnames) {
 			pkg <- toinstall.pkgs[pkgname, ]
 			# pretend we are accessing CRAN if list.canonical
-			list.contriburl = ifelse(list.canonical, "https://cran.r-project.org/src/contrib", contriburl)
+			list.contriburl = ifelse(list.canonical, "https://cran.r-project.org/src/contrib", pkg["Repository"])
 			cat(pkg["Package"], pkg["Version"], paste0(list.contriburl, "/", pkgname, "_", pkg["Version"], ".tar.gz"), "\n", sep=",")
 		}
 	}
@@ -887,6 +888,8 @@ parse.args <- function() {
 			use.installed.pkgs <<- TRUE
 		} else if (a == "--invert-pkgset") {
 			invert.pkgset <<- TRUE
+		} else if (a == "--find-top100") {
+			find.top100 <<- TRUE
 		} else {
 			if (grepl("^-.*", a)) {
 				usage()
@@ -965,8 +968,24 @@ get.initial.package.blacklist <- function() {
 	}
 }
 
+do.find.top100 <- function() {
+	avail.pkgs <- available.packages(type="source");
+	if (!require('cranlogs', quietly = T)) {
+		install.packages('cranlogs', quiet = T)
+		library('cranlogs', quietly = T)
+	}
+	top100 <- cran_top_downloads(when = c("last-day", "last-week", "last-month"), count = 100)
+	names <- top100[['package']]
+	l = length(names)
+	for (i in 1:l) {
+		pkgname <- names[[i]]
+		pkg <- avail.pkgs[pkgname, ]
+		list.contriburl = ifelse(list.canonical, "https://cran.r-project.org/src/contrib", pkg["Repository"])
+		cat(pkg["Package"], pkg["Version"], paste0(list.contriburl, "/", pkgname, "_", pkg["Version"], ".tar.gz"), "\n", sep = ",")
+	}
+}
+
 run.setup <- function() {
-	parse.args()
 	check.libs()
 	check.pkgfilelist()
 	set.repos()
@@ -977,8 +996,14 @@ run.setup <- function() {
 }
 
 run <- function() {
-	run.setup()
-    do.it()
+	parse.args()
+	if (find.top100) {
+		set.repos()
+		do.find.top100()
+	} else {
+	    run.setup()
+        do.it()
+    }
 }
 
 quiet <- F
@@ -1013,6 +1038,7 @@ gnur <- FALSE
 list.versions <- FALSE
 list.canonical <- FALSE
 invert.pkgset <- F
+find.top100 <- F
 
 if (!interactive()) {
     run()
diff --git a/com.oracle.truffle.r.test.packages/top100 b/com.oracle.truffle.r.test.packages/top100
index d9f2856a3c34440d219594730cf4dc416432932c..53473f7b1dc448ddba82366e338149bf81f36019 100644
--- a/com.oracle.truffle.r.test.packages/top100
+++ b/com.oracle.truffle.r.test.packages/top100
@@ -1,100 +1,100 @@
+R6
 Rcpp
+curl
+jsonlite
+tibble
 ggplot2
-plyr
+dplyr
+rlang
 stringr
-colorspace
+stringi
 digest
+magrittr
+plyr
+BH
 reshape2
-RColorBrewer
+pkgconfig
+DBI
 scales
-manipulate
+lazyeval
+backports
+RColorBrewer
+colorspace
+glue
 mime
-labeling
-munsell
-proto
+htmltools
+bindrcpp
+evaluate
+plogr
 gtable
+munsell
 dichromat
-zoo
-RCurl
-bitops
-evaluate
-car
-jsonlite
+labeling
 knitr
-formatR
-highr
-R6
+yaml
+bindr
+data.table
+memoise
+assertthat
+git2r
 httr
-lme4
-rJava
-quantreg
-SparseM
-nloptr
-dplyr
-DBI
-minqa
-MASS
 markdown
-lattice
+htmlwidgets
+openssl
+base64enc
+readr
+bitops
+XML
 devtools
+highr
+rJava
+rmarkdown
+httpuv
+tidyr
+caTools
+car
+shiny
+hms
+igraph
 Formula
-pbkrtest
-gtools
+RcppArmadillo
+gridExtra
+zoo
+xtable
+rprojroot
+sandwich
+viridisLite
+TTR
+checkmate
+lme4
 RcppEigen
-caTools
-magrittr
-yaml
-htmltools
+sourcetools
+quantmod
 Hmisc
-mgcv
+purrr
+viridis
 forecast
-Matrix
-lazyeval
-BH
-sandwich
-mvtnorm
-assertthat
-latticeExtra
-rjson
-rpart
-foreach
-XML
-roxygen2
-rstudioapi
-iterators
-xtable
-RJSONIO
-quadprog
+lubridate
+bit64
+SparseM
+readxl
 sp
-acepack
-RcppArmadillo
-e1071
-igraph
-tseries
-memoise
+quantreg
 gdata
-tm
-rmarkdown
-brew
-shiny
-timeDate
-codetools
-chron
-randomForest
-data.table
-testthat
-slam
-nnet
-xlsx
+xts
+withr
+RSQLite
+rstudioapi
+tseries
+psych
+RCurl
 whisker
-rgl
-boot
-reshape
-NLP
-gridExtra
-mnormt
-maps
-gplots
-survival
-foreign
-httpuv
+bit
+agricolae
+nloptr
+minqa
+blob
+pbkrtest
+MatrixModels
+cellranger
+mvtnorm
diff --git a/com.oracle.truffle.r.test.packages/top100versions b/com.oracle.truffle.r.test.packages/top100versions
new file mode 100644
index 0000000000000000000000000000000000000000..3c6cae6a78c329783298a98f3af7614a13690a3a
--- /dev/null
+++ b/com.oracle.truffle.r.test.packages/top100versions
@@ -0,0 +1,100 @@
+R6,2.2.2,https://cran.r-project.org/src/contrib/R6_2.2.2.tar.gz,
+Rcpp,0.12.12,https://cran.r-project.org/src/contrib/Rcpp_0.12.12.tar.gz,
+curl,2.8.1,https://cran.r-project.org/src/contrib/curl_2.8.1.tar.gz,
+tibble,1.3.3,https://cran.r-project.org/src/contrib/tibble_1.3.3.tar.gz,
+jsonlite,1.5,https://cran.r-project.org/src/contrib/jsonlite_1.5.tar.gz,
+ggplot2,2.2.1,https://cran.r-project.org/src/contrib/ggplot2_2.2.1.tar.gz,
+rlang,0.1.1,https://cran.r-project.org/src/contrib/rlang_0.1.1.tar.gz,
+dplyr,0.7.2,https://cran.r-project.org/src/contrib/dplyr_0.7.2.tar.gz,
+stringr,1.2.0,https://cran.r-project.org/src/contrib/stringr_1.2.0.tar.gz,
+withr,2.0.0,https://cran.r-project.org/src/contrib/withr_2.0.0.tar.gz,
+devtools,1.13.3,https://cran.r-project.org/src/contrib/devtools_1.13.3.tar.gz,
+stringi,1.1.5,https://cran.r-project.org/src/contrib/stringi_1.1.5.tar.gz,
+digest,0.6.12,https://cran.r-project.org/src/contrib/digest_0.6.12.tar.gz,
+plyr,1.8.4,https://cran.r-project.org/src/contrib/plyr_1.8.4.tar.gz,
+magrittr,1.5,https://cran.r-project.org/src/contrib/magrittr_1.5.tar.gz,
+reshape2,1.4.2,https://cran.r-project.org/src/contrib/reshape2_1.4.2.tar.gz,
+BH,1.62.0-1,https://cran.r-project.org/src/contrib/BH_1.62.0-1.tar.gz,
+pkgconfig,2.0.1,https://cran.r-project.org/src/contrib/pkgconfig_2.0.1.tar.gz,
+scales,0.4.1,https://cran.r-project.org/src/contrib/scales_0.4.1.tar.gz,
+DBI,0.7,https://cran.r-project.org/src/contrib/DBI_0.7.tar.gz,
+lazyeval,0.2.0,https://cran.r-project.org/src/contrib/lazyeval_0.2.0.tar.gz,
+RColorBrewer,1.1-2,https://cran.r-project.org/src/contrib/RColorBrewer_1.1-2.tar.gz,
+glue,1.1.1,https://cran.r-project.org/src/contrib/glue_1.1.1.tar.gz,
+colorspace,1.3-2,https://cran.r-project.org/src/contrib/colorspace_1.3-2.tar.gz,
+plogr,0.1-1,https://cran.r-project.org/src/contrib/plogr_0.1-1.tar.gz,
+bindrcpp,0.2,https://cran.r-project.org/src/contrib/bindrcpp_0.2.tar.gz,
+backports,1.1.0,https://cran.r-project.org/src/contrib/backports_1.1.0.tar.gz,
+munsell,0.4.3,https://cran.r-project.org/src/contrib/munsell_0.4.3.tar.gz,
+gtable,0.2.0,https://cran.r-project.org/src/contrib/gtable_0.2.0.tar.gz,
+htmltools,0.3.6,https://cran.r-project.org/src/contrib/htmltools_0.3.6.tar.gz,
+mime,0.5,https://cran.r-project.org/src/contrib/mime_0.5.tar.gz,
+bindr,0.1,https://cran.r-project.org/src/contrib/bindr_0.1.tar.gz,
+dichromat,2.0-0,https://cran.r-project.org/src/contrib/dichromat_2.0-0.tar.gz,
+labeling,0.3,https://cran.r-project.org/src/contrib/labeling_0.3.tar.gz,
+knitr,1.16,https://cran.r-project.org/src/contrib/knitr_1.16.tar.gz,
+evaluate,0.10.1,https://cran.r-project.org/src/contrib/evaluate_0.10.1.tar.gz,
+yaml,2.1.14,https://cran.r-project.org/src/contrib/yaml_2.1.14.tar.gz,
+memoise,1.1.0,https://cran.r-project.org/src/contrib/memoise_1.1.0.tar.gz,
+data.table,1.10.4,https://cran.r-project.org/src/contrib/data.table_1.10.4.tar.gz,
+git2r,0.19.0,https://cran.r-project.org/src/contrib/git2r_0.19.0.tar.gz,
+httr,1.2.1,https://cran.r-project.org/src/contrib/httr_1.2.1.tar.gz,
+assertthat,0.2.0,https://cran.r-project.org/src/contrib/assertthat_0.2.0.tar.gz,
+openssl,0.9.6,https://cran.r-project.org/src/contrib/openssl_0.9.6.tar.gz,
+htmlwidgets,0.9,https://cran.r-project.org/src/contrib/htmlwidgets_0.9.tar.gz,
+markdown,0.8,https://cran.r-project.org/src/contrib/markdown_0.8.tar.gz,
+readr,1.1.1,https://cran.r-project.org/src/contrib/readr_1.1.1.tar.gz,
+XML,3.98-1.9,https://cran.r-project.org/src/contrib/XML_3.98-1.9.tar.gz,
+rJava,0.9-8,https://cran.r-project.org/src/contrib/rJava_0.9-8.tar.gz,
+bitops,1.0-6,https://cran.r-project.org/src/contrib/bitops_1.0-6.tar.gz,
+base64enc,0.1-3,https://cran.r-project.org/src/contrib/base64enc_0.1-3.tar.gz,
+tidyr,0.6.3,https://cran.r-project.org/src/contrib/tidyr_0.6.3.tar.gz,
+highr,0.6,https://cran.r-project.org/src/contrib/highr_0.6.tar.gz,
+rmarkdown,1.6,https://cran.r-project.org/src/contrib/rmarkdown_1.6.tar.gz,
+httpuv,1.3.5,https://cran.r-project.org/src/contrib/httpuv_1.3.5.tar.gz,
+shiny,1.0.3,https://cran.r-project.org/src/contrib/shiny_1.0.3.tar.gz,
+caTools,1.17.1,https://cran.r-project.org/src/contrib/caTools_1.17.1.tar.gz,
+car,2.1-5,https://cran.r-project.org/src/contrib/car_2.1-5.tar.gz,
+RcppArmadillo,0.7.900.2.0,https://cran.r-project.org/src/contrib/RcppArmadillo_0.7.900.2.0.tar.gz,
+hms,0.3,https://cran.r-project.org/src/contrib/hms_0.3.tar.gz,
+zoo,1.8-0,https://cran.r-project.org/src/contrib/zoo_1.8-0.tar.gz,
+purrr,0.2.3,https://cran.r-project.org/src/contrib/purrr_0.2.3.tar.gz,
+gridExtra,2.2.1,https://cran.r-project.org/src/contrib/gridExtra_2.2.1.tar.gz,
+xtable,1.8-2,https://cran.r-project.org/src/contrib/xtable_1.8-2.tar.gz,
+sourcetools,0.1.6,https://cran.r-project.org/src/contrib/sourcetools_0.1.6.tar.gz,
+rprojroot,1.2,https://cran.r-project.org/src/contrib/rprojroot_1.2.tar.gz,
+lme4,1.1-13,https://cran.r-project.org/src/contrib/lme4_1.1-13.tar.gz,
+readxl,1.0.0,https://cran.r-project.org/src/contrib/readxl_1.0.0.tar.gz,
+mgcv,1.8-18,https://cran.r-project.org/src/contrib/mgcv_1.8-18.tar.gz,
+RcppEigen,0.3.3.3.0,https://cran.r-project.org/src/contrib/RcppEigen_0.3.3.3.0.tar.gz,
+viridisLite,0.2.0,https://cran.r-project.org/src/contrib/viridisLite_0.2.0.tar.gz,
+lubridate,1.6.0,https://cran.r-project.org/src/contrib/lubridate_1.6.0.tar.gz,
+Formula,1.2-2,https://cran.r-project.org/src/contrib/Formula_1.2-2.tar.gz,
+SparseM,1.77,https://cran.r-project.org/src/contrib/SparseM_1.77.tar.gz,
+igraph,1.1.2,https://cran.r-project.org/src/contrib/igraph_1.1.2.tar.gz,
+TTR,0.23-2,https://cran.r-project.org/src/contrib/TTR_0.23-2.tar.gz,
+boot,1.3-20,https://cran.r-project.org/src/contrib/boot_1.3-20.tar.gz,
+forecast,8.1,https://cran.r-project.org/src/contrib/forecast_8.1.tar.gz,
+quantreg,5.33,https://cran.r-project.org/src/contrib/quantreg_5.33.tar.gz,
+quantmod,0.4-10,https://cran.r-project.org/src/contrib/quantmod_0.4-10.tar.gz,
+checkmate,1.8.3,https://cran.r-project.org/src/contrib/checkmate_1.8.3.tar.gz,
+viridis,0.4.0,https://cran.r-project.org/src/contrib/viridis_0.4.0.tar.gz,
+Hmisc,4.0-3,https://cran.r-project.org/src/contrib/Hmisc_4.0-3.tar.gz,
+psych,1.7.5,https://cran.r-project.org/src/contrib/psych_1.7.5.tar.gz,
+rstudioapi,0.6,https://cran.r-project.org/src/contrib/rstudioapi_0.6.tar.gz,
+xml2,1.1.1,https://cran.r-project.org/src/contrib/xml2_1.1.1.tar.gz,
+RCurl,1.95-4.8,https://cran.r-project.org/src/contrib/RCurl_1.95-4.8.tar.gz,
+nloptr,1.0.4,https://cran.r-project.org/src/contrib/nloptr_1.0.4.tar.gz,
+gdata,2.18.0,https://cran.r-project.org/src/contrib/gdata_2.18.0.tar.gz,
+bit64,0.9-7,https://cran.r-project.org/src/contrib/bit64_0.9-7.tar.gz,
+whisker,0.3-2,https://cran.r-project.org/src/contrib/whisker_0.3-2.tar.gz,
+sp,1.2-5,https://cran.r-project.org/src/contrib/sp_1.2-5.tar.gz,
+cellranger,1.1.0,https://cran.r-project.org/src/contrib/cellranger_1.1.0.tar.gz,
+tseries,0.10-42,https://cran.r-project.org/src/contrib/tseries_0.10-42.tar.gz,
+rematch,1.0.1,https://cran.r-project.org/src/contrib/rematch_1.0.1.tar.gz,
+minqa,1.2.4,https://cran.r-project.org/src/contrib/minqa_1.2.4.tar.gz,
+xts,0.10-0,https://cran.r-project.org/src/contrib/xts_0.10-0.tar.gz,
+pbkrtest,0.4-7,https://cran.r-project.org/src/contrib/pbkrtest_0.4-7.tar.gz,
+sandwich,2.4-0,https://cran.r-project.org/src/contrib/sandwich_2.4-0.tar.gz,
+MatrixModels,0.4-1,https://cran.r-project.org/src/contrib/MatrixModels_0.4-1.tar.gz,
+RSQLite,2.0,https://cran.r-project.org/src/contrib/RSQLite_2.0.tar.gz,
diff --git a/com.oracle.truffle.r.test/src/META-INF/services/org.junit.runner.notification.RunListener b/com.oracle.truffle.r.test/src/META-INF/services/org.junit.runner.notification.RunListener
new file mode 100644
index 0000000000000000000000000000000000000000..463b9e7047c4ce75f746b4c7c5adfbda01ea5efc
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/META-INF/services/org.junit.runner.notification.RunListener
@@ -0,0 +1 @@
+com.oracle.truffle.r.test.TestBase$RunListener
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 5c89154642282ef8112e8636bce9fda6e47c3a4a..dc5be133758935e9793c7928f2c44168ad2c843e 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
@@ -235,7 +235,7 @@ Field "b":
 Error in envRefInferField(x, what, getClass(class(x)), selfEnv) :
   ‘inexistingMethod’ is not a valid field or method name for reference class “Foo13R5”
 
-##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Ignored.Unknown#
+##com.oracle.truffle.r.test.S4.TestR5.testInstanceMethods#Ignored.ImplementationError#
 #{ clazz <- setRefClass('Foo18R5', fields = c('a'), methods = list(initialize = function() a <<- 456, finalize = function() { print(sprintf('finalizer: %d', a)) } )); (function () { x <- clazz$new(); print('fun') })(); gc() }
 code for methods in class “Foo18R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 [1] "fun"
@@ -267,12 +267,12 @@ attr(,"package")
 [1] 999
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/NextMethod.R") }
+#{ source("tmptest/S4/NextMethod.R") }
 foo.bar(A, D)
 foo.bar(C, D)
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/NextMethod1.R") }
+#{ source("tmptest/S4/NextMethod1.R") }
 foo.bar(A, D)
 foo.bar(B, D)
 foo.bar(A, D)
@@ -282,7 +282,7 @@ foo.bar(A, D)
 foo.bar(B, D)
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding0.R") }
+#{ source("tmptest/S4/activeBinding0.R") }
 get
 [1] 1
 set
@@ -290,20 +290,20 @@ get
 [1] 2
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding1.R") }
+#{ source("tmptest/S4/activeBinding1.R") }
 get
 1
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding2.R") }
+#{ source("tmptest/S4/activeBinding2.R") }
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/activeBinding3.R") }
+#{ source("tmptest/S4/activeBinding3.R") }
 set
 get
 [1] 3
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/dispatch.R") }
+#{ source("tmptest/S4/dispatch.R") }
 Creating a generic function from function ‘foo.bar’ in the global environment
 [1] 1
 [1] 2
@@ -312,7 +312,7 @@ Creating a generic function from function ‘foo.bar’ in the global environmen
 [1] "primitive, B, A"
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#Output.IgnoreErrorContext#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses0.R") }
+#{ source("tmptest/S4/refClasses0.R") }
 Error : invalid assignment for reference class field ‘aa’, should be from class “integer” or a subclass (was class “character”)
 code for methods in class “myRefClass3” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 Error : invalid assignment for reference class field ‘dd’, should be from class “numeric” or a subclass (was class “character”)
@@ -321,13 +321,13 @@ code for methods in class “myRefClass5” was not checked for suspicious field
 code for methods in class “myRefClass6” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses1.R") }
+#{ source("tmptest/S4/refClasses1.R") }
 code for methods in class “A5R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 code for methods in class “B5R5” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 [1] "A5R5$foo"
 
 ##com.oracle.truffle.r.test.S4.TestS4.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/S4/R/refClasses2.R") }
+#{ source("tmptest/S4/refClasses2.R") }
 code for methods in class “MatrixClass” was not checked for suspicious field assignments (recommended package ‘codetools’ not available?)
 
 ##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#
@@ -363,7 +363,7 @@ NULL
 Error in makeActiveBinding("someSymbol6", function(x) { :
   cannot change active binding if binding is locked
 
-##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#Ignored.Unknown#
+##com.oracle.truffle.r.test.S4.TestS4.testActiveBindings#Ignored.ImplementationError#
 #makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get0') else print('set0') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1; makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get1') else print('set1') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1
 [1] "get0"
 [1] "set0"
@@ -1012,17 +1012,17 @@ Error in Encoding(x) : a character vector argument expected
 #argv <- list('Byte Code Compiler'); .Internal(Encoding(argv[[1]]))
 [1] "unknown"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding2#Ignored.ImplementationError#
 #argv <- list(c('\n', '\n', '## These cannot be run by examples() but should be OK when pasted\n', '## into an interactive R session with the tcltk package loaded\n', '\n', 'tt <- tktoplevel()\n', 'tkpack(txt.w <- tktext(tt))\n', 'tkinsert(txt.w, \'0.0\', \'plot(1:10)\')\n', '\n', '# callback function\n', 'eval.txt <- function()\n', '   eval(parse(text = tclvalue(tkget(txt.w, \'0.0\', \'end\'))))\n', 'tkpack(but.w <- tkbutton(tt, text = \'Submit\', command = eval.txt))\n', '\n', '## Try pressing the button, edit the text and when finished:\n', '\n', 'tkdestroy(tt)\n', '\n', '\n')); .Internal(Encoding(argv[[1]]))
  [1] "unknown" "unknown" "unknown" "unknown" "unknown" "unknown" "unknown"
  [8] "unknown" "unknown" "unknown" "unknown" "unknown" "unknown" "unknown"
 [15] "unknown" "unknown" "unknown" "unknown" "unknown"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding3#Ignored.ImplementationError#
 #argv <- list('detaching ‘package:nlme’, ‘package:splines’'); .Internal(Encoding(argv[[1]]))
 [1] "UTF-8"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding4#Ignored.ReferenceError#
 #argv <- list(structure(character(0), class = 'check_code_usage_in_package')); .Internal(Encoding(argv[[1]]))
 character(0)
 
@@ -1034,7 +1034,7 @@ character(0)
 #argv <- list('A shell of class documentation has been written to the file ./myTst2/man/DocLink-class.Rd.\n'); .Internal(Encoding(argv[[1]]))
 [1] "unknown"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Encoding.testEncoding7#Ignored.ImplementationError#
 #argv <- list(c('* Edit the help file skeletons in man, possibly combining help files for multiple functions.', '* Edit the exports in NAMESPACE, and add necessary imports.', '* Put any C/C++/Fortran code in src.', '* If you have compiled code, add a useDynLib() directive to NAMESPACE.', '* Run R CMD build to build the package tarball.', '* Run R CMD check to check the package tarball.', '', 'Read Writing R Extensions for more information.')); .Internal(Encoding(argv[[1]]))
 [1] "unknown" "unknown" "unknown" "unknown" "unknown" "unknown" "unknown"
 [8] "unknown"
@@ -1847,26 +1847,30 @@ character(0)
 #argv <- structure(list(TZ = 'EST5EDT'), .Names = 'TZ');do.call('Sys.setenv', argv)
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocale1#
-#argv <- list(3L, 'C'); .Internal(Sys.setlocale(argv[[1]], argv[[2]]))
-[1] "C"
+#argv <- list(3L, 'C'); Sys.setlocale(argv[[1]], argv[[2]])
+Error in Sys.setlocale(argv[[1]], argv[[2]]) :
+  invalid 'category' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocale3#
 #argv <- structure(list(category = 'LC_TIME', locale = 'C'), .Names = c('category',     'locale'));do.call('Sys.setlocale', argv)
 [1] "C"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#Output.IgnoreErrorMessage#
-#.Internal(Sys.setlocale('3L', 'C'))
-Error: invalid 'category' argument
-In addition: Warning message:
-NAs introduced by coercion
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocale3#
+#{ Sys.setenv(LC_CTYPE="en_US.UTF-8"); Sys.getlocale("LC_CTYPE"); }
+[1] "en_US.UTF-8"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#
-#.Internal(Sys.setlocale(4, 42))
-Error: invalid 'locale' argument
+#Sys.setlocale('3L', 'C')
+Error in Sys.setlocale("3L", "C") : invalid 'category' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#
-#.Internal(Sys.setlocale(4, c('more', 'elements')))
-Error: invalid 'locale' argument
+#Sys.setlocale(4, 42)
+Error in Sys.setlocale(4, 42) : invalid 'category' argument
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssetlocale.testSyssetlocaleInvalidArgs#
+#Sys.setlocale(4, c('more', 'elements'))
+Error in Sys.setlocale(4, c("more", "elements")) :
+  invalid 'category' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_Syssleep.testSyssleep1#
 #argv <- list(0.5); .Internal(Sys.sleep(argv[[1]]))
@@ -3085,7 +3089,7 @@ In anyDuplicated.default(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = "cat") :
 #argv <- list(c('1', '4', '6', '9', '11', NA, '15', '16', '17', '20', '21', '23', '29', '41', '45', '48', '55', '62', '63', '65', '70', '74', '82', '83', '85', '86', '92', '93', '97', '98', '99', '103', '104', '106', '108', '109', '112', '113', '120', '126', '127', '128', '132', '139', '142', '145', '148', '151', '159', '164', '165', '169', '171', '173', '175', '189', '191', '193', '194', '195', '198', '200', '202', '209', '212', '213', '215', '216', '221', '223', '224', '227'), FALSE, FALSE); .Internal(anyDuplicated(argv[[1]], argv[[2]], argv[[3]]))
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testanyDuplicated18#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicated.testanyDuplicated18#
 #argv <- structure(list(x = structure(c(3, 2, 7, 2, 6, 2, 7, 2),     .Dim = c(4L, 2L), .Dimnames = list(c('A', 'B', 'C', 'D'),         c('M', 'F'))), MARGIN = 0), .Names = c('x', 'MARGIN'));do.call('anyDuplicated', argv)
 [1] 4
 
@@ -3129,7 +3133,7 @@ In anyDuplicated.default(c(1L, 2L, 1L, 1L, 3L, 2L), incomparables = "cat") :
 #argv <- structure(list(x = c(1, NA, 3, NA, 3), incomparables = c(3,     NA)), .Names = c('x', 'incomparables'));do.call('anyDuplicated.default', argv)
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicatedmatrix.testanyDuplicatedmatrix1#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_anyDuplicatedmatrix.testanyDuplicatedmatrix1#
 #argv <- structure(list(x = structure(c(3, 2, 7, 2, 6, 2, 7, 2),     .Dim = c(4L, 2L), .Dimnames = list(c('A', 'B', 'C', 'D'),         c('M', 'F'))), MARGIN = 0), .Names = c('x', 'MARGIN'));do.call('anyDuplicated.matrix', argv)
 [1] 4
 
@@ -3296,7 +3300,11 @@ Error in aperm.default(c(1, 2, 3)) :
 Error in aperm.default(c(c(2, 3), c(4, 5), c(6, 7)), c(3, 4)) :
   invalid first argument, must be an array
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm1#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testApermAttrs#
+#{ a<-array(1:24, c(2,3,4), dimnames=list(x=c('x1','x2'),y=c('y1','y2','y3'),z=c('z1','z2','z3','z4'))); b<-aperm(a,c(3,1,2)); a; b; dimnames(b)$x[1]<-'c'; dimnames(a)$x; }
+[1] "x1" "x2"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm1#Output.IgnoreWhitespace#
 #argv <- list(structure(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Dim = c(5L, 14L), .Dimnames = list(c('#ifdef', '\\Sexpr', 'build', 'install', 'render'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
       #ifdef \\Sexpr build install render
  [1,]  FALSE   FALSE FALSE   FALSE  FALSE
@@ -3314,7 +3322,7 @@ Error in aperm.default(c(c(2, 3), c(4, 5), c(6, 7)), c(3, 4)) :
 [13,]  FALSE   FALSE FALSE   FALSE  FALSE
 [14,]  FALSE   FALSE FALSE   FALSE  FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm10#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm10#
 #argv <- list(structure(c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), .Dim = c(4L, 4L, 2L), .Dimnames = structure(list(Hair = c('Black', 'Brown', 'Red', 'Blond'), Eye = c('Brown', 'Blue', 'Hazel', 'Green'), Sex = c('Male', 'Female')), .Names = c('Hair', 'Eye', 'Sex')), class = 'table'), c(3L, 1L, 2L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
 , , Eye = Brown
 
@@ -3359,7 +3367,7 @@ Sex      Black Brown Red Blond
 [2,]    0 -0.5   NA
 [3,]   -1   NA    0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm13#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm13#
 #argv <- list(structure(c('    Null deviance:', 'Residual deviance:', '3.118557', '0.012672', ' on', ' on', '8', '7', ' degrees of freedom\n', ' degrees of freedom\n'), .Dim = c(2L, 5L), .Dimnames = list(c('null.deviance', 'deviance'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
      null.deviance           deviance
 [1,] "    Null deviance:"    "Residual deviance:"
@@ -3385,7 +3393,7 @@ Sex      Black Brown Red Blond
 [3,]
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm15#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm15#Output.IgnoreWhitespace#
 #argv <- list(structure(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Dim = c(5L, 20L), .Dimnames = list(c('#ifdef', '\\Sexpr', 'build', 'install', 'render'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
       #ifdef \\Sexpr build install render
  [1,]  FALSE   FALSE FALSE   FALSE  FALSE
@@ -3447,7 +3455,7 @@ Sex      Black Brown Red Blond
 #argv <- list(structure(c(NA, NA, NA), .Dim = 3L), 1L, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
 [1] NA NA NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm19#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm19#
 #argv <- list(structure(c(4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 4000, 8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000, 96000, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 12000, 24000, 36000, 48000, 60000, 72000, 84000, 96000, 108000, 120000, 132000, 144000, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 16000, 32000, 48000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 20000, 40000, 60000, 80000, 1e+05, 120000, 140000, 160000, 180000, 2e+05, 220000, 240000, 24, 48, 72, 96, 120, 144, 168, 192, 216, 240, 264, 288, 24000, 48000, 72000, 96000, 120000, 144000, 168000, 192000, 216000, 240000, 264000, 288000, 28, 56, 84, 112, 140, 168, 196, 224, 252, 280, 308, 336, 28000, 56000, 84000, 112000, 140000, 168000, 196000, 224000, 252000, 280000, 308000, 336000, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 36, 72, 108, 144, 180, 216, 252, 288, 324, 360, 396, 432, 36000, 72000, 108000, 144000, 180000, 216000, 252000, 288000, 324000, 360000, 396000, 432000, 40, 80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 40000, 80000, 120000, 160000, 2e+05, 240000, 280000, 320000, 360000, 4e+05, 440000, 480000, 44, 88, 132, 176, 220, 264, 308, 352, 396, 440, 484, 528, 44000, 88000, 132000, 176000, 220000, 264000, 308000, 352000, 396000, 440000, 484000, 528000, 48, 96, 144, 192, 240, 288, 336, 384, 432, 480, 528, 576, 48000, 96000, 144000, 192000, 240000, 288000, 336000, 384000, 432000, 480000, 528000, 576000, 52, 104, 156, 208, 260, 312, 364, 416, 468, 520, 572, 624, 52000, 104000, 156000, 208000, 260000, 312000, 364000, 416000, 468000, 520000, 572000, 624000, 56, 112, 168, 224, 280, 336, 392, 448, 504, 560, 616, 672, 56000, 112000, 168000, 224000, 280000, 336000, 392000, 448000, 504000, 560000, 616000, 672000, 60, 120, 180, 240, 300, 360, 420, 480, 540, 600, 660, 720, 60000, 120000, 180000, 240000, 3e+05, 360000, 420000, 480000, 540000, 6e+05, 660000, 720000, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 64000, 128000, 192000, 256000, 320000, 384000, 448000, 512000, 576000, 640000, 704000, 768000, 68, 136, 204, 272, 340, 408, 476, 544, 612, 680, 748, 816, 68000, 136000, 204000, 272000, 340000, 408000, 476000, 544000, 612000, 680000, 748000, 816000, 72, 144, 216, 288, 360, 432, 504, 576, 648, 720, 792, 864, 72000, 144000, 216000, 288000, 360000, 432000, 504000, 576000, 648000, 720000, 792000, 864000, 76, 152, 228, 304, 380, 456, 532, 608, 684, 760, 836, 912, 76000, 152000, 228000, 304000, 380000, 456000, 532000, 608000, 684000, 760000, 836000, 912000, 80, 160, 240, 320, 400, 480, 560, 640, 720, 800, 880, 960, 80000, 160000, 240000, 320000, 4e+05, 480000, 560000, 640000, 720000, 8e+05, 880000, 960000, 84, 168, 252, 336, 420, 504, 588, 672, 756, 840, 924, 1008, 84000, 168000, 252000, 336000, 420000, 504000, 588000, 672000, 756000, 840000, 924000, 1008000, 88, 176, 264, 352, 440, 528, 616, 704, 792, 880, 968, 1056, 88000, 176000, 264000, 352000, 440000, 528000, 616000, 704000, 792000, 880000, 968000, 1056000, 92, 184, 276, 368, 460, 552, 644, 736, 828, 920, 1012, 1104, 92000, 184000, 276000, 368000, 460000, 552000, 644000, 736000, 828000, 920000, 1012000, 1104000, 96, 192, 288, 384, 480, 576, 672, 768, 864, 960, 1056, 1152, 96000, 192000, 288000, 384000, 480000, 576000, 672000, 768000, 864000, 960000, 1056000, 1152000), .Dim = c(3L, 4L, 2L, 3L, 4L, 2L), .Dimnames = list(c('A', 'B', 'C'), c('D', 'E', 'F', 'G'), c('frequentist', 'bayesian'), NULL, NULL, c('happy', 'sad'))), c(4L, 1L, 5L, 2L, 6L, 3L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
 , , 1, D, happy, frequentist
 
@@ -3949,7 +3957,7 @@ Sex      Black Brown Red Blond
 [2,] "default" "default" "default"
 [3,] NA        NA        NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm20#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm20#
 #argv <- list(structure(1:24, .Dim = c(4L, 6L), .Dimnames = structure(list(happy = c('a', 'b', 'c', 'd'), sad = c('A', 'B', 'C', 'D', 'E', 'F')), .Names = c('happy', 'sad'))), c(2, 1), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
    happy
 sad  a  b  c  d
@@ -3960,7 +3968,7 @@ sad  a  b  c  d
   E 17 18 19 20
   F 21 22 23 24
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm21#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm21#
 #argv <- list(structure(1:120, .Dim = 2:5, .Dimnames = list(NULL, c('a', 'b', 'c'), NULL, c('V5', 'V6', 'V7', 'V8', 'V9'))), 1:4, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
 , , 1, V5
 
@@ -4083,7 +4091,7 @@ sad  a  b  c  d
 [2,] 116 118 120
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm22#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm22#
 #argv <- list(structure(c('    Null deviance:', 'Residual deviance:', '67.5316', ' 4.5512', ' on', ' on', '9', '7', ' degrees of freedom\n', ' degrees of freedom\n'), .Dim = c(2L, 5L), .Dimnames = list(c('null.deviance', 'deviance'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
      null.deviance           deviance
 [1,] "    Null deviance:"    "Residual deviance:"
@@ -4097,13 +4105,13 @@ sad  a  b  c  d
       [,1]  [,2]  [,3]
 [1,] FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm24#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm24#
 #argv <- list(structure(c(3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 2, 3, 4, 5), .Dim = c(8L, 2L), .Dimnames = list(c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), c('x1', 'x2'))), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
    a b c d e f g h
 x1 3 3 3 3 3 3 3 3
 x2 4 3 2 1 2 3 4 5
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm25#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm25#
 #argv <- list(structure(c(0, 1.23517986278748, 1.95771376416406, 2.47035972557496, 2.86799882564536, 3.19289362695154, 3.46758826742286, 3.70553958836244, 3.91542752832811, 4.10317868843284, 4.27302027203108, 4.42807348973901, 4.57070862330685, 4.70276813021034, 4.82571258980942, 4.94071945114991, 5.04875179140451, 5.15060739111559, 5.2469545231864, 5.33835855122032, 5.42530203158692, 5.50820013481856, 5.58741263619316, 5.66325335252649, 5.73599765129073, 5.80588848609433, 5.87314129249217, 5.93794799299782, 6.00048029898585, 6.0608924525969, 6.11932351888589, 6.17589931393739, 6.23073403619514, 6.28393165419199, 6.33558709306823, 6.38578725390307, 6.43461189335533, 6.48213438597388, 6.52842238747091, 6.5735384140078, 6.61754034994095, 6.6604818943744, 6.70241295516147, 6.74337999760604, 6.78342635397348, 6.82259249898064, 6.86091629565604, 6.89843321531397, 6.93517653484573, 6.97117751407821, 7.00646555556857, 7.04106834888181, 7.07501200112497, 7.10832115527965, 7.14101909767645, 7.1731278557853, 7.20466828735046, 7.23566016177333, 7.26612223453848, 7.29607231538438, 7.3255273308395, 7.35450338167337, 7.38301579575098, 7.41107917672487, 7.43870744895221, 7.46591389898262, 7.49271121392624, 7.51911151697947, 7.54512640035722, 7.57076695585571, 7.59604380324749, 7.62096711669055, 7.64554664931599, 7.66979175614282, 7.69371141545478, 7.71731424876136, 7.74060853945395, 7.76360225025839, 7.78630303957574, 7.80871827679528, 7.83085505665623, 7.85272021272842, 7.87432033007586, 7.89566175716188, 7.91675061704988, 7.93759281794895, 7.95819406314991, 7.97855986039352, 7.99869553070936, 8.01860621676096, 8.03829689072971, 8.05777236176812, 8.07703728304995, 8.09609615844352, 8.11495334883177, 8.13361307810145, 8.15207943882202, 8.17035639763321, 8.1884478003592, 8.20635737686569, 5.76558893216369, 5.5342688729893, 5.69366159038267, 6.17674775070929, 6.08762735966107, 6.68653280779044, 6.70253591217234, 6.32938323618963, 6.81735284786279, 6.64835766778347, 6.91213030655848, 7.1496842781073, 7.25682341590407, 7.46164094256645, 7.37149913131863, 7.56470707593246, 7.71334191900841, 7.71375128844693, 7.82793409372511, 7.90749319121623, 7.96255733207686, 8.11381187364273, 8.21211505208663, 8.18427543602736, 8.29133399017863, 8.31295002652197, 8.345677476918, 8.39053879616249, 8.40857122007675, 8.48086068897741, 8.7064475146364, 8.66563269607315, 8.79435721712053, 8.7996087849725, 8.82443395257555, 8.91314507957224, 8.8999544270272, 8.96760168103462, 8.93548690078514, 9.01332239000153, 9.07083338712431, 9.15422051683385, 9.20109302097792, 9.2062218972166, 9.31170984199071, 9.30909253379462, 9.35447695163181, 9.45333740615033, 9.41458248768079, 9.46983861007334, 9.51652628670815, 9.5301888386762, 9.59497468213833, 9.61268143770055, 9.64141492393412, 9.68857453461133, 9.77580537125637, 9.79816256416163, 9.79128849346381, 9.80699184934282, 9.91833626833319, 9.95487179604373, 9.88086373278725, 9.93505313047982, 9.97034080826287, 9.97752630228797, 10.1165750634827, 10.0977558023188, 10.1414502841663, 10.129071787117, 10.166774063688, 10.1792762662323, 10.2172491181904, 10.2670710204409, 10.2742314938915, 10.287876622612, 10.3447249333494, 10.4075370351282, 10.3465199067119, 10.4404223214255, 10.422301774768, 10.4739543513507, 10.5314461891317, 10.4813429169605, 10.5097541699286, 10.5389544549716, 10.5752633644781, 10.6133054015308, 10.6776080133421, 10.6266190058322, 10.6657950921482, 10.7067723709738, 10.7424707425861, 10.7418659657784, 10.7335163259687, 10.780101845273, 10.8334343829096, 10.8616735406708, 10.8535694508523, 10.8900668188725), .Dim = c(100L, 2L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100'), c('log(x)', 'log(z)'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
       log(x)    log(z)
 1   0.000000  5.765589
@@ -4207,7 +4215,7 @@ x2 4 3 2 1 2 3 4 5
 99  8.188448 10.853569
 100 8.206357 10.890067
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm27#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm27#
 #argv <- structure(list(a = structure(c(0.124248979591837, 0.266432653061224,     0.404342857142857, 0.0992163265306122, 0.0851836734693878,     0.0937632653061225, 0.0163551020408163, 0.182897959183673,     0.303289795918367, 0.010330612244898, 0.0557795918367347,     0.0490938775510204, 0.0992163265306122, 0.0851836734693878,     0.0937632653061225, 0.143689795918367, 0.098469387755102,     0.104004081632653, 0.0116979591836735, 0.0826530612244898,     0.0713795918367347, 0.00929795918367347, 0.0412040816326531,     0.0476285714285714, 0.0163551020408163, 0.182897959183673,     0.303289795918367, 0.0116979591836735, 0.0826530612244898,     0.0713795918367347, 0.0301591836734694, 0.220816326530612,     0.304587755102041, 0.00606938775510204, 0.0731020408163265,     0.0488244897959184, 0.010330612244898, 0.0557795918367347,     0.0490938775510204, 0.00929795918367347, 0.0412040816326531,     0.0476285714285714, 0.00606938775510204, 0.0731020408163265,     0.0488244897959184, 0.0111061224489796, 0.0391061224489796,     0.0754326530612245), .Dim = c(3L, 4L, 4L), .Dimnames = structure(list(Species = c('setosa',     'versicolor', 'virginica'), c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width'), c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width')), .Names = c('Species', '',     ''))), perm = c(2, 3, 1)), .Names = c('a', 'perm'));do.call('aperm', argv)
 , , Species = setosa
 
@@ -4250,19 +4258,19 @@ x2 4 3 2 1 2 3 4 5
  [8,] 0.6666667
  [9,] 0.6666667
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm4#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm4#
 #argv <- list(structure(c(0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L), .Dim = c(1L, 8L), .Dimnames = list('strata(enum)', c('rx', 'size', 'number', 'strata(enum)', 'cluster(id)', 'rx:strata(enum)', 'size:strata(enum)', 'number:strata(enum)'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
              rx size number strata(enum) cluster(id) rx:strata(enum)
 strata(enum)  0    0      0            1           0               1
              size:strata(enum) number:strata(enum)
 strata(enum)                 1                   1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm5#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm5#
 #argv <- list(structure(c(9.2319289524956, -0.470372045488369, 186.857050189827), .Dim = c(1L, 3L), .Dimnames = list('118', c('age', 'sex', 'meal.cal'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
          age       sex meal.cal
 118 9.231929 -0.470372 186.8571
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm6#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm6#
 #argv <- list(structure(c(414L, 439L, 382L, 388L, 383L, 364L, 364L, 363L, 349L, 371L, 102L, 388L, 388L, 363L, 367L, 365L, 382L, 362L, 373L, 385L, 376L, 360L, 306L, 160L, 316L, 316L, 315L, 357L, 360L, 347L, 353L, 308L, 327L, 329L, 343L, 251L, 318L, 304L, 316L, 335L, 365L, 336L, 350L, 356L, 339L, 301L, 330L, 300L, 300L, 312L, 334L, 270L, 347L, 293L, 303L, 337L, 287L, 293L, 293L, 318L, 359L, 351L, 322L, 343L, 269L, 286L, 286L, 273L, 297L, 273L, 273L, 273L, 294L, 303L, 281L, 273L, 255L, 269L, 270L, 270L, 276L, 264L, 245L, 261L, 270L, 273L, 306L, 274L, 279L, 278L, 278L, 284L, 276L, 265L, 294L, 277L, 259L, 287L, 263L, 240L, 217L, 271L, 252L, 331L, 255L, 271L, 254L, 185L, 213L, 210L, 203L, 288L, 269L, 269L, 91L, 91L, 192L, 199L, 195L, 198L, 207L, 200L, 197L, 243L, 203L, 197L, 227L, 227L, 219L, 8L, NA, NA, 246L, NA, 292L, NA, 294L, NA, 19L, 373L, NA, 211L, 82L, NA, 334L, 18L, NA, 280L, NA, NA, NA, NA, 146L, NA, NA, NA, 267L, 206L, 175L, NA, NA, NA, NA, 118L, NA, NA, NA, NA, 274L, NA, NA, 187L, NA, 6L, NA, NA, 146L, 304L, NA, 52L, 67L, NA, 265L, NA, 91L, NA, NA, NA, 318L, 57L, 226L, 65L, NA, 264L, NA, NA, NA, 236L, NA, 207L, NA, NA, NA, NA, NA, NA, 23L, NA, NA, NA, NA, NA, NA, 113L, 99L, NA, NA, 14L, NA, NA, NA, NA, NA, NA, NA, 4L, NA, 167L, NA, NA, NA, NA, NA, NA, NA, NA, NA, 165L, NA, NA, NA, NA, NA, NA, NA, NA, 11L, NA, NA, 168L, NA, NA, 120L, NA, 104L, NA, 373L, 26L, NA, NA, 253L, NA, NA, NA, NA, NA, NA, NA, NA, 260L, 114L, NA, 370L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 280L, NA, NA, NA, NA, 240L, NA, NA, NA, NA, 361L, NA, NA, NA, NA, NA, NA, NA, 188L, NA, NA, 65L, 248L, NA, NA, NA, 121L, NA, NA, NA, NA, 121L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 306L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 159L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 22L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 152L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 265L, 337L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 255L, 250L, NA, NA, NA, 203L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 213L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 169L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 241L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 269L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 284L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 249L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 307L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 322L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 350L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), .Dim = c(128L, 8L), .Dimnames = list(    NULL, c('futime', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7'))), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
        [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
 futime  414  439  382  388  383  364  364  363  349   371   102   388   388
@@ -4383,7 +4391,7 @@ e7         NA
 [5,]  -10    0  180    0    0    0  340  380
 [6,]    0    0    0    0    0    0    0    0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm8#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aperm.testaperm8#
 #argv <- list(structure(c(544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 1539.44739946315, 1548.66655077773, 1557.88570209231, 1566.45228027983, 1575.01885846735, 1583.14083472285, 1591.26281097836, 1599.26100149451, 1607.25919201066, 1611.39689466313, 1615.5345973156, 1612.61129444623, 1609.68799157686, 1603.44643859537, 1597.20488561388, 1588.73002343463, 1580.25516125537, 1570.86127478964, 1561.46738832392, 1549.89535441445, 1538.32332050498, 1524.62526591843, 1510.92721133189, 1499.65830819836, 1488.38940506483, 1479.31388700637, 1470.23836894792, 1460.03887936132, 1449.83938977473, 1441.27547309544, 1432.71155641615, 1432.51830671501, 1432.32505701387, 1433.15763708544, 1433.99021715701, 1434.96142536256, 1435.9326335681, 1435.47421580154, 1435.01579803498, 1433.4368629411, 1431.85792784722, 1430.85617066215, 1429.85441347709, 1432.59097206397, 1435.32753065085, 1440.49425642708, 1445.66098220331, 1448.76676550395, 1451.87254880459, 1452.9163236715, 1453.96009853841, 1454.6961768366, 1455.43225513478, 1452.22362902495, 1449.01500291512, 1442.43484036078, 1435.85467780644, 1426.50159512644, 1417.14851244644, 1409.58997614642, 1402.0314398464, 1397.59624058751, 1393.16104132862, 1386.64426440334, 1380.12748747807, 1371.71107833433, 1363.2946691906, 1354.59002807904, 1345.88538696748, 1336.94914699242, 1328.01290701735, 1318.64960669271, 49.7622186359663, -84.1535032467218, -121.764781099341, 37.2870304782966, 82.528433600382, -44.2319392670254, 25.3010406627996, -34.7698782399993, 48.5709781995188, 110.301655093951, -1.96962838525201, -3.7990131710535, -51.4783734777507, 135.066608935635, 114.916035379091, -28.990712676497, -11.7078691876363, 7.04762066618673, -38.9035366827579, 16.5957688400649, -38.4931502947952, 52.0732838386475, 26.6377575984557, 329.153973076816, -13.1797869657194, 872.199160524634, 371.882552045056, -254.299568603192, -95.2920977069916, 8.63342236039193, 16.852295225008, -29.0271834604991, 13.5051131963112, 4.54091267164154, 25.5747517733375, 386.850855912621, 259.276984531009, -199.961168270532, -153.894877042003, 94.302447817031, -20.3106357794875, 21.0527247936745, -6.29056183593116, 13.9001511905426, -29.4973604406664, -31.7957066699985, -224.096013272965, -30.9544842287708, 22.3370692945275, 432.596723859509, 47.1608224545594, -304.956866078466, 50.1150369329559, 24.6852664308792, -14.4511512739648, -4.94371710626865, -19.024507596255, -56.8030453693573, -314.583543516094, 165.222305128756, 316.17817825271, 23.9168069434991, 11.9598796643579, -128.904953645213, 0.419804589665318, -6.80218287850425, 29.2691824505584, 53.9010951754703, 40.9447832426993, -26.2505972353374, -41.4479380870087, -214.837325417531, 2134, 1863, 1877, 1877, 1492, 1249, 1280, 1131, 1209, 1492, 1621, 1846, 2103, 2137, 2153, 1833, 1403, 1288, 1186, 1133, 1053, 1347, 1545, 2066, 2020, 2750, 2283, 1479, 1189, 1160, 1113, 970, 999, 1208, 1467, 2059, 2240, 1634, 1722, 1801, 1246, 1162, 1087, 1013, 959, 1179, 1229, 1655, 2019, 2284, 1942, 1423, 1340, 1187, 1098, 1004, 970, 1140, 1110, 1812, 2263, 1820, 1846, 1531, 1215, 1075, 1056, 975, 940, 1081, 1294, 1341), .Dim = c(72L, 4L), .Dimnames = list(NULL, c('STL.seasonal', 'STL.trend', 'STL.remainder', 'data')), .Tsp = c(1974, 1979.91666666667, 12), class = c('mts', 'ts', 'matrix')), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))
       STL.seasonal STL.trend STL.remainder data
  [1,]   544.790382  1539.447    49.7622186 2134
@@ -4597,7 +4605,7 @@ dr
   49   50   51   52   53   54   55   56   57   58 59.5
    1    1    1    1    1    1    1    1    1    1    2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testarray10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_array.testarray10#Output.IgnoreWhitespace#
 #argv <- list(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), c(5L, 16L), list(c('#ifdef', '\\Sexpr', 'build', 'install', 'render'), NULL)); .Internal(array(argv[[1]], argv[[2]], argv[[3]]))
          [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9] [,10] [,11] [,12]
 #ifdef  FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
@@ -5747,6 +5755,10 @@ character(0)
 a b
 1 2
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#
+#typeof(as.call(list(substitute(graphics::par))))
+[1] "language"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascall.testAsCall#
 #{ as.call(42) }
 Error in as.call(42) : invalid argument list
@@ -5854,6 +5866,10 @@ character(0)
 #{ as.character(list(list(c("hello", "hi")))) }
 [1] "list(c(\"hello\", \"hi\"))"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter#
+#{ as.character.cls <- function(x) 42; as.character(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascharacter.testAsCharacter#
 #{ f1<-function() 7; f2<-function(x) { sys.call() }; as.character(f2(f1())) }
 [1] "f2"   "f1()"
@@ -6269,6 +6285,10 @@ NAs introduced by coercion
 #{ as.complex(list(NULL)) }
 Error: (list) object cannot be coerced to type 'complex'
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex#
+#{ as.complex.cls <- function(x) 42; as.complex(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ascomplex.testAsComplex#
 #{ x<-c(a=1.1, b=2.2); dim(x)<-c(1,2); attr(x, "foo")<-"foo"; y<-as.complex(x); attributes(y) }
 NULL
@@ -6336,17 +6356,17 @@ q1.csv      0.8333333 0.5000000 0.1666667
 q2.csv      1.0000000 0.6666667 0.0000000
 q3.csv      0.3333333 0.6666667 0.5000000
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asdataframetable.testasdataframetable1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdataframetable.testasdataframetable1#
 #argv <- structure(list(x = structure(integer(0), .Dim = 0L, .Dimnames = structure(list(NULL),     .Names = ''), class = 'table')), .Names = 'x');do.call('as.data.frame.table', argv)
 [1] Freq
 <0 rows> (or 0-length row.names)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asdifftime.testasdifftime1#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdifftime.testasdifftime1#
 #argv <- structure(list(tim = c('0:3:20', '11:23:15')), .Names = 'tim');do.call('as.difftime', argv)
 Time differences in mins
 [1]   3.333333 683.250000
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asdifftime.testasdifftime2#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdifftime.testasdifftime2#
 #argv <- structure(list(tim = c('3:20', '23:15', '2:'), format = '%H:%M'),     .Names = c('tim', 'format'));do.call('as.difftime', argv)
 Time differences in hours
 [1]  3.333333 23.250000        NA
@@ -6395,6 +6415,10 @@ NAs introduced by coercion
 Warning message:
 imaginary parts discarded in coercion
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
+#{ as.double.cls <- function(x) 42; as.double(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testAsDouble#
 #{ x<-c(a=1.1, b=2.2); dim(x)<-c(1,2); attr(x, "foo")<-"foo"; y<-as.double(x); attributes(y) }
 NULL
@@ -6467,7 +6491,7 @@ numeric(0)
 [149] 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 4 4 4 4 4 4 4 4 4 4 4 4 4 5 5 5 5 5 5 5 5 5
 [186] 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble16#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble16#
 #argv <- list(structure(28, units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);
 [1] 2419200
 
@@ -6508,7 +6532,7 @@ numeric(0)
  [1] 9.9e-03 9.9e-02 9.9e-01 9.9e+00 9.9e+01 9.9e+02 9.9e+03 9.9e+04 9.9e+05
 [10] 9.9e+06 9.9e+07 9.9e+08 9.9e+09 9.9e+10
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble19#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble19#
 #argv <- list(structure(180.958333333333, units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);
 [1] 15634800
 
@@ -6558,7 +6582,7 @@ numeric(0)
  [1]   9.000   3.000   3.000   6.761 156.678  18.327  11.764 191.640 323.560
 [10] 197.210 190.640
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble3#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asdouble.testasdouble3#
 #argv <- list(structure(4, tzone = 'GMT', units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);
 [1] 345600
 
@@ -6926,6 +6950,10 @@ imaginary parts discarded in coercion
 #{ as.integer(list(list(1),2,3)) }
 [1] NA  2  3
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger#
+#{ as.integer.cls <- function(x) 42; as.integer(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testAsInteger#
 #{ x<-c(a=1.1, b=2.2); dim(x)<-c(1,2); attr(x, "foo")<-"foo"; y<-as.integer(x); attributes(y) }
 NULL
@@ -6942,7 +6970,7 @@ NULL
 #argv <- list(c('1', NA, '0'));as.integer(argv[[1]]);
 [1]  1 NA  0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testasinteger11#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testasinteger11#Ignored.ImplementationError#
 #argv <- list(c('3', '14159265358979'));as.integer(argv[[1]]);
 [1]  3 NA
 Warning message:
@@ -7005,7 +7033,7 @@ NAs introduced by coercion to integer range
 [551]  4  4  2  4  4  4  4  3  2  3  3  2 NA  3  4  4  3  3  4  4  4  1  4  4  4
 [576]  4  4  4  4  2  4  2  3  4  1  3  1 NA  4  1  2  2  1  4  3  3  4  1  1  3
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testasinteger2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testasinteger2#Ignored.ImplementationError#
 #argv <- list(c('   33', '   34', '   35', '   36', '   37', '   38', '   18', '   19', '   20', '   21', '   22', '   23', '   36', '   37', '   38', '   39'));as.integer(argv[[1]]);
  [1] 33 34 35 36 37 38 18 19 20 21 22 23 36 37 38 39
 
@@ -7013,7 +7041,7 @@ NAs introduced by coercion to integer range
 #argv <- list(39);as.integer(argv[[1]]);
 [1] 39
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testasinteger3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asinteger.testasinteger3#Ignored.ImplementationError#
 #argv <- list(c(-Inf, -8.5, -2.83333333333333, -1.41666666666667, -0.85, -0.566666666666666, -0.404761904761905, -0.303571428571428, -0.236111111111111, -0.188888888888889));as.integer(argv[[1]]);
  [1] NA -8 -2 -1  0  0  0  0  0  0
 Warning message:
@@ -7095,6 +7123,10 @@ logical(0)
 #{ as.logical(c(3+3i, 4+4i)) }
 [1] TRUE TRUE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_aslogical.testAsLogical#
+#{ as.logical.cls <- function(x) 42; as.logical(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_aslogical.testAsLogical#
 #{ x<-c(a=1.1, b=2.2); dim(x)<-c(1,2); attr(x, "foo")<-"foo"; y<-as.logical(x); attributes(y) }
 NULL
@@ -7541,6 +7573,10 @@ out-of-range values treated as 0 in coercion to raw
 #{ as.raw(list(1,2,3)) }
 [1] 01 02 03
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testAsRaw#
+#{ as.raw.cls <- function(x) 42; as.raw(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asraw.testasraw1#
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));as.raw(argv[[1]]);
 raw(0)
@@ -7584,6 +7620,53 @@ raw(0)
 attr(,"Csingle")
 [1] TRUE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_astype_dispatch.testAsFunctionInternalDispatch#
+#{ as.character.myclass <- function(x) 42L; as.character(structure(TRUE, class='myclass')); }
+[1] 42
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_astype_dispatch.testAsFunctionInternalDispatch#
+#{ as.complex.myclass <- function(x) 42L; as.complex(structure(TRUE, class='myclass')); }
+[1] 42
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_astype_dispatch.testAsFunctionInternalDispatch#
+#{ as.double.myclass <- function(x) 42L; as.double(structure(TRUE, class='myclass')); }
+[1] 42
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_astype_dispatch.testAsFunctionInternalDispatch#
+#{ as.integer.myclass <- function(x) 42L; as.integer(structure(TRUE, class='myclass')); }
+[1] 42
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_astype_dispatch.testAsFunctionInternalDispatch#
+#{ as.logical.myclass <- function(x) 42L; as.logical(structure(TRUE, class='myclass')); }
+[1] 42
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_astype_dispatch.testAsFunctionInternalDispatch#
+#{ as.raw.myclass <- function(x) 42L; as.raw(structure(TRUE, class='myclass')); }
+[1] 42
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_astype_dispatch.testExtraArgumentsArePassedToOverload#
+#as.integer.myclass <- function(x, extra, ...) list(x=x, extra=extra, varargs=list(...)); as.integer(structure(TRUE, class='myclass'), my=TRUE, extra=42L, args='hello');
+$x
+[1] TRUE
+attr(,"class")
+[1] "myclass"
+
+$extra
+[1] 42
+
+$varargs
+$varargs$my
+[1] TRUE
+
+$varargs$args
+[1] "hello"
+
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_astype_dispatch.testWithBuiltinFunction#
+#as.numeric(diff(structure(c(-154401120, 1503191520), class = c('POSIXct', 'POSIXt'), tzone = 'GMT')), units='secs')
+[1] 1657592640
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsSymbol#
 #{ as.symbol("name") }
 name
@@ -7596,6 +7679,10 @@ name
 #{ as.symbol(as.symbol(123)) }
 `123`
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
+#as.vector(NULL, mode='pairlist')
+NULL
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
 #as.vector(as.symbol('asdf'), 'symbol')
 asdf
@@ -7692,6 +7779,10 @@ Warning messages:
 2: In as.vector(c("foo", "bar"), "raw") :
   out-of-range values treated as 0 in coercion to raw
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
+#{ as.vector.cls <- function(x, mode) 42; as.vector(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testAsVector#
 #{ x<-1:4; dim(x)<-c(2, 2); dimnames(x)<-list(c("a", "b"), c("c", "d")); y<-as.vector(x, "list"); y }
 [[1]]
@@ -7824,7 +7915,7 @@ $Depends
 [1] "methods"
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector15#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector15#Ignored.ImplementationError#
 #argv <- list(quote(sqrt(abs(`Standardized residuals`))), 'expression'); .Internal(as.vector(argv[[1]], argv[[2]]))
 expression(sqrt(abs(`Standardized residuals`)))
 
@@ -7845,7 +7936,7 @@ X[[2L]]
 #argv <- list(NA, 'logical'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector19#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector19#Ignored.ImplementationError#
 #argv <- list(NULL, 'double'); .Internal(as.vector(argv[[1]], argv[[2]]))
 numeric(0)
 
@@ -7874,7 +7965,7 @@ $weight
 c(1, rep(0.1, 51))
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector21#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector21#Ignored.ImplementationError#
 #argv <- list(NULL, 'integer'); .Internal(as.vector(argv[[1]], argv[[2]]))
 integer(0)
 
@@ -8036,7 +8127,7 @@ I("def'gh")
  [91]  1.63636364  1.67676768  1.71717172  1.75757576  1.79797980  1.83838384
  [97]  1.87878788  1.91919192  1.95959596  2.00000000
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector38#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector38#
 #argv <- list(integer(0), 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))
 NULL
 
@@ -8054,7 +8145,7 @@ $bg
 #argv <- list(c(NA, NaN), 'logical'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [1] NA NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector41#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector41#Ignored.ImplementationError#
 #argv <- list(structure(list(`character(0)` = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'character(0)', row.names = character(0), class = 'data.frame'), 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [1] character(0)
 <0 rows> (or 0-length row.names)
@@ -8069,7 +8160,7 @@ $bg
 [1] "GRID.VP.12"
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector44#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector44#Ignored.ImplementationError#
 #argv <- list(NULL, 'logical'); .Internal(as.vector(argv[[1]], argv[[2]]))
 logical(0)
 
@@ -8105,13 +8196,13 @@ list()
 #argv <- list(structure(c(5.4278733372119e-07, 0.000257866433233453, NA), .Names = c('x', 'm', 'Residuals')), 'any'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [1] 5.427873e-07 2.578664e-04           NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector53#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector53#
 #argv <- list('1.3', 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [[1]]
 [1] "1.3"
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector54#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector54#
 #argv <- list(1L, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [[1]]
 [1] 1
@@ -8133,7 +8224,7 @@ $Fr
 as.vector(HairEyeColor)
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector57#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector57#
 #argv <- list(FALSE, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [[1]]
 [1] FALSE
@@ -8280,7 +8371,7 @@ pi * -3:6
 #argv <- list(FALSE, 'character'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [1] "FALSE"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector75#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_asvector.testasvector75#
 #argv <- list(3.14159265358979, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))
 [[1]]
 [1] 3.141593
@@ -8451,12 +8542,66 @@ Error in atan2(y, x) : non-numeric argument to mathematical function
 #{ atan2(c(0.3,0.6,0.9), c(0.4, 0.3)) }
 [1] 0.6435011 1.1071487 1.1525720
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan21#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan21#
+#.Internal(atan2(structure(1:2, .Names = c('a','b')), 1));
+        a         b
+0.7853982 1.1071487
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan21#
+#.Internal(atan2(structure(1:6, dim = c(2,3)), 1));
+          [,1]     [,2]     [,3]
+[1,] 0.7853982 1.249046 1.373401
+[2,] 1.1071487 1.325818 1.405648
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan21#
+#.Internal(atan2(structure(c(1,2), .Names = c('a','b')), 1));
+        a         b
+0.7853982 1.1071487
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan21#
+#argv <- list(structure(0.142857142857143, .Names = 'Var2'), 1.75510204081633); .Internal(atan2(argv[[1]], argv[[2]]))
+      Var2
+0.08121631
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan21#
 #argv <- list(structure(0.142857142857143, .Names = 'Var2'), structure(1.75510204081633, .Names = 'Var1')); .Internal(atan2(argv[[1]], argv[[2]]))
       Var2
 0.08121631
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan22#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan21#
+#x <- 1:4; class(x) <- 'asdfasdf'; attr(x, 'f') <- 'fff'; names(x) <- c('a','b','c','d'); y <- 1:2; class(y) <- 'fds'; attr(y, 'a') <- 'Asdf'; names(y) <- c('v','y'); .Internal(atan2(x,1)); .Internal(atan2(x,x)); .Internal(atan2(x,y)); .Internal(atan2(y,x)); .Internal(atan2(y,1))
+        a         b         c         d
+0.7853982 1.1071487 1.2490458 1.3258177
+attr(,"class")
+[1] "asdfasdf"
+attr(,"f")
+[1] "fff"
+        a         b         c         d
+0.7853982 0.7853982 0.7853982 0.7853982
+attr(,"class")
+[1] "asdfasdf"
+attr(,"f")
+[1] "fff"
+        a         b         c         d
+0.7853982 0.7853982 1.2490458 1.1071487
+attr(,"class")
+[1] "asdfasdf"
+attr(,"f")
+[1] "fff"
+        a         b         c         d
+0.7853982 0.7853982 0.3217506 0.4636476
+attr(,"class")
+[1] "asdfasdf"
+attr(,"f")
+[1] "fff"
+        v         y
+0.7853982 1.1071487
+attr(,"class")
+[1] "fds"
+attr(,"a")
+[1] "Asdf"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan22#
 #argv <- list(structure(-0.224489795918367, .Names = 'Var2'), structure(-0.816326530612245, .Names = 'Var1')); .Internal(atan2(argv[[1]], argv[[2]]))
      Var2
 -2.873226
@@ -8467,7 +8612,7 @@ Error in atan2(y, x) : non-numeric argument to mathematical function
  [7] -0.1206102  0.4239882  0.4921311  0.9506540  1.3952942  2.1497456
 [13]  2.7900689
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan24#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_atan2.testatan24#Ignored.Unimplemented#
 #argv <- list(0+1i, 0+0i); .Internal(atan2(argv[[1]], argv[[2]]))
 [1] 1.570796+0i
 
@@ -9072,7 +9217,7 @@ attr(,"hessian")
 [2,]   NA   NA   NA   NA
 [3,]   NA   NA   NA   NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testattrassign6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_attrassign.testattrassign6#Output.IgnoreWhitespace#
 #argv <- list(structure(c('o', 'p', 'v', 'i', 'r', 'w', 'b', 'm', 'f', 's'), date = structure(1224086400, class = c('POSIXct', 'POSIXt'), tzone = '')), 'date', value = structure(1224086400, class = c('POSIXct', 'POSIXt'), tzone = ''));`attr<-`(argv[[1]],argv[[2]],argv[[3]]);
  [1] "o" "p" "v" "i" "r" "w" "b" "m" "f" "s"
 attr(,"date")
@@ -9611,11 +9756,11 @@ Error in attributes(x) <- 44 : attributes must be a list or NULL
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_attributesassign.testArgsCasts#
 #x <- 42;  attributes(x) <- NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_attributesassign.testattributesassign1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_attributesassign.testattributesassign1#Ignored.ImplementationError#
 #argv <- list(NULL, NULL);`attributes<-`(argv[[1]],argv[[2]]);
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_attributesassign.testattributesassign2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_attributesassign.testattributesassign2#Output.IgnoreWhitespace#
 #argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame'), structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame'));`attributes<-`(argv[[1]],argv[[2]]);
 [[1]]
 factor(0)
@@ -9847,7 +9992,7 @@ character(0)
 #argv <- structure(list(path = 'myTst'), .Names = 'path');do.call('basename', argv)
 [1] "myTst"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_bcVersion.testbcVersion1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_bcVersion.testbcVersion1#Ignored.Unimplemented#
 # .Internal(bcVersion())
 [1] 8
 
@@ -10264,6 +10409,10 @@ NULL
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(body(argv[[1]]))
 NULL
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testCombine#
+#typeof(c(substitute(graphics::par), list(as.symbol('a'))))
+[1] "list"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testCombine#
 #{ c( 100, 1:3, 200 ) }
 [1] 100   1   2   3 200
@@ -11061,7 +11210,7 @@ V             0.0cwt    0.2cwt    0.4cwt    0.6cwt
   Victory      69.77324  89.19900 110.36566 118.03233
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testc14#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_c.testc14#
 #options(digits=4);c(0.12345678912345,0.123)
 [1] 0.1235 0.1230
 
@@ -12801,6 +12950,15 @@ structure(integer(0), .Dim = 0:1, .Dimnames = list(NULL, NULL))
 structure(integer(0), .Dim = c(0L, 3L), .Dimnames = list(NULL,
     NULL))
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testRetType#Ignored.ImplementationError#
+#dput(cbind(substitute(graphics::par), list(as.symbol('a'))))
+structure(list(`::`, graphics, par, a, a, a), .Dim = c(3L, 2L
+))
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testRetType#
+#typeof(cbind(substitute(graphics::par), list(as.symbol('a'))))
+[1] "list"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_cbind.testcbind1#
 #argv <- list(748L, c(5.08759633523238, 4.0943445622221, 5.66642668811243,     3.43398720448515), c(1L, 1L, 1L, 1L), 1L, c(FALSE, TRUE,     TRUE, TRUE), c(0, 1, 0, 1), c(0, 1, 1, 1), c(0, 1, 0, 1),     c(FALSE, FALSE, TRUE, FALSE), c(FALSE, FALSE, FALSE, TRUE));do.call('cbind', argv)
      [,1]     [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
@@ -13355,16 +13513,16 @@ structure(integer(0), .Dim = c(0L, 3L), .Dimnames = list(NULL,
 [2,]    2    4   12   14
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ceiling.testCeiling#
-#{ ceiling(c(0.2,-3.4,NA,0/0,1/0)) }
-[1]   1  -3  NA NaN Inf
+#if (!any(R.version$engine == "FastR")) { 2+2i } else { { ceiling(1.1+1.9i); } }
+[1] 2+2i
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ceiling.testCeiling#
-#{ trunc("aaa"); }
-Error in trunc("aaa") : non-numeric argument to mathematical function
+#{ ceiling("aaa"); }
+Error in ceiling("aaa") : non-numeric argument to mathematical function
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ceiling.testCeiling#
-#{ trunc(1+1i); }
-Error in trunc(1 + (0+1i)) : unimplemented complex function
+#{ ceiling(c(0.2,-3.4,NA,0/0,1/0)) }
+[1]   1  -3  NA NaN Inf
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_ceiling.testCeiling#
 #{ typeof(ceiling(42L)); }
@@ -13515,7 +13673,7 @@ character(0)
      [,1]
 [1,]    1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_chol.testChol#Ignored.Unknown#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_chol.testChol#Output.IgnoreErrorMessage#
 #{ m <- matrix(c(5,-5,-5,3),2,2) ; chol(m) }
 Error in chol.default(m) :
   the leading minor of order 2 is not positive definite
@@ -14230,7 +14388,7 @@ attr(,"class")attr(,"package")
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_clearPushBack.testclearPushBack1#
 #argv <- list(FALSE); .Internal(clearPushBack(argv[[1]]))
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_cnoquote.testcnoquote1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cnoquote.testcnoquote1#Ignored.ImplementationError#
 #argv <- structure(list(structure(c('.', '.', '|', '.', '.', '|',     '.', '.'), .Dim = c(2L, 4L), .Dimnames = list(NULL, c('',     '', '', '')), class = 'noquote')), .Names = '');do.call('c.noquote', argv)
 [1] . . | . . | . .
 
@@ -14495,7 +14653,7 @@ NULL
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L)), 0, 0, FALSE); .Internal(colSums(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 numeric(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_colSums.testcolSums7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_colSums.testcolSums7#Ignored.ImplementationError#
 #argv <- list(structure(c(-7.5, -6.5, -5.5, -4.5, -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, -421.875, -274.625, -166.375, -91.125, -42.875, -15.625, -3.375, -0.125, 0.125, 3.375, 15.625, 42.875, 91.125, 166.375, 274.625, 421.875, -9187.5, -2866.5, -445.499999999999, -4.5, -283.5, -562.5, -541.5, -220.5, 220.5, 541.5, 562.5, 283.5, 4.49999999999999, 445.5, 2866.5, 9187.5, -139741.875, -4844.38499999995, -10122.255, -28872.045, -28539.315, -15800.625, -4325.535, -178.605, 178.605, 4325.535, 15800.625, 28539.315, 28872.045, 10122.255, 4844.38500000001, 139741.875), .Dim = c(16L, 4L)), 16, 4, FALSE); .Internal(colSums(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] 0.000000e+00 0.000000e+00 1.013412e-12 6.002665e-11
 
@@ -14719,35 +14877,35 @@ numeric(0)
 [199,]  0  0  0  0  0
 [200,]  0  0  0  0  0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_comment.testcomment1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_comment.testcomment1#Ignored.Unimplemented#
 #argv <- list(NULL); .Internal(comment(argv[[1]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_comment.testcomment2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_comment.testcomment2#Ignored.Unimplemented#
 #argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0'))); .Internal(comment(argv[[1]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_comment.testcomment3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_comment.testcomment3#Ignored.Unimplemented#
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(comment(argv[[1]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_comment.testcomment4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_comment.testcomment4#Ignored.Unimplemented#
 #argv <- list(structure(1:12, .Dim = 3:4, comment = c('This is my very important data from experiment #0234', 'Jun 5, 1998'))); .Internal(comment(argv[[1]]))
 [1] "This is my very important data from experiment #0234"
 [2] "Jun 5, 1998"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_commentassign.testcommentassign1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_commentassign.testcommentassign1#Ignored.ImplementationError#
 #argv <- list(structure(1:12, .Dim = 3:4, comment = c('This is my very important data from experiment #0234', 'Jun 5, 1998')), c('This is my very important data from experiment #0234', 'Jun 5, 1998')); .Internal(`comment<-`(argv[[1]], argv[[2]]))
      [,1] [,2] [,3] [,4]
 [1,]    1    4    7   10
 [2,]    2    5    8   11
 [3,]    3    6    9   12
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_commentassign.testcommentassign2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_commentassign.testcommentassign2#Ignored.ImplementationError#
 #argv <- list(character(0), NULL); .Internal(`comment<-`(argv[[1]], argv[[2]]))
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_commentassign.testcommentassign3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_commentassign.testcommentassign3#Ignored.ImplementationError#
 #argv <- list(logical(0), NULL); .Internal(`comment<-`(argv[[1]], argv[[2]]))
 logical(0)
 
@@ -15677,7 +15835,7 @@ Error in cos() : 0 arguments passed to 'cos' which requires 1
 [4,]  0.2836622 -0.2751633 -0.9182828
 [5,]  0.9601703  0.6469193  0.7766860
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_cos.testcos4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_cos.testcos4#Output.MissingWarning#
 #argv <- list(Inf);cos(argv[[1]]);
 [1] NaN
 Warning message:
@@ -16110,6 +16268,13 @@ Error in crossprod(x, y) :
 [1,]  NaN  NaN
 [2,]  NaN   NA
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_crossprod.testCrossprodDimnames#
+#{ crossprod(structure(1:9, .Dim=c(3L,3L), .Dimnames=list(c('a', 'b', 'c'), c('A', 'B', 'C'))), structure(1:9, .Dim=c(3L,3L), .Dimnames=list(c('d', 'e', 'f'), c('D', 'E', 'F')))) }
+   D   E   F
+A 14  32  50
+B 32  77 122
+C 50 122 194
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_crossprod.testcrossprod1#
 #argv <- list(structure(c(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1), .Dim = c(60L, 5L)), structure(c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1), .Dim = c(60L, 6L))); .Internal(crossprod(argv[[1]], argv[[2]]))
      [,1] [,2] [,3] [,4] [,5] [,6]
@@ -16153,7 +16318,7 @@ Error in crossprod(x, y) :
 [1,] 0.000000000  -2.539995
 [2,] 0.004701819 -15.927030
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_crossprod.testcrossprod8#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_crossprod.testcrossprod8#
 #argv <- list(structure(c(-0.0972759604917099, -0.0972759604917099, -0.197781705719934, -0.197781705719934, -0.258476920906799, -0.258476920906799, -0.31681058743414, -0.31681058743414, -0.36711291168933, -0.36711291168933, -0.386611727075222, -0.386611727075222, -0.339690730499459, -0.33969073049946, -0.392353467475584, -0.392353467475584, -0.277328754578855, -0.277328754578855, -0.062581948827679, -0.062581948827679, 0.204605005658209, 0.204605005658209, 0.32860008733551, 0.32860008733551, 0.504748197638673, 0.504748197638673, 0.0398546163039329, 0.039854616303933, -0.269613788250837, -0.269613788250837, -0.312096598983548, -0.312096598983548, 0.0190548270250438, 0.0190548270250438, 0.270521530002251, 0.270521530002251), .Dim = c(12L, 3L)), structure(c(-2.82631170793264, -2.82631170793264, -3.89457420977924, -3.89457420977924, -3.62818861156626, -3.62818861156626, -2.72530862462141, -2.72530862462141, -1.437640468988, -1.437640468988, -0.811701520293695, -0.811701520293695, 14291.543903102, 14291.543903102, 13346.8386233407, 13346.8386233407, 8863.44390274002, 8863.44390274002, 4080.15117667984, 4080.15117667984, 979.818149952962, 979.818149952962, 296.593928028368, 296.593928028368), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('Vm', 'K')))); .Internal(crossprod(argv[[1]], argv[[2]]))
                Vm          K
 [1,] 7.376014e+00 -16175.971
@@ -20940,7 +21105,7 @@ Error in digamma(as.raw(1)) :
 #{ digamma(c(100, 2.2)) }
 [1] 4.6001619 0.5442934
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_digamma.testdigamma1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_digamma.testdigamma1#
 #argv <- list(structure(c(3.80516394437114, 12.8051639443711, 15.8051639443711, 6.80516394437114, 6.80516394437114, 14.8051639443711, 21.8051639443711, 23.8051639443711, 7.80516394437114, 7.80516394437114, 16.8051639443711, 8.80516394437114, 15.8051639443711, 7.80516394437114, 33.8051639443711, 54.8051639443711, 58.8051639443711, 15.8051639443711, 17.8051639443711, 17.8051639443711, 18.8051639443711, 41.8051639443711, 44.8051639443711, 47.8051639443711, 9.80516394437114, 24.8051639443711, 24.8051639443711, 29.8051639443711, 35.8051639443711, 37.8051639443711, 39.8051639443711, 4.80516394437114, 6.80516394437114, 12.8051639443711, 25.8051639443711, 46.8051639443711, 6.80516394437114, 7.80516394437114, 7.80516394437114, 10.8051639443711, 14.8051639443711, 24.8051639443711, 26.8051639443711, 33.8051639443711, 54.8051639443711, 55.8051639443711, 6.80516394437114, 6.80516394437114, 12.8051639443711, 18.8051639443711, 20.8051639443711, 9.80516394437114, 14.8051639443711, 15.8051639443711, 21.8051639443711, 48.8051639443711, 49.8051639443711, 61.8051639443711, 82.8051639443711, 3.80516394437114, 1.80516394437114, 3.80516394437114, 4.80516394437114, 6.80516394437114, 11.8051639443711, 15.8051639443711, 22.8051639443711, 37.8051639443711, 41.8051639443711, 7.80516394437114, 18.8051639443711, 68.8051639443711, 1.80516394437114, 1.80516394437114, 3.80516394437114, 8.80516394437114, 12.8051639443711, 13.8051639443711, 1.80516394437114, 1.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 12.8051639443711, 18.8051639443711, 4.80516394437114, 5.80516394437114, 23.8051639443711, 31.8051639443711, 37.8051639443711, 9.80516394437114, 1.80516394437114, 2.80516394437114, 6.80516394437114, 8.80516394437114, 17.8051639443711, 28.8051639443711, 1.80516394437114, 31.8051639443711, 11.8051639443711, 15.8051639443711, 28.8051639443711, 42.8051639443711, 70.8051639443711, 26.8051639443711, 11.8051639443711, 12.8051639443711, 21.8051639443711, 34.8051639443711, 6.80516394437114, 8.80516394437114, 1.80516394437114, 2.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 8.80516394437114, 12.8051639443711, 16.8051639443711, 6.80516394437114, 15.8051639443711, 7.80516394437114, 7.80516394437114, 8.80516394437114, 29.8051639443711, 1.80516394437114, 6.80516394437114, 15.8051639443711, 3.80516394437114, 3.80516394437114, 4.80516394437114, 9.80516394437114, 11.8051639443711, 13.8051639443711, 2.80516394437114, 2.80516394437114, 10.8051639443711, 23.8051639443711, 4.80516394437114, 4.80516394437114, 6.80516394437114, 16.8051639443711, 19.8051639443711, 23.8051639443711, 38.8051639443711), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146')));digamma(argv[[1]]);
         1         2         3         4         5         6         7         8
 1.1992419 2.5102939 2.7283680 1.8424125 1.8424125 2.6608240 3.0590412 3.1487517
@@ -20981,7 +21146,7 @@ Error in digamma(as.raw(1)) :
       145       146
 3.1487517 3.6456131
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_digamma.testdigamma2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_digamma.testdigamma2#
 #argv <- list(structure(c(9.16602330897621, 9.16602330897621, 1.16602330897621, 1.16602330897621, 3.16602330897621, 3.16602330897621, 6.16602330897621, 6.16602330897621, 6.16602330897621, 6.16602330897621, 2.16602330897621, 2.16602330897621, 8.16602330897621, 8.16602330897621, 1.16602330897621, 1.16602330897621, 7.16602330897621, 7.16602330897621, 19.1660233089762, 19.1660233089762, 2.16602330897621, 2.16602330897621), .Names = c('1', '1.1', '2', '2.1', '3', '3.1', '4', '4.1', '5', '5.1', '6', '6.1', '7', '7.1', '8', '8.1', '9', '9.1', '10', '10.1', '11', '11.1')));digamma(argv[[1]]);
          1        1.1          2        2.1          3        3.1          4
  2.1599635  2.1599635 -0.3329761 -0.3329761  0.9863152  0.9863152  1.7357784
@@ -20998,7 +21163,7 @@ Error in digamma(as.raw(1)) :
 Warning message:
 In digamma(argv[[1]]) : NaNs produced
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_digamma.testdigamma4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_digamma.testdigamma4#
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));digamma(argv[[1]]);
 <0 x 0 matrix>
 
@@ -21833,6 +21998,13 @@ NULL
 A 1 3
 B 2 4
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dimnamesassign.testDimnamesElementAssign#
+#{ x<-matrix(12,3,4); dimnames(x)[[2]]<-c('a','b','c','d'); x }
+      a  b  c  d
+[1,] 12 12 12 12
+[2,] 12 12 12 12
+[3,] 12 12 12 12
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_dimnamesassign.testdimnamesassign1#
 #argv <- list(structure(c(300, 3000, 400, 4000), .Dim = c(2L, 2L, 1L), .Dimnames = list(c('happy', 'sad'), NULL, '')), value = list(c('happy', 'sad'), NULL, ''));`dimnames<-`(argv[[1]],argv[[2]]);
 , ,
@@ -22085,7 +22257,7 @@ nonlin          NA         NA          NA 2.526731 2.647712 0.40492879
 a 1259  845  719  390
 b 1360 1053  774  413
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_dir.testdir1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dir.testdir1#
 #argv <- structure(list(path = '.', pattern = 'myTst_.*tar[.]gz$'),     .Names = c('path', 'pattern'));do.call('dir', argv)
 character(0)
 
@@ -22253,6 +22425,18 @@ Error in (function (x)  : object 'foo' not found
 #v1 <- as.numeric_version('3.0.0'); v2 <- as.numeric_version('3.1.0'); do.call('<', list(v1, v2))
 [1] TRUE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_docall.testDoCall#
+#{ boo <- function(c) ls(parent.frame(2)); foo <- function(a,b) boo(a); bar <- function(x,z) do.call('foo', list(1,2)); bar() }
+[1] "x" "z"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_docall.testDoCall#
+#{ boo <- function(c) ls(parent.frame(2)); foo <- function(a,b) boo(a); bar <- function(x,z) do.call('foo', list(parse(text='goo()'),2)); bar() }
+[1] "x" "z"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_docall.testDoCall#
+#{ boo <- function(c) ls(parent.frame(3)); foo <- function(a,b) boo(a); bar <- function(x,z) do.call('foo', list(parse(text='goo()'),2)); baz <- function(bazX) bar(bazX,1); baz(); }
+[1] "bazX"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_docall.testDoCall#
 #{ do.call("+", list(quote(1), 2))}
 [1] 3
@@ -22296,6 +22480,10 @@ Error in (function (x)  : object 'y' not found
 #{ f <- function(x) x; do.call(f, list(quote(y)))}
 Error in (function (x)  : object 'y' not found
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_docall.testDoCall#
+#{ f1 <- function(a) ls(parent.frame(2)); f2 <- function(b) f1(b); f3 <- function(c) f2(c); f4 <- function(d) do.call('f3', list(d)); f4(42); }
+[1] "c"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_docall.testDoCall#
 #{ foo <- function() ls(parent.frame()); bar <- function(a,b,c) do.call('foo', list()); bar(a=1,b=2,c=3); }
 [1] "a" "b" "c"
@@ -22382,6 +22570,159 @@ FALSE
 #argv <- list(c(0.00508571428571428, 0.876285714285715), structure(1L, class = c('terminal', 'connection')), 69); .Internal(dput(argv[[1]], argv[[2]], argv[[3]]))
 c(0.00508571428571428, 0.876285714285715)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dqr.testdqrcf#Ignored.OutputFormatting#
+#.Fortran(.F_dqrcf, 1, 1L, 1L, 1, 1, 1L, 1, 1L)
+[[1]]
+[1] 1
+
+[[2]]
+[1] 1
+
+[[3]]
+[1] 1
+
+[[4]]
+[1] 1
+
+[[5]]
+[1] 1
+
+[[6]]
+[1] 1
+
+[[7]]
+[1] 1
+
+[[8]]
+[1] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dqr.testdqrdc2#Ignored.OutputFormatting#
+#.Fortran(.F_dqrdc2, 1, 1L, 1L, 1L, 1, 1L, 1, 1L, 1)
+[[1]]
+[1] 1
+
+[[2]]
+[1] 1
+
+[[3]]
+[1] 1
+
+[[4]]
+[1] 1
+
+[[5]]
+[1] 1
+
+[[6]]
+[1] 1
+
+[[7]]
+[1] 1
+
+[[8]]
+NULL
+
+[[9]]
+[1] 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dqr.testdqrqty#
+#.Fortran(.F_dqrqty, 1, 1L, 1L, 1, 1, 1L, qty=1)
+[[1]]
+[1] 1
+
+[[2]]
+[1] 1
+
+[[3]]
+[1] 1
+
+[[4]]
+[1] 1
+
+[[5]]
+[1] 1
+
+[[6]]
+[1] 1
+
+$qty
+[1] 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dqr.testdqrqy#
+#.Fortran(.F_dqrqy, 1, 1L, 1L, 1, 1, 1L, 1)
+[[1]]
+[1] 1
+
+[[2]]
+[1] 1
+
+[[3]]
+[1] 1
+
+[[4]]
+[1] 1
+
+[[5]]
+[1] 1
+
+[[6]]
+[1] 1
+
+[[7]]
+[1] 1
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dqr.testdqrrsd#
+#.Fortran(.F_dqrrsd, 1, 1L, 1L, 1, 1, 1L, 1)
+[[1]]
+[1] 1
+
+[[2]]
+[1] 1
+
+[[3]]
+[1] 1
+
+[[4]]
+[1] 1
+
+[[5]]
+[1] 1
+
+[[6]]
+[1] 1
+
+[[7]]
+[1] 0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_dqr.testdqrxb#
+#.Fortran(.F_dqrxb, 1, 1L, 1L, 1, 1, 1L, 1)
+[[1]]
+[1] 1
+
+[[2]]
+[1] 1
+
+[[3]]
+[1] 1
+
+[[4]]
+[1] 1
+
+[[5]]
+[1] 1
+
+[[6]]
+[1] 1
+
+[[7]]
+[1] 1
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_drop.testDrop#
 #a <- matrix(1:6, 3, 2, dimnames=list(1:3, c(' ','x'))); b <- array(c(1,2), dim=c(2), dimnames=list(c('int', 'x'))); drop(a %*% b);
  1  2  3
@@ -22830,19 +23171,19 @@ character(0)
 #argv <- list(c('1', '2', NA), 0L, '\'', 0L, FALSE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "'1'" "'2'" NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString10#Ignored.ImplementationError#
 #argv <- list('\'class\' is a reserved slot name and cannot be redefined', 0L, '\'', 0L, FALSE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "'\\'class\\' is a reserved slot name and cannot be redefined'"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString11#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString11#
 #argv <- list(structure(character(0), .Dim = c(0L, 0L)), 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 <0 x 0 matrix>
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString12#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString12#Ignored.ReferenceError#
 #argv <- list(character(0), logical(0), '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString13#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString13#
 #argv <- list(structure('integer(0)', .Names = 'c0', row.names = character(0)), structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
           c0
 "integer(0)"
@@ -22861,7 +23202,7 @@ character(0)
 #argv <- list(c('NA', 'a', 'b', 'c', 'd', NA), 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "NA"   "a"    "b"    "c"    "d"    "<NA>"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString7#Ignored.ImplementationError#
 #argv <- list('ab\bc\ndef', 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "ab\\bc\\ndef"
 
@@ -22869,7 +23210,7 @@ character(0)
 #argv <- list(c('FALSE', NA), 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "FALSE" "<NA>"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString9#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_encodeString.testencodeString9#
 #argv <- list(structure('integer(0)', .Names = 'c0', row.names = character(0)), 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
           c0
 "integer(0)"
@@ -23100,6 +23441,18 @@ Error in eval(expr, envir, enclos) : object 'a' not found
 Error in eval(quote(x + y), c(-1, -2)) :
   numeric 'envir' arg not of length one
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_eval.testWithEnvirAndEnclose#
+#{ df <- list(a=c(1,2,3), b=c(3,4,5)); df$c <- with(df, a^2); df; }
+$a
+[1] 1 2 3
+
+$b
+[1] 3 4 5
+
+$c
+[1] 1 4 9
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_exists.testexists1#
 #argv <- structure(list(x = '.Device'), .Names = 'x');do.call('exists', argv)
 [1] TRUE
@@ -23722,6 +24075,11 @@ q + b
 attr(,"mya")
 [1] 42
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_extract_replace.replaceWithPositionNames#
+#{ foo <- function(x, idx) { x[idx] <- F; x }; foo(c(T,T,T,T), structure(c('a'), .Names = c('a'))); r <- foo(c(T,T,T,T), structure(c('a', 'b'), .Names = c('a', 'b'))); r }
+                            a     b
+ TRUE  TRUE  TRUE  TRUE FALSE FALSE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_factor.testFactor#
 #{ as.logical(factor(c("a", "b", "a"))) }
 [1] NA NA NA
@@ -24166,16 +24524,16 @@ Error: 4 arguments passed to .Internal(findInterval) which requires 5
 Error: 4 arguments passed to .Internal(findInterval) which requires 5
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_floor.testFloor#
-#{ floor(c(0.2,-3.4,NA,0/0,1/0)) }
-[1]   0  -4  NA NaN Inf
+#if (!any(R.version$engine == "FastR")) { 1+1i } else { { floor(1.1+1.9i); } }
+[1] 1+1i
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_floor.testFloor#
-#{ trunc("aaa"); }
-Error in trunc("aaa") : non-numeric argument to mathematical function
+#{ floor("aaa"); }
+Error in floor("aaa") : non-numeric argument to mathematical function
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_floor.testFloor#
-#{ trunc(1+1i); }
-Error in trunc(1 + (0+1i)) : unimplemented complex function
+#{ floor(c(0.2,-3.4,NA,0/0,1/0)) }
+[1]   0  -4  NA NaN Inf
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_floor.testFloor#
 #{ typeof(floor(42L)); }
@@ -24571,7 +24929,7 @@ character(0)
 #argv <- structure(list(x = structure(integer(0), class = 'AsIs')),     .Names = 'x');do.call('format.AsIs', argv)
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC1#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC1#
 #argv <- list(c(3.14159265358979, 3.1415926535898, 1), 'double', 10, 4L, 'g', '', c(12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "     3.142" "     3.142" "         1"
 
@@ -24599,15 +24957,25 @@ character(0)
 [21] "1967" "1968" "1968" "1968" "1968" "1968" "1969" "1969" "1969" "1970"
 [31] "1970" "1970" "1970" "1970" "1971" "1971" "1971" "1972" "1972"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC15#
+#.Internal(formatC(1e-15, "double", 1L, 6L, "g", "", 12))
+[1] "1e-15"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC15#
+#y <- structure(c(2, 14.1776856316985), .Dim = c(2L, 1L), .Dimnames = list(c("m.ship.expon.", "objective"), " ")); formatC(y, digits = 6)
+
+m.ship.expon. "      2"
+objective     "14.1777"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC2#Ignored.ImplementationError#
 #argv <- list(1, 'double', 8, 5, 'g', '-', 13); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "1       "
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC3#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC3#
 #argv <- list(structure(c(1.5, 13.3414265412268, 1e-15, 8, 1, 500, 28), .Dim = c(7L, 1L), .Dimnames = list(c('m.ship.expon.', 'objective', 'tolerance', 'iterations', 'converged', 'maxit', 'n'), ' ')), 'double', 8L, 7L, 'g', '', c(15L, 15L, 15L, 15L, 15L, 15L, 15L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "     1.5" "13.34143" "   1e-15" "       8" "       1" "     500" "      28"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC4#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatC.testformatC4#
 #argv <- list(c(1000, 1e+07, 1), 'double', 5, 4L, 'g', '', c(12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] " 1000" "1e+07" "    1"
 
@@ -24684,59 +25052,59 @@ character(0)
 #argv <- structure(list(x = structure(c(0, 30, 60), units = 'mins',     class = 'difftime')), .Names = 'x');do.call('format.difftime', argv)
 [1] " 0 mins" "30 mins" "60 mins"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo1#Ignored.Unimplemented#
 #argv <- list(c(0.099999994, 0.2), 7L, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 10  8  0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo10#Ignored.Unimplemented#
 #argv <- list(structure(c(2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), .Names = c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y')), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 1 0 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo11#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo11#Ignored.Unimplemented#
 #argv <- list(structure(c(-3.14159265358979e-05, 3.14159265358979e-05, -0.000314159265358979, 0.000314159265358979, -0.00314159265358979, 0.00314159265358979, -0.0314159265358979, 0.0314159265358979, -0.314159265358979, 0.314159265358979, -3.14159265358979, 3.14159265358979, -31.4159265358979, 31.4159265358979, -314.159265358979, 314.159265358979, -3141.59265358979, 3141.59265358979, -31415.9265358979, 31415.9265358979, -314159.265358979, 314159.265358979, -1e-05, 1e-05, -1e-04, 1e-04, -0.001, 0.001, -0.01, 0.01, -0.1, 0.1), .Dim = c(2L, 16L)), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 13  6  1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo12#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo12#Ignored.Unimplemented#
 #argv <- list(c(NaN, NA), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 3 0 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo14#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo14#Ignored.Unimplemented#
 #argv <- structure(list(x = complex(real = Inf, imaginary = Inf)),     .Names = 'x');do.call('format.info', argv)
 [1] 3 0 0 3 0 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo15#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo15#Ignored.Unimplemented#
 #argv <- structure(list(x = c(complex(real = NaN, imaginary = NaN),     NA)), .Names = 'x');do.call('format.info', argv)
 [1] 3 0 0 3 0 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo2#Ignored.Unimplemented#
 #argv <- list(c(0.099999994, 0.2), 6L, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 3 1 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo3#Ignored.Unimplemented#
 #argv <- list(c(Inf, -Inf), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 4 0 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo4#Ignored.Unimplemented#
 #argv <- list(FALSE, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 5
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo5#Ignored.Unimplemented#
 #argv <- list(3.14159265358979e-10, NULL, 8); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 12  6  1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo6#Ignored.Unimplemented#
 #argv <- list(1e+08, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 5 0 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo7#Ignored.Unimplemented#
 #argv <- list(1e+222, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 6 0 2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo8#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo8#Ignored.Unimplemented#
 #argv <- list(31.4159265358979, NULL, 8); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 11  8  0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo9#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_formatinfo.testformatinfo9#Ignored.Unimplemented#
 #argv <- list(712L, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))
 [1] 3
 
@@ -24761,7 +25129,7 @@ In gamma(argv[[1]]) : NaNs produced
 Warning message:
 In gamma(argv[[1]]) : NaNs produced
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma3#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gamma.testgamma3#
 #argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));gamma(argv[[1]]);
 <0 x 0 matrix>
 
@@ -24825,11 +25193,11 @@ In gamma(argv[[1]]) : NaNs produced
 #argv <- list(FALSE); .Internal(gcinfo(argv[[1]]))
 [1] FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gctorture2.testgctorture21#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gctorture2.testgctorture21#Ignored.Unimplemented#
 #argv <- list(NULL, NULL, FALSE); .Internal(gctorture2(argv[[1]], argv[[2]], argv[[3]]))
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gctorture2.testgctorture22#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gctorture2.testgctorture22#Ignored.Unimplemented#
 #argv <- list(FALSE, FALSE, FALSE); .Internal(gctorture2(argv[[1]], argv[[2]], argv[[3]]))
 [1] 0
 
@@ -24861,6 +25229,14 @@ Error in get("x", inherits = FALSE) : object 'x' not found
 #{ x <- 33 ; f <- function() { if (FALSE) { x <- 22  } ; get("x", inherits = FALSE) } ; f() }
 Error in get("x", inherits = FALSE) : object 'x' not found
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_get.testGet#
+#{x <- 1L; get('x', mode='double'); }
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_get.testGet#
+#{x <- 1L; get('x', mode='numeric'); }
+[1] 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_get.testGet#
 #{y<-function(){y<-2;get("y",mode="closure")};y();}
 function(){y<-2;get("y",mode="closure")}
@@ -24910,13 +25286,13 @@ NULL
 #argv <- list('FALSE', '', FALSE); .Internal(getSymbolInfo(argv[[1]], argv[[2]], argv[[3]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_getconst.testgetconst1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_getconst.testgetconst1#Ignored.Unimplemented#
 #argv <- list(list(list(), NULL), 1); .Internal(getconst(argv[[1]], argv[[2]]))
 [[1]]
 list()
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_getconst.testgetconst2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_getconst.testgetconst2#Ignored.Unimplemented#
 #argv <- list(list(FALSE), 1); .Internal(getconst(argv[[1]], argv[[2]]))
 [[1]]
 [1] FALSE
@@ -24954,7 +25330,7 @@ character(0)
 #argv <- list(NULL, NULL); .Internal(gettext(argv[[1]], argv[[2]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testRegExpr#Ignored.ImplementationError#
 #gregexpr("(a)[^a]\\1", c("andrea apart", "amadeus", NA))
 [[1]]
 [1] 6
@@ -25375,7 +25751,7 @@ attr(,"useBytes")
 [1] TRUE
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testgregexpr4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testgregexpr4#Ignored.ImplementationError#
 #argv <- list('éè', '«Latin-1 accented chars»: éè øØ å<Å æ<Æ é éè', FALSE, FALSE, TRUE, TRUE); .Internal(gregexpr(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))
 [[1]]
 [1] 29 54
@@ -25405,7 +25781,7 @@ attr(,"useBytes")
 [1] TRUE
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testgregexpr7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gregexpr.testgregexpr7#Ignored.ImplementationError#
 #argv <- list('éè', '«Latin-1 accented chars»: éè øØ å<Å æ<Æ é éè', TRUE, FALSE, FALSE, TRUE); .Internal(gregexpr(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))
 [[1]]
 [1] 29 54
@@ -25429,6 +25805,41 @@ attr(,"useBytes")
 [1] TRUE
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#Output.IgnoreErrorMessage#
+#grep('(()', ')')
+Error in grep("(()", ")") :
+  invalid regular expression '(()', reason 'Missing ')''
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#
+#grep('(())', ')')
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#Output.IgnoreErrorMessage#
+#grep('([(]', ')')
+Error in grep("([(]", ")") :
+  invalid regular expression '([(]', reason 'Missing ')''
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#Output.IgnoreErrorMessage#
+#grep('([)]', ')')
+Error in grep("([)]", ")") :
+  invalid regular expression '([)]', reason 'Missing ')''
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#
+#grep('))', ')')
+integer(0)
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#
+#grep('))', '))')
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#
+#grep('[(]', ')')
+integer(0)
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#
+#grep('[)]', ')')
+[1] 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#
 #{ .Internal(grep("7", 7, F, F, F, F, F, F)) }
 Error: invalid 'text' argument
@@ -25441,7 +25852,7 @@ Error: invalid 'pattern' argument
 #{ .Internal(grep(character(), "7", F, F, F, F, F, F)) }
 Error: invalid 'pattern' argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_grep.testGrep#Ignored.ImplementationError#
 #{ grep('^ *$', ' \n') }
 integer(0)
 
@@ -25655,7 +26066,7 @@ Warning message:
 In gsub("a", "aa", "prAgue alley", fixed = TRUE, ignore.case = TRUE) :
   argument 'ignore.case = TRUE' will be ignored
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#Ignored.Unimplemented#
 #{ gsub("a","aa", "prAgue alley", ignore.case=TRUE) }
 [1] "praague aalley"
 
@@ -25683,7 +26094,7 @@ In gsub("a", "aa", "prAgue alley", fixed = TRUE, ignore.case = TRUE) :
 #{ gsub(pattern = 'a*', replacement = 'x', x = 'ÄaÄ', perl = TRUE) }
 [1] "xÄxÄx"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testGsub#Ignored.ImplementationError#
 #{ gsub(pattern = 'Ä*', replacement = 'x', x = 'aÄÄÄÄÄb', perl = TRUE) }
 [1] "xaxbx"
 
@@ -25691,7 +26102,7 @@ In gsub("a", "aa", "prAgue alley", fixed = TRUE, ignore.case = TRUE) :
 #argv <- list('([[:alnum:]])--([[:alnum:]])', '\\1-\\2', 'Date-Time Classes', FALSE, FALSE, FALSE, FALSE); .Internal(gsub(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "Date-Time Classes"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testgsub10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testgsub10#Ignored.ImplementationError#
 #argv <- list('a*', 'x', 'baaac', FALSE, FALSE, FALSE, FALSE); .Internal(gsub(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "xbxcx"
 
@@ -25703,7 +26114,7 @@ In gsub("a", "aa", "prAgue alley", fixed = TRUE, ignore.case = TRUE) :
 #argv <- list('([[:digit:]]+[.-]){1,}[[:digit:]]+', '', 'pkgB_1.0.tar.gz', FALSE, FALSE, FALSE, FALSE); .Internal(gsub(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "pkgB_.tar.gz"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testgsub13#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testgsub13#Ignored.ImplementationError#
 #argv <- list('\\b', '|', 'The quick brown èé', FALSE, TRUE, FALSE, FALSE); .Internal(gsub(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
 [1] "|The| |quick| |brown| |èé|"
 
@@ -25943,7 +26354,7 @@ attr(,"Rd_tag")
 #argv <- structure(list(pattern = 'a*', replacement = 'x', x = 'baaaac',     perl = TRUE), .Names = c('pattern', 'replacement', 'x', 'perl'));do.call('gsub', argv)
 [1] "xbxcx"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testgsub31#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_gsub.testgsub31#Ignored.ImplementationError#
 #argv <- structure(list(pattern = 'a*', replacement = 'x', x = 'baaaac'),     .Names = c('pattern', 'replacement', 'x'));do.call('gsub', argv)
 [1] "xbxcx"
 
@@ -26089,13 +26500,13 @@ character(0)
 #argv <- list('façile'   , 'latin1', 'ASCII', '', TRUE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))
 [1] "faile"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testiconv8#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testiconv8#
 #argv <- list(structure('Prediction matrix for soap film smooth', Rd_tag = 'TEXT'), 'UTF-8', 'ASCII', NA_character_, FALSE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))
 [1] "Prediction matrix for soap film smooth"
 attr(,"Rd_tag")
 [1] "TEXT"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testiconv9#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_iconv.testiconv9#
 #argv <- list(structure(c('Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance'), .Names = c('Q1_MISSING_NONE', 'Q1_MISSING_1', 'Q1_MISSING_2', 'Q1_MISSING_3', 'Q1_MISSING_RANGE', 'Q1_MISSING_LOW', 'Q1_MISSING_HIGH', 'Q1_MISSING_RANGE_1', 'Q1_MISSING_LOW_1', 'Q1_MISSING_HIGH_1')), 'latin1', '', NA_character_, TRUE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))
                             Q1_MISSING_NONE
 "Q.1 Opinion of presidents job performance"
@@ -26118,7 +26529,7 @@ attr(,"Rd_tag")
                           Q1_MISSING_HIGH_1
 "Q.1 Opinion of presidents job performance"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_icuSetCollate.testicuSetCollate1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_icuSetCollate.testicuSetCollate1#Ignored.Unimplemented#
 # .Internal(icuSetCollate())
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_identical.testAttrOrder#Ignored.ImplementationError#
@@ -26521,6 +26932,14 @@ attr(,"Rd_tag")
 #argv <- structure(list(test = c(TRUE, TRUE, FALSE, TRUE, FALSE),     yes = 'True', no = 'False'), .Names = c('test', 'yes', 'no'));do.call('ifelse', argv)
 [1] "True"  "True"  "False" "True"  "False"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#
+#inherits(1L, 'double')
+[1] FALSE
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#
+#inherits(1L, 'numeric')
+[1] FALSE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_inherits.testInherits#
 #inherits(NULL, 'NULL')
 [1] TRUE
@@ -27418,6 +27837,10 @@ character(0)
 #argv <- list(structure(list(carb = c(33, 40, 37, 27, 30, 43, 34, 48, 30, 38, 50, 51, 30, 36, 41, 42, 46, 24, 35, 37), age = c(33, 47, 49, 35, 46, 52, 62, 23, 32, 42, 31, 61, 63, 40, 50, 64, 56, 61, 48, 28), wgt = c(100, 92, 135, 144, 140, 101, 95, 101, 98, 105, 108, 85, 130, 127, 109, 107, 117, 100, 118, 102), prot = c(14, 15, 18, 12, 15, 15, 14, 17, 15, 14, 17, 19, 19, 20, 15, 16, 18, 13, 18, 14)), .Names = c('carb', 'age', 'wgt', 'prot'), row.names = c(NA, -20L), class = 'data.frame'));is.array(argv[[1]]);
 [1] FALSE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isarray.testisarrayGenericDispatch#
+#{ is.array.cls <- function(x) 42; is.array(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_isatomic.testIsAtomic#
 #{ !is.atomic(function() {}) }
 [1] TRUE
@@ -28104,7 +28527,7 @@ logical(0)
      [,1] [,2] [,3] [,4] [,5] [,6] [,7]
 [1,] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite23#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite23#
 #argv <- list(structure(c(-4, 0, 0, 0, 0, 0, 0, -406.725, 41.7955066364795, 0, 0, 0, 0, 0, -1550.79375, 381.717151319926, 49.8228991342168, 0, 0, 0, 0, -1277.325, 224.617432123818, -31.1858918860748, -282.060212912726, 0, 0, 0, -1042.675, 125.261805546114, -29.9849484767744, 164.425554254677, -170.353263600129, 0, 0, -469.696, 26.3795103523805, 4.19691803785862, -3.18974110831568, 0.0462484557378925, 1.46320172717486, 0, -7818, 18.2758880432689, 1.77525956575195, -1.45298766739792, -0.449176219307484, -0.281900648530911, -0.669305080560524), .Dim = c(7L, 7L), .Dimnames = list(c('1947', '1948', '1949', '1950', '1951', '1952', '1953'), c('(Intercept)', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'))));is.finite(argv[[1]]);
      (Intercept) GNP.deflator  GNP Unemployed Armed.Forces Population Year
 1947        TRUE         TRUE TRUE       TRUE         TRUE       TRUE TRUE
@@ -28136,7 +28559,7 @@ value
 #argv <- list(c(NA, 5, 9, 1, 2, 5, 6, 7, 8, 3, 8));is.finite(argv[[1]]);
  [1] FALSE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite6#
 #argv <- list(structure(1.27861470300044, .Dim = c(1L, 1L), .Dimnames = list('(Intercept)', '(Intercept)')));is.finite(argv[[1]]);
             (Intercept)
 (Intercept)        TRUE
@@ -28153,7 +28576,7 @@ value
 [13]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
 [25]  TRUE  TRUE FALSE  TRUE  TRUE  TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite9#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isfinite.testisfinite9#
 #argv <- list(structure(c(0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.0147058823529412, 0.0110294117647059, 0.0257352941176471, 0.00735294117647059, 0.0294117647058824, 0.0147058823529412, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.0110294117647059, 0.0147058823529412, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.00735294117647059, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.0147058823529412, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.0183823529411765, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.00367647058823529, 0.00735294117647059, 0.0183823529411765, 0.00735294117647059, 0.00735294117647059, 0.00735294117647059, 0.0147058823529412, 0.0147058823529412, 0.00367647058823529, 0.00367647058823529, 0.0110294117647059, 0.0147058823529412, 0.00735294117647059, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.0183823529411765, 0.0147058823529412, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.0147058823529412, 0.00735294117647059, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.0294117647058824, 0.00367647058823529, 0.0183823529411765, 0.00367647058823529, 0.0110294117647059, 0.0147058823529412, 0.0147058823529412, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00735294117647059, 0.0220588235294118, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529), class = 'table', .Dim = 126L, .Dimnames = structure(list(fe = c('1.6', '1.667', '1.7', '1.733', '1.75', '1.783', '1.8', '1.817', '1.833', '1.85', '1.867', '1.883', '1.917', '1.933', '1.95', '1.967', '1.983', '2', '2.017', '2.033', '2.067', '2.083', '2.1', '2.133', '2.15', '2.167', '2.183', '2.2', '2.217', '2.233', '2.25', '2.267', '2.283', '2.3', '2.317', '2.333', '2.35', '2.367', '2.383', '2.4', '2.417', '2.483', '2.617', '2.633', '2.8', '2.883', '2.9', '3.067', '3.317', '3.333', '3.367', '3.417', '3.45', '3.5', '3.567', '3.6', '3.683', '3.717', '3.733', '3.75', '3.767', '3.817', '3.833', '3.85', '3.883', '3.917', '3.95', '3.966', '3.967', '4', '4.033', '4.05', '4.067', '4.083', '4.1', '4.117', '4.133', '4.15', '4.167', '4.183', '4.2', '4.233', '4.25', '4.267', '4.283', '4.3', '4.317', '4.333', '4.35', '4.366', '4.367', '4.383', '4.4', '4.417', '4.433', '4.45', '4.467', '4.483', '4.5', '4.517', '4.533', '4.55', '4.567', '4.583', '4.6', '4.617', '4.633', '4.65', '4.667', '4.7', '4.716', '4.733', '4.75', '4.767', '4.783', '4.8', '4.817', '4.833', '4.85', '4.883', '4.9', '4.933', '5', '5.033', '5.067', '5.1')), .Names = 'fe')));is.finite(argv[[1]]);
 fe
   1.6 1.667   1.7 1.733  1.75 1.783   1.8 1.817 1.833  1.85 1.867 1.883 1.917
@@ -28345,7 +28768,7 @@ FALSE FALSE FALSE
 [2,] FALSE FALSE FALSE
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite14#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite14#
 #argv <- list(structure(c(1, 0.5, 0.5, 1), .Dim = c(2L, 2L), .Dimnames = list(c('A', 'B'), c('A', 'B'))));is.infinite(argv[[1]]);
       A     B
 A FALSE FALSE
@@ -28392,7 +28815,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
    66    67    68    69    70    71
 FALSE FALSE FALSE FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isinfinite.testisinfinite5#
 #argv <- list(structure(c(80, 80, 75, 62, 62, 62, 62, 62, 58, 58, 58, 58, 58, 58, 50, 50, 50, 50, 50, 56, 70, 27, 27, 25, 24, 22, 23, 24, 24, 23, 18, 18, 17, 18, 19, 18, 18, 19, 19, 20, 20, 20, 89, 88, 90, 87, 87, 87, 93, 93, 87, 80, 89, 88, 82, 93, 89, 86, 72, 79, 80, 82, 91, 42, 37, 37, 28, 18, 18, 19, 20, 15, 14, 14, 13, 11, 12, 8, 7, 8, 8, 9, 15, 15), .Dim = c(21L, 4L), .Dimnames = list(NULL, c('Air.Flow', 'Water.Temp', 'Acid.Conc.', 'stack.loss'))));is.infinite(argv[[1]]);
       Air.Flow Water.Temp Acid.Conc. stack.loss
  [1,]    FALSE      FALSE      FALSE      FALSE
@@ -28958,6 +29381,10 @@ FALSE FALSE
 #argv <- list(structure(list(Topic = c('myTst-package', 'foo-class', 'myTst', 'show,foo-method', 'show,foo-method', 'show-methods'), File = c('myTst-package', 'foo-class', 'myTst-package', 'foo-class', 'show-methods', 'show-methods')), .Names = c('Topic', 'File'), row.names = c(3L, 1L, 4L, 2L, 6L, 5L), class = 'data.frame'));is.matrix(argv[[1]]);
 [1] FALSE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_ismatrix.testismatrixGenericDispatch#
+#{ is.matrix.cls <- function(x) 42; is.matrix(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA#
 #is.na(data.frame(col1=1:5, col2=c(NA, 1, NA, 2, NA)))
       col1  col2
@@ -29019,6 +29446,10 @@ a         f     g
 #{ is.na(list(1[10],1L[10],list(),integer())) }
 [1]  TRUE  TRUE FALSE FALSE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA#
+#{ is.na.cls <- function(x) 42; is.na(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testisna1#
 #argv <- list(8.21977282218514e-09);is.na(argv[[1]]);
 [1] FALSE
@@ -29415,6 +29846,10 @@ logical(0)
 [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [25] FALSE  TRUE FALSE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnan.testisnanGenericDispatch#
+#{ is.nan.cls <- function(x) 42; is.nan(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_isnull.testisnull1#
 #argv <- list(c('a', 'b', 'c'));is.null(argv[[1]]);
 [1] FALSE
@@ -29495,11 +29930,11 @@ logical(0)
 #argv <- list(structure(c(39.7, 27.7, 43.5, 89.7, 70.2, 63.5, 36.5, 15.2, 35.3, 45.2, 1.2, 49.5, 63.1, 34, 17, 17.6, 67.8, 45.1, 50.9, 64.9, 59.8, 73, 37.6, 60.7, 60.8, 69.3, 71.2, 64.5, 75.9, 7.7, 72.6, 18.7, 78.2, 55.1, 58.1, 62, 53.3, 85.9, 67.5, 16.7, 46.6, 84.9, 19.4, 38.4, 5, 22, 17, 5, 16, 6, 12, 31, 9, 16, 37, 15, 13, 17, 15, 35, 14, 6, 22, 7, 22, 19, 15, 19, 16, 22, 12, 14, 9, 29, 18, 25, 12, 14, 14, 21, 12, 3, 14, 22, 16, 7, 26, 26, 5, 29, 15, 2, 7, 3, 7, 20, 7, 13, 53, 8, 13, 8, 12, 32, 8, 9, 12, 3, 10, 9, 7, 12, 10, 5, 1, 6, 9, 11, 2, 7, 6, 3, 8, 12, 7, 2, 7, 13, 29, 6, 28, 12, 93.4, 58.33, 5.16, 100, 92.85, 2.56, 33.77, 2.15, 90.57, 91.38, 42.34, 6.1, 96.83, 3.3, 9.96, 16.92, 97.16, 84.84, 15.14, 98.22, 5.23, 2.84, 4.97, 4.43, 7.72, 2.82, 2.4, 98.61, 99.06, 13.79, 24.2, 8.65, 98.96, 4.52, 5.23, 8.52, 97.67, 99.71, 2.27, 11.22, 50.43, 99.68, 12.11, 5.62, 20.2, 19.3, 20.6, 18.3, 23.6, 18, 20.3, 10.8, 26.6, 24.4, 18, 22.5, 18.1, 20, 22.2, 23, 24.9, 22.2, 16.7, 20.2, 18, 20, 20, 22.7, 16.3, 18.7, 21, 24.5, 17.8, 20.5, 21.2, 19.5, 19.4, 22.4, 23.8, 16.5, 21, 15.1, 19.1, 18.9, 18.2, 19.8, 20.2, 20.3), .Dim = c(44L, 5L), .Dimnames = list(c('Franches-Mnt', 'Rive Gauche', 'Neuveville', 'Herens', 'Broye', 'Paysd\'enhaut', 'Moutier', 'La Vallee', 'Porrentruy', 'Sarine', 'V. De Geneve', 'Yverdon', 'Sion', 'Grandson', 'Courtelary', 'Neuchatel', 'Glane', 'Delemont', 'Nyone', 'Monthey', 'Morges', 'Lavaux', 'Val de Ruz', 'Avenches', 'Rolle', 'Cossonay', 'Oron', 'Veveyse', 'St Maurice', 'La Chauxdfnd', 'Echallens', 'ValdeTravers', 'Martigwy', 'Moudon', 'Payerne', 'Aigle', 'Gruyere', 'Conthey', 'Aubonne', 'Le Locle', 'Rive Droite', 'Entremont', 'Lausanne', 'Boudry'), c('Agriculture', 'Examination', 'Education', 'Catholic', 'Infant.Mortality'))));is.numeric(argv[[1]]);
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric14#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric14#
 #argv <- list(structure(c(1386439154.20645, 1386469154.20645, 1386499154.20645, 1386529154.20645, 1386559154.20645, 1386589154.20645, 1386619154.20645, 1386649154.20645, 1386679154.20645, 1386709154.20645, 1386739154.20645, 1386769154.20645, 1386799154.20645, 1386829154.20645, 1386859154.20645, 1386889154.20645, 1386919154.20645, 1386949154.20645, 1386979154.20645, 1387009154.20645, 1387039154.20645, 1387069154.20645, 1387099154.20645, 1387129154.20645, 1387159154.20645, 1387189154.20645, 1387219154.20645, 1387249154.20645, 1387279154.20645, 1387309154.20645, 1387339154.20645, 1387369154.20645, 1387399154.20645, 1387429154.20645), class = c('POSIXct', 'POSIXt')));is.numeric(argv[[1]]);
 [1] FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric14#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric14#
 #is.numeric(structure(1L, class = c('POSIXct', 'POSIXt')))
 [1] FALSE
 
@@ -29523,7 +29958,7 @@ logical(0)
 #argv <- list(structure(c(79.5323303457107, 6, 86.1989970123773, 6, 69.7732394366197, 5, 98.0323303457106, 6, 108.032330345711, 6, 89.1989970123773, 6, 114.198997012377, 6, 116.698997012377, 6, 110.365663679044, 6, 124.365663679044, 6, 126.365663679044, 6, 118.032330345711, 6), .Dim = c(6L, 4L), .Dimnames = structure(list(V = c('Golden.rain', 'rep        ', 'Marvellous ', 'rep        ', 'Victory    ', 'rep        '), N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = c('V', 'N'))));is.numeric(argv[[1]]);
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric2#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric2#
 #argv <- list(structure(c(12784, 12874, 12965, 13057, 13149, 13239, 13330, 13422, 13514, 13604, 13695, 13787, 13879, 13970, 14061, 14153, 14245, 14335), class = 'Date'));is.numeric(argv[[1]]);
 [1] FALSE
 
@@ -29531,7 +29966,7 @@ logical(0)
 #argv <- list(structure(numeric(0), .Dim = c(3L, 0L)));is.numeric(argv[[1]]);
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric21#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric21#
 #argv <- list(structure(16146, class = 'Date'));is.numeric(argv[[1]]);
 [1] FALSE
 
@@ -29539,7 +29974,7 @@ logical(0)
 #argv <- list(structure(c(-3.001e+155, -1.067e+107, -1.976e+62, -9.961e+152, -2.059e+23, 0.5104), .Names = c('Min.', '1st Qu.', 'Median', 'Mean', '3rd Qu.', 'Max.'), class = c('summaryDefault', 'table')));is.numeric(argv[[1]]);
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric24#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumeric24#
 #argv <- list(structure(16352, class = 'Date'));do.call('is.numeric', argv)
 [1] FALSE
 
@@ -29571,6 +30006,10 @@ logical(0)
 #argv <- list(structure(list(a_string = c('foo', 'bar'), a_bool = FALSE, a_struct = structure(list(a = 1, b = structure(c(1, 3, 2, 4), .Dim = c(2L, 2L)), c = 'foo'), .Names = c('a', 'b', 'c')), a_cell = structure(list(1, 'foo', structure(c(1, 3, 2, 4), .Dim = c(2L, 2L)), 'bar'), .Dim = c(2L, 2L)), a_complex_scalar = 0+1i, a_list = list(1, structure(c(1, 3, 2, 4), .Dim = c(2L, 2L)), 'foo'), a_complex_matrix = structure(c(1+2i, 5+0i, 3-4i, -6+0i), .Dim = c(2L, 2L)), a_range = c(1, 2, 3, 4, 5), a_scalar = 1,     a_complex_3_d_array = structure(c(1+1i, 3+1i, 2+1i, 4+1i, 5-1i, 7-1i, 6-1i, 8-1i), .Dim = c(2L, 2L, 2L)), a_3_d_array = structure(c(1, 3, 2, 4, 5, 7, 6, 8), .Dim = c(2L, 2L, 2L)), a_matrix = structure(c(1, 3, 2, 4), .Dim = c(2L, 2L)), a_bool_matrix = structure(c(TRUE, FALSE, FALSE, TRUE), .Dim = c(2L, 2L))), .Names = c('a_string', 'a_bool', 'a_struct', 'a_cell', 'a_complex_scalar', 'a_list', 'a_complex_matrix', 'a_range', 'a_scalar', 'a_complex_3_d_array', 'a_3_d_array', 'a_matrix', 'a_bool_matrix')));is.numeric(argv[[1]]);
 [1] FALSE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isnumeric.testisnumericGenericDispatch#
+#{ is.numeric.cls <- function(x) 42; is.numeric(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_isobject.testIsObject#
 #{ f<-function() 42; class(f)<-"foo"; is.object(f) }
 [1] TRUE
@@ -29923,6 +30362,10 @@ Error in is.unsorted(x, strictly) : invalid 'strictly' argument
 #argv <- list(c(1L, 3L, 2L, 4L), TRUE); .Internal(is.unsorted(argv[[1]], argv[[2]]))
 [1] TRUE
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#
+#is.vector(1L, 'numeric');
+[1] TRUE
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_isvector.testIsVector#
 #{ is.vector(1) }
 [1] TRUE
@@ -30591,11 +31034,11 @@ NULL
 #argv <- list(FALSE, FALSE); .Internal(lbeta(argv[[1]], argv[[2]]))
 [1] Inf
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lchoose.testlchoose1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lchoose.testlchoose1#Ignored.Unimplemented#
 #argv <- list(FALSE, FALSE); .Internal(lchoose(argv[[1]], argv[[2]]))
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lchoose.testlchoose2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lchoose.testlchoose2#Ignored.Unimplemented#
 #argv <- list(50L, 0:48); .Internal(lchoose(argv[[1]], argv[[2]]))
  [1]  0.000000  3.912023  7.110696  9.883285 12.347138 14.566342 16.581245
  [8] 18.419524 20.101283 21.641728 23.052715 24.343699 25.522354 26.594991
@@ -30605,7 +31048,7 @@ NULL
 [36] 28.442320 27.566851 26.594991 25.522354 24.343699 23.052715 21.641728
 [43] 20.101283 18.419524 16.581245 14.566342 12.347138  9.883285  7.110696
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lchoose.testlchoose3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lchoose.testlchoose3#Ignored.Unimplemented#
 #argv <- list(0.5, 1:9); .Internal(lchoose(argv[[1]], argv[[2]]))
 [1] -0.6931472 -2.0794415 -2.7725887 -3.2425924 -3.5992673 -3.8869494 -4.1281114
 [8] -4.3357508 -4.5180723
@@ -30618,6 +31061,10 @@ NULL
 #length(quote(x))
 [1] 1
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength#
+#{ foo <- function(...) length(get('...')); foo(a=1, b=2, c=3, d=4); }
+[1] 4
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_length.testLength#
 #{ length(1) }
 [1] 1
@@ -31423,14 +31870,14 @@ Error in lgamma(as.raw(1)) :
 #{ lgamma(c(100, 2.2)) }
 [1] 359.13420537   0.09694747
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma1#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma1#
 #argv <- list(structure(c(2, 1, 1, 1, 3, 1, 1, 1, 4), .Dim = c(3L, 3L)));lgamma(argv[[1]]);
      [,1]      [,2]     [,3]
 [1,]    0 0.0000000 0.000000
 [2,]    0 0.6931472 0.000000
 [3,]    0 0.0000000 1.791759
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma2#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma2#
 #argv <- list(structure(c(2, 3, 2, 1, 4, 4, 7, 2, 11, 11, 15, 10, 7, 8, 13, 12), .Dim = c(4L, 4L), .Dimnames = structure(list(income = c('< 15k', '15-25k', '25-40k', '> 40k'), satisfaction = c('VeryD', 'LittleD', 'ModerateS', 'VeryS')), .Names = c('income', 'satisfaction'))));lgamma(argv[[1]]);
         satisfaction
 income       VeryD  LittleD ModerateS     VeryS
@@ -31457,7 +31904,7 @@ value out of range in 'lgamma'
 #argv <- list(numeric(0));lgamma(argv[[1]]);
 numeric(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_lgamma.testlgamma7#
 #argv <- list(structure(c(11.4065045686104, 9.40650456861037, 8.40650456861037, 11.4065045686104, 9.40650456861037, 6.40650456861036, 15.4065045686104, 9.40650456861037, 9.40650456861037, 8.40650456861037, 6.40650456861036, 7.40650456861036, 8.40650456861037, 7.40650456861036, 9.40650456861037, 13.4065045686104, 10.4065045686104, 11.4065045686104, 14.4065045686104, 10.4065045686104, 16.4065045686104, 10.4065045686104, 7.40650456861036, 9.40650456861037, 7.40650456861036, 13.4065045686104, 17.4065045686104, 4.40650456861036, 10.4065045686104, 5.40650456861036, 6.40650456861036, 4.40650456861036, 5.40650456861036, 4.40650456861036, 4.40650456861036, 8.40650456861037, 9.40650456861037, 5.40650456861036, 9.40650456861037, 7.40650456861036, 7.40650456861036, 8.40650456861037), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42')));lgamma(argv[[1]]);
         1         2         3         4         5         6         7         8
 16.068174 11.484342  9.355336 16.068174 11.484342  5.495664 26.283999 11.484342
@@ -31992,7 +32439,7 @@ attr(,"class")
 [1] 17
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist3#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist3#
 #argv <- list(x = c(9.5367431640625e-07, 1.9073486328125e-06, 3.814697265625e-06, 7.62939453125e-06, 1.52587890625e-05, 3.0517578125e-05, 6.103515625e-05, 0.0001220703125, 0.000244140625, 0.00048828125, 0.0009765625, 0.001953125, 0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024), y = c(3.69420518444359e+25, 2.30887824027777e+24, 1.44304890017492e+23, 9.01905562612606e+21, 5.63690976641081e+20, 35230686042118275072, 2201917878145066496, 137619867512235136, 8601241751556820, 537577617482832, 33598603095309.8, 2099913194115.17, 131244699796.888, 8202825028.58974, 512684387.219832, 32044730.0464007, 2003284.70114408, 125327.674230857, 7863.68742857025, 499.272560819512, 33.2784230289721, 2.7659432263306, 0.488936768533843, -0.282943224311172, 7.32218543045282e-05, -0.00636442868227041, -0.0483709204009262, -0.0704795507649514, 0.0349437746169591, -0.0264830837608839, 0.0200901469411759), xlab = NULL, ylab = NULL);list(argv[[1]],argv[[2]],argv[[3]],argv[[4]]);
 [[1]]
  [1] 9.536743e-07 1.907349e-06 3.814697e-06 7.629395e-06 1.525879e-05
@@ -32936,7 +33383,7 @@ attr(,"constant")
 [1] 0.5234843
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist65#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_list.testlist65#Output.IgnoreWhitespace#Ignored.OutputFormatting#
 #argv <- list(ANY = structure(function (x, y = NULL) .Internal(crossprod(x, y)), target = structure('ANY', class = structure('signature', package = 'methods'), .Names = 'x', package = 'methods'), defined = structure('ANY', class = structure('signature', package = 'methods'), .Names = 'x', package = 'methods'), generic = structure('crossprod', package = 'base'), class = structure('derivedDefaultMethod', package = 'methods')));list(argv[[1]]);
 [[1]]
 function (x, y = NULL)
@@ -33066,12 +33513,11 @@ character(0)
 #argv <- list('./myTst/data', NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); .Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_listfiles.testlistfiles3#Ignored.Unknown#
-#argv <- list('.', '^CITATION.*', FALSE, FALSE, TRUE, FALSE, FALSE, FALSE); .Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))
-[1] "com.oracle.truffle.r.native/gnur/R-3.3.2/library/base/CITATION"
-[2] "com.oracle.truffle.r.native/gnur/R-3.3.2/src/library/base/inst/CITATION"
-[3] "library/base/CITATION"
-[4] "rlibs/lattice/CITATION"
+##com.oracle.truffle.r.test.builtins.TestBuiltin_listfiles.testlistfiles3#Output.IgnoreWhitespace#
+#print('Work dir: ', getwd()); argv <- list('.', '^CITATION.*', FALSE, FALSE, TRUE, FALSE, FALSE, FALSE); sort(.Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])))
+Error in print.default("Work dir: ", getwd()) : invalid 'digits' argument
+In addition: Warning message:
+In print.default("Work dir: ", getwd()) : NAs introduced by coercion
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_listfiles.testlistfiles4#
 #argv <- list('mgcv', NULL, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE); .Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))
@@ -34373,7 +34819,7 @@ integer(0)
 [408] 4 1 1 1 2 2 2 3 3 3 4 4 4 1 1 1 2 2 2 3 3 3 4 4 4 1 1 1 2 2 2 3 3 3 4 4 4
 [445] 1 1 1 2 2 2 3 3 3 4 4 4 1 1 1 2 2 2 3 3 3 4 4 4
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_match.testmatch22#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_match.testmatch22#Ignored.ImplementationError#
 #argv <- list(c(NA, NA, 3, 4, 5), c(NA, NA, 4, 5), 0L, NA); .Internal(match(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] 0 0 0 3 4
 
@@ -34863,6 +35309,19 @@ function (..., na.rm = FALSE)  .Primitive("min")
 #x <- min; min <- 1; f <- function() { match.fun(x, descend=T)}; f()
 function (..., na.rm = FALSE)  .Primitive("min")
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_matchfun.testmatchfun#
+#{ foo <- function() { myfunc <- function(x) 42; lapply(2, 'myfunc'); }; boo <- function() { myfunc <- function(x) 42; lapply(2, 'myfunc'); }; list(foo = foo(), boo = boo()); }
+$foo
+$foo[[1]]
+[1] 42
+
+
+$boo
+$boo[[1]]
+[1] 42
+
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_matmul.testMatmulCorrectDimnames#
 #m1 <- matrix(1:6,3,2,dimnames=list(c('a','b','c'),c('c1','c2')));m2 <- matrix(c(3,4),2,1,dimnames=list(c('a2','b2'),c('col'))); m1 %*% m2; 
   col
@@ -34883,6 +35342,13 @@ c  33
 2    2
 3    3
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_matrix.testMatrixFastPath#
+#matrix(1:9,,3)
+     [,1] [,2] [,3]
+[1,]    1    4    7
+[2,]    2    5    8
+[3,]    3    6    9
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_matrix.testmatrix1#
 #argv <- list(NA_real_, 1L, 5L, FALSE, list('Residuals', c('Df', 'Sum Sq', 'Mean Sq', 'F value', 'Pr(>F)')), FALSE, FALSE); .Internal(matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))
           Df Sum Sq Mean Sq F value Pr(>F)
@@ -35682,7 +36148,7 @@ In max(as.double(NA), na.rm = TRUE) :
 #{ max(as.integer(NA), as.integer(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Ignored.Unknown#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #{ max(as.integer(NA), as.integer(NA), na.rm=TRUE) }
 [1] -Inf
 Warning message:
@@ -35693,7 +36159,7 @@ In max(as.integer(NA), as.integer(NA), na.rm = TRUE) :
 #{ max(as.integer(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Ignored.Unknown#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #{ max(as.integer(NA), na.rm=TRUE) }
 [1] -Inf
 Warning message:
@@ -35736,18 +36202,30 @@ In max(double()) : no non-missing arguments to max; returning -Inf
 Warning message:
 In max(double(0)) : no non-missing arguments to max; returning -Inf
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Ignored.Unknown#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #{ max(integer()) }
 [1] -Inf
 Warning message:
 In max(integer()) : no non-missing arguments to max; returning -Inf
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#Ignored.Unknown#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
 #{ max(integer(0)) }
 [1] -Inf
 Warning message:
 In max(integer(0)) : no non-missing arguments to max; returning -Inf
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
+#{ max(logical(0)) }
+[1] -Inf
+Warning message:
+In max(logical(0)) : no non-missing arguments to max; returning -Inf
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testMaximum#
+#{ max(seq_len(0)) }
+[1] -Inf
+Warning message:
+In max(seq_len(0)) : no non-missing arguments to max; returning -Inf
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_max.testmax1#
 #argv <- list(10L, 1L);max(argv[[1]],argv[[2]]);
 [1] 10
@@ -35865,16 +36343,16 @@ In max() : no non-missing arguments to max; returning -Inf
 #argv <- list(structure(list(x = c(-1, 1, 1, -1, -1, 1, 1, -1), y = c(-0.701149425287356, -0.701149425287356, -0.701149425287356, -0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356, 0.701149425287356), z = c(-0.4, -0.4, 0.4, 0.4, -0.4, -0.4, 0.4, 0.4)), .Names = c('x', 'y', 'z'), row.names = c(NA, -8L), class = 'data.frame'));max(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);
 [1] 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_maxcol.testmaxcol1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_maxcol.testmaxcol1#Ignored.Unimplemented#
 #argv <- list(structure(c(80.2, 17, 15, 12, 9.96, 22.2, 83.1, 45.1, 6, 9, 84.84, 22.2, 92.5, 39.7, 5, 5, 93.4, 20.2, 85.8, 36.5, 12, 7, 33.77, 20.3, 76.9, 43.5, 17, 15, 5.16, 20.6, 76.1, 35.3, 9, 7, 90.57, 26.6, 83.8, 70.2, 16, 7, 92.85, 23.6, 92.4, 67.8, 14, 8, 97.16, 24.9, 82.4, 53.3, 12, 7, 97.67, 21, 82.9, 45.2, 16, 13, 91.38, 24.4, 87.1, 64.5, 14, 6, 98.61, 24.5, 64.1, 62, 21, 12, 8.52, 16.5, 66.9, 67.5, 14, 7, 2.27, 19.1, 68.9, 60.7, 19, 12, 4.43, 22.7, 61.7, 69.3, 22, 5, 2.82, 18.7, 68.3, 72.6, 18, 2, 24.2, 21.2, 71.7, 34, 17, 8, 3.3, 20, 55.7, 19.4, 26, 28, 12.11, 20.2, 54.3, 15.2, 31, 20, 2.15, 10.8, 65.1, 73, 19, 9, 2.84, 20, 65.5, 59.8, 22, 10, 5.23, 18, 65, 55.1, 14, 3, 4.52, 22.4, 56.6, 50.9, 22, 12, 15.14, 16.7, 57.4, 54.1, 20, 6, 4.2, 15.3, 72.5, 71.2, 12, 1, 2.4, 21, 74.2, 58.1, 14, 8, 5.23, 23.8, 72, 63.5, 6, 3, 2.56, 18, 60.5, 60.8, 16, 10, 7.72, 16.3, 58.3, 26.8, 25, 19, 18.46, 20.9, 65.4, 49.5, 15, 8, 6.1, 22.5, 75.5, 85.9, 3, 2, 99.71, 15.1, 69.3, 84.9, 7, 6, 99.68, 19.8, 77.3, 89.7, 5, 2, 100, 18.3, 70.5, 78.2, 12, 6, 98.96, 19.4, 79.4, 64.9, 7, 3, 98.22, 20.2, 65, 75.9, 9, 9, 99.06, 17.8, 92.2, 84.6, 3, 3, 99.46, 16.3, 79.3, 63.1, 13, 13, 96.83, 18.1, 70.4, 38.4, 26, 12, 5.62, 20.3, 65.7, 7.7, 29, 11, 13.79, 20.5, 72.7, 16.7, 22, 13, 11.22, 18.9, 64.4, 17.6, 35, 32, 16.92, 23, 77.6, 37.6, 15, 7, 4.97, 20, 67.6, 18.7, 25, 7, 8.65, 19.5, 35, 1.2, 37, 53, 42.34, 18, 44.7, 46.6, 16, 29, 50.43, 18.2, 42.8, 27.7, 22, 29, 58.33, 19.3), .Dim = c(6L, 47L), .Dimnames = list(c('Fertility', 'Agriculture', 'Examination', 'Education', 'Catholic', 'Infant.Mortality'), c('Courtelary', 'Delemont', 'Franches-Mnt', 'Moutier', 'Neuveville', 'Porrentruy', 'Broye', 'Glane', 'Gruyere', 'Sarine', 'Veveyse', 'Aigle', 'Aubonne', 'Avenches', 'Cossonay', 'Echallens', 'Grandson', 'Lausanne', 'La Vallee', 'Lavaux', 'Morges', 'Moudon', 'Nyone', 'Orbe', 'Oron', 'Payerne', 'Paysd\'enhaut', 'Rolle', 'Vevey', 'Yverdon', 'Conthey', 'Entremont', 'Herens', 'Martigwy', 'Monthey', 'St Maurice', 'Sierre', 'Sion', 'Boudry', 'La Chauxdfnd', 'Le Locle', 'Neuchatel', 'Val de Ruz', 'ValdeTravers', 'V. De Geneve', 'Rive Droite', 'Rive Gauche'))), 1L); .Internal(max.col(argv[[1]], argv[[2]]))
 [1]  3 33 45 45 33  6
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_maxcol.testmaxcol2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_maxcol.testmaxcol2#Ignored.Unimplemented#
 #argv <- list(structure(c(0.0140185568997224, 0.0152950000405453, 0.013933189413423, 0.0141545247888734, 0.0144656253644622, 0.0138841285101751, 0.014995293880605, 0.0135531935867069, 0.0136464824425927, 0.0139216121812551, 0.0150015663096977, 0.0141230892456885, 0.013614290948012, 0.0169498879707739, 0.0167919904349555, 0.0164281655519131, 0.0145450130659148, 0.0154935322596005, 0.0140566103751186, 0.0137862479562347, 0.0138916844301758, 0.0144143878263478, 0.0153699249520618, 0.0156955405518398, 0.0143684930741837, 0.991123944314599, 0.772371856665358, 0.998388573397845, 0.997744681008954, 0.935000528851613, 0.995759465226583, 0.998319991897437, 0.998446741491899, 0.997291233910865, 0.998453850443283, 0.449550979690061, 0.99765492178392, 0.0744670889060699, 0.997953251276348, 0.998367231220745, 0.998303801028119, 0.996490251221358, 0.987068752837462, 0.963362766144961, 0.997745619693091, 0.998180187351627, 0.995230116685749, 0.99834615324817, 0.998224606721368, 0.998138182928866, 0.000101796455995556, 0.0169548122668949, 0.00010041243364593, 0.994976075194857, 0.000116262428296307, 0.000266333816370553, 0.000213420942072358, 0.000150164062855871, 9.91852669694001e-05, 0.962237984681016, 0.000109709045973819, 0.363503438381572, 0.000165884012322677, 0.000404227768170316, 0.000101407372837694, 0.000138346452367636, 0.76867700377653, 0.000101067307394145, 0.000798310678132636, 0.439735407970107, 0.000105640126458538, 0.000103729730504055, 0.000157422658078269, 0.00062878104546921, 0.000140302481934868, 0.987636544924171, 0.986762198204236, 0.987695606647598, 0.987542563977846, 0.987328468487257, 0.987729584212166, 0.986966061808917, 0.987959390267427, 0.987894530108167, 0.987703622276188, 0.986961786481457, 0.987564327481863, 0.987916920251847, 0.98565103396999, 0.98575611086066, 0.985998830615913, 0.98727397408636, 0.986627618096195, 0.987610242071539, 0.987797448350422, 0.987724349638781, 0.987363673212559, 0.986711269247982, 0.986491053812255, 0.987395229430566, 0.0127450421932153, 0.00673790924500044, 0.0168765170487183, 0.015797380803532, 0.00875985277873091, 0.0142537568101031, 0.0172964637554702, 0.0177648866573519, 0.0158550778308362, 0.0172334564486378, 0.00522951225361075, 0.016267073149734, 0.00347221059583105, 0.0218803200901225, 0.0183403081414579, 0.0180163362514856, 0.0146261930363668, 0.0119682371438135, 0.00971509310832369, 0.0157071233034631, 0.017455515535567, 0.0139105878597395, 0.0174050248646065, 0.0173796025035352, 0.0168918350504782, 0.00106971573173608, 0.0026383344434856, 0.00106703814487522, 0.0135614845327103, 0.0010949673490627, 0.00126684800065677, 0.0012190851300456, 0.00114670950680761, 0.00106469628452917, 0.00946684926508704, 0.00108427378412549, 0.00489096395354091, 0.00116581741675497, 0.00136406369196257, 0.00106938597766297, 0.00112914854449728, 0.00664571845549644, 0.00106837166942789, 0.00153810249624049, 0.0051794966429432, 0.00107683746869901, 0.00107356047093305, 0.00115632815053843, 0.001475874716352, 0.00113310775095649, 0.000705529701133523, 0.000706190813132159, 0.000705483416292851, 0.000705607277564461, 0.000705767694047911, 0.000705456690994395, 0.000706040550884142, 0.000705277731844386, 0.000705325918720134, 0.00070547711802582, 0.000706043725519247, 0.000705586003991082, 0.000705308033747408, 0.000706976814055453, 0.000706900888924168, 0.000706734153004456, 0.000705809204506355, 0.000706288779684405, 0.000705550244606539, 0.000705403095546089, 0.000705460812978617, 0.000705740784771567, 0.000706233802920496, 0.000706387215078423, 0.000705716602186515, 0.00537527373619432, 0.193553056279976, 0.000869791621482113, 0.00126068143747944, 0.0477132994644455, 0.00247011263414166, 0.000876993026210466, 0.000793804652755058, 0.00147446124252569, 0.000818798505743392, 0.527720370257185, 0.0012613575859543, 0.931485133910046, 0.000794860447953985, 0.000799403966921179, 0.000843774285071599, 0.00203097055872496, 0.00804383321163345, 0.0255537088264535, 0.00126855734163029, 0.000930853589102135, 0.00281671019786704, 0.000858777960111907, 0.000915470358337216, 0.000986308498091386, 0.999944492377256, 0.98624753604171, 0.999945310582066, 0.00303527549384713, 0.999935958318038, 0.99984366374275, 0.999876760118408, 0.999915533835607, 0.999946031942947, 0.0270168111120999, 0.999939809617296, 0.622685795280626, 0.999906081646851, 0.999754847875723, 0.999944697838299, 0.999922757726417, 0.198924025871316, 0.99994491987507, 0.99948964681356, 0.539122196215121, 0.999942224996369, 0.999943338667082, 0.999911124821608, 0.999605022779117, 0.999921489451661), .Dim = c(75L, 3L), .Dimnames = list(    NULL, c('c', 's', 'v'))), 1L); .Internal(max.col(argv[[1]], argv[[2]]))
  [1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 3 1 3
 [39] 1 1 1 1 1 1 1 1 1 1 1 1 3 3 3 1 3 3 3 3 3 1 3 3 3 3 3 3 1 3 3 3 3 3 3 3 3
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_maxcol.testmaxcol3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_maxcol.testmaxcol3#Ignored.Unimplemented#
 #argv <- list(structure(list(), .Dim = 0:1), 1L); .Internal(max.col(argv[[1]], argv[[2]]))
 integer(0)
 
@@ -35958,7 +36436,7 @@ integer(0)
 #argv <- structure(list(x = structure(c(31, NA, NA, 31), units = 'days',     class = 'difftime'), na.rm = TRUE), .Names = c('x', 'na.rm'));do.call('mean', argv)
 Time difference of 31 days
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_mean.testmean2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_mean.testmean2#Ignored.ImplementationError#
 #argv <- list(c(0.104166666666667, 0.285714285714286, 0.285714285714286, NA)); .Internal(mean(argv[[1]]))
 [1] NA
 
@@ -36388,7 +36866,7 @@ In min(as.double(NA), na.rm = TRUE) :
 #{ min(as.integer(NA), as.integer(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Ignored.ImplementationError#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ min(as.integer(NA), as.integer(NA), na.rm=TRUE) }
 [1] Inf
 Warning message:
@@ -36399,7 +36877,7 @@ In min(as.integer(NA), as.integer(NA), na.rm = TRUE) :
 #{ min(as.integer(NA), na.rm=FALSE) }
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Ignored.ImplementationError#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ min(as.integer(NA), na.rm=TRUE) }
 [1] Inf
 Warning message:
@@ -36446,13 +36924,13 @@ In min(double()) : no non-missing arguments to min; returning Inf
 Warning message:
 In min(double(0)) : no non-missing arguments to min; returning Inf
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Ignored.ImplementationError#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ min(integer()) }
 [1] Inf
 Warning message:
 In min(integer()) : no non-missing arguments to min; returning Inf
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#Ignored.ImplementationError#Output.IgnoreWarningContext#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_min.testMinimum#
 #{ min(integer(0)) }
 [1] Inf
 Warning message:
@@ -38015,7 +38493,7 @@ NULL
 #argv <- list(list(), NULL);`oldClass<-`(argv[[1]],argv[[2]]);
 list()
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_oldClassassign.testoldClassassign2#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_oldClassassign.testoldClassassign2#
 #argv <- list(NULL, NULL);`oldClass<-`(argv[[1]],argv[[2]]);
 NULL
 
@@ -38485,7 +38963,7 @@ In Ops.factor(argv[[1]]) : ‘<=’ not meaningful for factors
 [193] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [205] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators107#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators107#Ignored.OutputFormatting#
 #argv <- list(structure(0:100, .Tsp = c(1, 101, 1), class = 'ts'), 0);`<=`(argv[[1]],argv[[2]]);
 Time Series:
 Start = 1
@@ -38501,7 +38979,7 @@ Frequency = 1
  [85] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
  [97] FALSE FALSE FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators108#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators108#Ignored.OutputFormatting#
 #argv <- list(structure(c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 890, 900, 910, 920, 930, 940, 950, 960, 970, 980, 990, 1000, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96), .Dim = c(101L, 3L), .Dimnames = list(NULL, c('t1', '10 * t1', 't1 - 4')), .Tsp = c(1, 101, 1), class = c('mts', 'ts', 'matrix')), 0);`<=`(argv[[1]],argv[[2]]);
 Time Series:
 Start = 1
@@ -38610,7 +39088,7 @@ Frequency = 1
 100 FALSE   FALSE  FALSE
 101 FALSE   FALSE  FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators109#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators109#Ignored.OutputFormatting#
 #argv <- list(structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c('structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ', 'structure(c(419.147602949539, 391.474665943444, 435.919286153217, ', 'structure(c(484.030717075782, 462.954959541421, 526.353307750503, ')), .Tsp = c(1949, 1962.91666666667, 12), class = c('mts', 'ts', 'matrix')), 0);`<=`(argv[[1]],argv[[2]]);
          structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119,
 Jan 1949                                                          FALSE
@@ -39145,7 +39623,7 @@ logical(0)
 Warning message:
 In Ops.factor(argv[[1]]) : ‘!’ not meaningful for factors
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators113#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators113#Ignored.ImplementationError#
 #argv <- list(structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c('fm2', 'original'), class = c('ordered', 'factor')), 'original');`!=`(argv[[1]],argv[[2]]);
   [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
  [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
@@ -39231,7 +39709,7 @@ TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE
       Var1
 0.07413578
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators120#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators120#Ignored.OutputFormatting#
 #argv <- list(structure(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), .Tsp = c(1959, 1997.91666666667, 12), class = 'ts'), 10L);`==`(argv[[1]],argv[[2]]);
        Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep   Oct   Nov   Dec
 1959 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE FALSE
@@ -39345,7 +39823,7 @@ ab TRUE TRUE
 #argv <- list(c(1, 1, 10, 1, 1, 10, 10), 0);`!=`(argv[[1]],argv[[2]]);
 [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators130#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators130#
 #argv <- list(2, structure(list(2L), class = structure('L', package = '.GlobalEnv')));`==`(argv[[1]],argv[[2]]);
 [1] TRUE
 
@@ -39379,7 +39857,7 @@ blocks    1    2    3    4    5    6
 #argv <- list(NULL, NULL);`>`(argv[[1]],argv[[2]]);
 logical(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators137#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators137#Ignored.OutputFormatting#
 #argv <- list(structure(c(2, 1, 0, 1, 2), .Tsp = c(-1, 3, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);
 Time Series:
 Start = -1
@@ -39437,7 +39915,7 @@ Frequency = 1
    34    43    45    48   161
  TRUE  TRUE  TRUE  TRUE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators142#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators142#
 #argv <- list(structure(list(c(3L, 0L, 1L)), class = c('R_system_version', 'package_version', 'numeric_version')), structure('2.13.2', .Names = 'SweaveListingUtils'));`>`(argv[[1]],argv[[2]]);
 
 TRUE
@@ -39460,7 +39938,7 @@ In Ops.factor(argv[[1]]) : ‘>’ not meaningful for factors
 #argv <- list(10, 16L);`%%`(argv[[1]],argv[[2]]);
 [1] 10
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators147#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators147#Ignored.OutputFormatting#
 #argv <- list(structure(0, .Tsp = c(1, 1, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);
 Time Series:
 Start = 1
@@ -39947,7 +40425,7 @@ In Ops.factor(argv[[1]]) : ‘%%’ not meaningful for factors
 [23,]  924000  968000 1012000 1056000
 [24,] 1008000 1056000 1104000 1152000
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators185#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators185#Ignored.ImplementationError#
 #argv <- list(structure(numeric(0), .Dim = c(10L, 0L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), NULL)), structure(numeric(0), .Names = character(0)));`%*%`(argv[[1]],argv[[2]]);
    [,1]
 1     0
@@ -40041,7 +40519,7 @@ data frame with 0 columns and 0 rows
  [1]    NA FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [13] FALSE FALSE FALSE FALSE    NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators20#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators20#
 #argv <- list(structure(978350400, class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), c(1605796.39468342, 2250605.34500331, 3464617.14155227, 5492840.71388841, 1219772.31891453, 5433460.81468463, 5713396.02452517, 3996505.04896045, 3804881.73750043, 373683.36378783, 1245734.22899097, 1067815.23929536, 4155114.17658627, 2323059.28775668, 4656000.90815127, 3010085.0161314, 4340156.73798323, 5999048.06153476, 2298452.76521891, 4701988.69854212, 5653097.23772854, 1283037.96871752, 3941322.93728739, 759357.220374048, 1616150.60446411, 2335218.03170443, 80984.7349449992, 2312682.3643595, 5259890.2349174, 2058430.73196709, 2915620.53836882, 3626174.11217093, 2984937.82503158, 1126244.053334, 5003953.83093506, 4042886.83258742, 4803562.677674, 652843.049369752, 4377003.8016513, 2487387.75048405, 4965083.1868127, 3913420.05222291, 4735177.34632641, 3344763.6128068, 3203744.02103573, 4774026.48925781, 141107.11171478, 2886287.43334115, 4429033.49147737, 4189640.45360684, 2888643.47467571, 5208594.91588175, 2649611.30449176, 1480533.93148631, 427466.877132654, 601571.336723864, 1912811.28504127, 3136700.02379268, 4003806.70217425, 2460508.97211581, 5521073.589921, 1775713.19845319, 2776429.51241881, 2010322.98948616, 3936464.58484232, 1560485.48977822, 2894241.66157097, 4634646.93606645, 509525.338098407, 5293943.40406358, 2050713.12808245, 5076935.23793668, 2096741.74243212, 2018670.78146338, 2880972.33020514, 5396015.5351907, 5227525.11837333, 2358656.75892681, 4701235.58655381, 5809817.647174, 2628820.56391239, 4309288.77686709, 2419165.9430936, 1967729.81455922, 4578863.07127029, 1225882.75911659, 4300861.15349829, 735992.738373578, 1484714.53242749, 866704.886756837, 1449278.70250493, 356435.113750398, 3884559.38760191, 5299676.19835585, 4710875.96918643, 4822123.77896905, 2753499.89549071, 2480188.52821738, 4904143.22827756, 3658636.53959334));`+`(argv[[1]],argv[[2]]);
   [1] "2001-01-20 02:03:16 GMT" "2001-01-27 13:10:05 GMT"
   [3] "2001-02-10 14:23:37 GMT" "2001-03-06 01:47:20 GMT"
@@ -40464,7 +40942,7 @@ Frequency = 1
 #argv <- list(c(14, 2, 2, -7), c(14, 2, 2, -7));`!=`(argv[[1]],argv[[2]]);
 [1] FALSE FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators240#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators240#Ignored.OutputFormatting#
 #argv <- list(structure(numeric(0), .Dim = c(0L, 4L)), structure(numeric(0), .Dim = c(0L, 4L)));`-`(argv[[1]],argv[[2]]);
      [,1] [,2] [,3] [,4]
 
@@ -40556,7 +41034,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 #argv <- list(structure(c(1208822400, 1208908800, 1208995200, 1209081600, 1209168000, 1209254400), class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), structure(1209168000, class = c('POSIXct', 'POSIXt'), tzone = 'GMT'));`<=`(argv[[1]],argv[[2]]);
 [1]  TRUE  TRUE  TRUE  TRUE  TRUE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators257#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators257#Ignored.OutputFormatting#
 #argv <- list(structure(c(1, 1.4142135623731, 1.73205080756888, 2, 2.23606797749979, 2.44948974278318, 2.64575131106459, 2.82842712474619, 3, 3.16227766016838), id = 'test 1', class = structure('withId', package = '.GlobalEnv')), 1);`%%`(argv[[1]],argv[[2]]);
  [1] 0.0000000 0.4142136 0.7320508 0.0000000 0.2360680 0.4494897 0.6457513
  [8] 0.8284271 0.0000000 0.1622777
@@ -40678,7 +41156,7 @@ TRUE
 #argv <- list(3.001e+155, 0);`>`(argv[[1]],argv[[2]]);
 [1] TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators272#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators272#Ignored.OutputFormatting#
 #argv <- list(structure(c(4, 3, 2, 1, 0), .Tsp = c(-1, 3, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);
 Time Series:
 Start = -1
@@ -40707,7 +41185,7 @@ Frequency = 1
     1     3     5     7     9    11    13    15    17    19    21    23
 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators275#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators275#Ignored.OutputFormatting#
 #argv <- list(structure(c(0, 1, 2, 3, 4, 5, 6, 7, 8), .Tsp = c(3, 11, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);
 Time Series:
 Start = 3
@@ -40766,7 +41244,7 @@ Frequency = 1
 1961 484.5734 428.8782 368.5266 406.7287
 1962 479.0765 423.4949 363.4393 400.5921
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators284#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators284#Ignored.ImplementationError#
 #argv <- list(10, -324:-307);`^`(argv[[1]],argv[[2]]);
  [1]  0.000000e+00 9.881313e-324 9.881313e-323 9.980126e-322 9.999889e-321
  [6] 9.999889e-320 9.999987e-319 1.000000e-317 1.000000e-316 1.000000e-315
@@ -40810,7 +41288,7 @@ Tea     4   4
 #argv <- list(0.9, Inf);`^`(argv[[1]],argv[[2]]);
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators289#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators289#Ignored.ImplementationError#
 #argv <- list(0+0i, -3:3);`^`(argv[[1]],argv[[2]]);
 [1] Inf+0i Inf+0i Inf+0i   1+0i   0+0i   0+0i   0+0i
 
@@ -40831,11 +41309,11 @@ y x
 #argv <- list(integer(0), 1:3);`^`(argv[[1]],argv[[2]]);
 numeric(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators293#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators293#Ignored.ImplementationError#
 #argv <- list(c(NA, -2L, -1L, 0L, 1L, 2L, NA, NA, NA), 0L);`^`(argv[[1]],argv[[2]]);
 [1] 1 1 1 1 1 1 1 1 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators294#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators294#Ignored.OutputFormatting#
 #argv <- list(c(-4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i), c(-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2));`^`(argv[[1]],argv[[2]]);
   [1]   0.0000000-0.5000000i   0.0000000-0.5773503i   0.0000000-0.7071068i
   [4]   0.0000000-1.0000000i         Inf+0.0000000i   1.0000000+0.0000000i
@@ -41033,7 +41511,7 @@ In Ops.factor(argv[[1]]) : ‘^’ not meaningful for factors
 #argv <- list(c(1.1, 2, Inf), -Inf);`^`(argv[[1]],argv[[2]]);
 [1] 0 0 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators307#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators307#Ignored.OutputFormatting#
 #argv <- list(logical(0), structure(logical(0), .Dim = c(0L, 0L), .Dimnames = list(NULL, NULL)));`|`(argv[[1]],argv[[2]]);
 <0 x 0 matrix>
 
@@ -41047,7 +41525,7 @@ Error in |argv[[1]] : 1 argument passed to '|' which requires 2
 [1,]  TRUE TRUE
 [2,] FALSE TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators31#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators31#Ignored.OutputFormatting#
 #argv <- list(structure(FALSE, class = structure('foo', package = '.GlobalEnv')), NA);`+`(argv[[1]],argv[[2]]);
 [1] NA
 attr(,"class")
@@ -41072,7 +41550,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
    40    42    43    44    45    46    47    48    49    50    51    52    53
 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators312#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators312#Ignored.OutputFormatting#
 #argv <- list(structure(c(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0), .Dim = c(6L, 3L), .Dimnames = structure(list(`  p L s` = c('. . .', '. | .', '. . |', '. | |', '. . ?', '. | ?'), c('perm', 'LDL', 'super')), .Names = c('  p L s', ''))), c(4, 2, 1));`%*%`(argv[[1]],argv[[2]]);
 
   p L s [,1]
@@ -41123,7 +41601,7 @@ logical(0)
 [3,] 0.16785659 0.10764861 0.02839348 0.0030801280
 [4,] 0.02095225 0.01343695 0.00354414 0.0003844688
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators319#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators319#Ignored.ImplementationError#
 #argv <- list(numeric(0), structure(numeric(0), .Dim = c(1L, 0L)));`%*%`(argv[[1]],argv[[2]]);
 <0 x 0 matrix>
 
@@ -41512,7 +41990,7 @@ is.na.numeric_version               is.name                is.nan
 Warning message:
 In Ops.factor(left, right) : ‘+’ not meaningful for factors
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators340#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators340#Ignored.OutputFormatting#
 #argv <- list(structure(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Tsp = c(1790, 1970, 0.1), class = 'ts'), c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE));`&`(argv[[1]],argv[[2]]);
 Time Series:
 Start = 1790
@@ -41521,7 +41999,7 @@ Frequency = 0.1
  [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 [13] FALSE FALSE FALSE FALSE FALSE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators341#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators341#Ignored.OutputFormatting#
 #argv <- list(structure(c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Dim = c(101L, 3L), .Dimnames = list(NULL, c('t1', '10 * t1', 't1 - 4')), .Tsp = c(1, 101, 1), class = c('mts', 'ts', 'matrix')), structure(c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE), .Dim = c(101L, 3L), .Dimnames = list(NULL, c('t1', '10 * t1', 't1 - 4'))));`&`(argv[[1]],argv[[2]]);
 Time Series:
 Start = 1
@@ -41738,7 +42216,7 @@ FALSE FALSE FALSE
 [21] 4.494233e+307 8.988466e+307           Inf           Inf           Inf
 [26]           NaN            NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators351#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators351#Ignored.OutputFormatting#
 #argv <- list(.Primitive('log'));`(`(argv[[1]]);
 function (x, base = exp(1))  .Primitive("log")
 
@@ -41760,7 +42238,7 @@ function (x, base = exp(1))  .Primitive("log")
 2 NA  NA     NA NA    NA <NA>
 3  1 2.0 3.0+0i NA  TRUE  def
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators355#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators355#Ignored.OutputFormatting#
 #argv <- list(structure(NA, .Dim = c(1L, 1L), name = 'Sam', class = structure('Foo', package = '.GlobalEnv')));`(`(argv[[1]]);
      [,1]
 [1,]   NA
@@ -42149,7 +42627,7 @@ attr(,"class")
 #argv <- list(181L, 3.14159265358979);`*`(argv[[1]],argv[[2]]);
 [1] 568.6283
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators39#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators39#Ignored.OutputFormatting#
 #argv <- list(structure(c(-24.5833333333333, -5.08333333333333, 10.25, 19.4166666666667), .Dim = 4L, .Dimnames = structure(list(N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = 'N'), strata = structure('Within', .Names = 'N'), class = 'mtable'), structure(103.972222222222, class = 'mtable'));`+`(argv[[1]],argv[[2]]);
 N
    0.0cwt    0.2cwt    0.4cwt    0.6cwt
@@ -42702,7 +43180,7 @@ Frequency = 1
 #argv <- list(-3.14159265358979, 3.14159265358979);`:`(argv[[1]],argv[[2]]);
 [1] -3.1415927 -2.1415927 -1.1415927 -0.1415927  0.8584073  1.8584073  2.8584073
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators72#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators72#Ignored.ImplementationError#
 #argv <- list(structure(c(1L, 1L, 1L, 2L, 2L, 2L), .Label = c('1', '2'), class = 'factor'), structure(c(1L, 1L, 2L, 2L, 3L, 3L), .Label = c('1', '2', '3'), class = 'factor'));`:`(argv[[1]],argv[[2]]);
 [1] 1:1 1:1 1:2 2:2 2:3 2:3
 Levels: 1:1 1:2 1:3 2:1 2:2 2:3
@@ -42815,7 +43293,7 @@ FALSE FALSE FALSE FALSE FALSE FALSE
 gridSVG2
     TRUE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators9#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators9#Ignored.OutputFormatting#
 #argv <- list(structure(1:10, class = structure('NumericNotStructure', package = '.GlobalEnv')), 1);`+`(argv[[1]],argv[[2]]);
  [1]  2  3  4  5  6  7  8  9 10 11
 attr(,"class")
@@ -42845,7 +43323,7 @@ attr(,"class")attr(,"package")
 [205]  TRUE  TRUE  TRUE  TRUE FALSE FALSE  TRUE FALSE FALSE  TRUE FALSE FALSE
 [217] FALSE  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE  TRUE  TRUE FALSE FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators91#Ignored.OutputFormatting#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testoperators91#
 #argv <- list(structure(list(c(3L, 0L, 1L)), class = c('R_system_version', 'package_version', 'numeric_version')), structure('3.1', .Names = 'gridSVG2'));`<`(argv[[1]],argv[[2]]);
 
 TRUE
@@ -42978,7 +43456,7 @@ Error in options(NA) : invalid argument
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_options.testoptions5#Ignored.ReferenceError#
 #options(NULL);
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_options.testoptions5#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_options.testoptions5#
 #options(list(NULL));
 Error in options(list(NULL)) : list argument has no valid names
 
@@ -43486,6 +43964,10 @@ character(0)
 #{ paste(1:2, 1:3, FALSE, collapse=NULL) }
 [1] "1 1 FALSE" "2 2 FALSE" "1 3 FALSE"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_paste.testPaste#
+#{ paste(NULL, list(), sep = "=") }
+character(0)
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_paste.testPaste#
 #{ paste(character(0),31415) }
 [1] " 31415"
@@ -43632,7 +44114,7 @@ character(0)
 [218] " 0.43"   " 0.36"   " 0.36"   " 0.06"   " 1.00_*" " 0.26"   " 0.40"
 [225] " 0.36"   " 0.25"   " 0.57_*" " 0.57_*"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_paste0.testpaste011#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_paste0.testpaste011#
 #argv <- list(list(character(0), character(0), character(0)), NULL); .Internal(paste0(argv[[1]], argv[[2]]))
 character(0)
 
@@ -43713,6 +44195,11 @@ character(0)
 #argv <- structure(list(path = '/tmp/RtmpagC9oa/Pkgs/exNSS4'),     .Names = 'path');do.call('path.expand', argv)
 [1] "/tmp/RtmpagC9oa/Pkgs/exNSS4"
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_pathexpand.testpathexpand6#
+#path.expand('.'); wd <- getwd(); tryCatch({ setwd('/tmp'); path.expand('.') }, finally = { setwd(wd) })
+[1] "."
+[1] "."
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_plus_Date.testplus_Date1#
 #argv <- structure(list(e1 = structure(1, units = 'days', class = 'difftime'),     e2 = structure(14579, class = 'Date')), .Names = c('e1',     'e2'));do.call('+.Date', argv)
 [1] "2009-12-02"
@@ -44168,28 +44655,28 @@ numeric(0)
 #argv <- list(FALSE, 48L, 19L); .Internal(pmin(argv[[1]], argv[[2]], argv[[3]]))
 [1] 19
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot1#Ignored.Unimplemented#
 #argv <- list(1:2); .Internal(polyroot(argv[[1]]))
 [1] -0.5+0i
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot2#Ignored.Unimplemented#
 #argv <- list(FALSE); .Internal(polyroot(argv[[1]]))
 complex(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot3#Ignored.Unimplemented#
 #argv <- list(structure(c(1, 0.035205614861993, 0.237828814667385), .Names = c('', '', ''))); .Internal(polyroot(argv[[1]]))
 [1] -0.074015+2.049202i -0.074015-2.049202i
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot4#Ignored.Unimplemented#
 #argv <- list(c(1, -1.16348488318732, 0.667550726251972, -0.342308178637008)); .Internal(polyroot(argv[[1]]))
 [1] 1.174248+0.000000i 0.387949+1.528836i 0.387949-1.528836i
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot5#Ignored.Unimplemented#
 #argv <- list(c(1, 0.0853462951557329, -0.433003162033324, 0.141816558560935, -0.268523717394886, -0.0970671649038473)); .Internal(polyroot(argv[[1]]))
 [1]  0.319017+1.488058i -1.080644-0.000000i  1.176089+0.000000i
 [4]  0.319017-1.488058i -3.499850-0.000000i
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_polyroot.testpolyroot6#Ignored.Unimplemented#
 #argv <- list(c(1, 8, 28, 56, 70, 56, 28, 8, 1)); .Internal(polyroot(argv[[1]]))
 [1] -1-0i -1+0i -1+0i -1-0i -1-0i -1-0i -1-0i -1-0i
 
@@ -44848,15 +45335,15 @@ y ~ A:U + A:V - 1
     a      b
 1 abc def'gh
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printfunction.testprintfunction1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printfunction.testprintfunction1#Ignored.OutputFormatting#
 #argv <- list(.Primitive('+'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))
 function (e1, e2)  .Primitive("+")
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printfunction.testprintfunction2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printfunction.testprintfunction2#Ignored.OutputFormatting#
 #argv <- list(.Primitive('if'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))
 .Primitive("if")
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printfunction.testprintfunction3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printfunction.testprintfunction3#Ignored.ReferenceError#
 #argv <- list(.Primitive('c'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))
 function (...)  .Primitive("c")
 
@@ -44864,7 +45351,7 @@ function (...)  .Primitive("c")
 #argv <- list(.Primitive('.Internal'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))
 function (call)  .Primitive(".Internal")
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_printfunction.testprintfunction5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_printfunction.testprintfunction5#Ignored.OutputFormatting#
 #argv <- list(.Primitive('log'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))
 function (x, base = exp(1))  .Primitive("log")
 
@@ -44965,6 +45452,22 @@ age                        0.00561 0.012    0.00872  0.22  1.0 0.64000
 sex                       -1.65487 0.483    0.38527 11.74  1.0 0.00061
 frailty(id, dist = 't', c                           20.33 13.9 0.12000
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#prod()
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#prod(complex())
+[1] 1+0i
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#prod(numeric())
+[1] 1
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
+#{ foo <- function(...) prod(...); foo(); }
+[1] 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProd#
 #{prod('a')}
 Error in prod("a") : invalid 'type' (character) of argument
@@ -45037,15 +45540,15 @@ Error in prod("a") : invalid 'type' (character) of argument
 #{prod(list())}
 Error in prod(list()) : invalid 'type' (list) of argument
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#
 #{prod(c(1,2,3,4,5,NA),FALSE)}
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#
 #{prod(c(2,4,3,NA),TRUE)}
 [1] NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testProdNa#
 #{prod(c(2,4,NA))}
 [1] NA
 
@@ -45057,7 +45560,7 @@ Error in prod(list()) : invalid 'type' (list) of argument
 #prod( );
 [1] 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testprod11#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testprod11#
 #argv <- list(numeric(0));prod(argv[[1]]);
 [1] 1
 
@@ -45073,7 +45576,7 @@ Error in prod(list()) : invalid 'type' (list) of argument
 #argv <- list(structure(c(4L, 4L, 2L), .Names = c('Hair', 'Eye', 'Sex')));prod(argv[[1]]);
 [1] 32
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testprod5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testprod5#
 #argv <- list(integer(0));prod(argv[[1]]);
 [1] 1
 
@@ -45089,7 +45592,7 @@ Error in prod(list()) : invalid 'type' (list) of argument
 #argv <- list(c(0.138260298853371, 0.000636169906925458));prod(argv[[1]]);
 [1] 8.795704e-05
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testprod9#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_prod.testprod9#
 #argv <- list(NA_integer_);prod(argv[[1]]);
 [1] NA
 
@@ -45232,11 +45735,11 @@ Error: only atomic vectors can be sorted
 #argv <- list(FALSE); .Internal(pushBackLength(argv[[1]]))
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_putconst.testputconst1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_putconst.testputconst1#Ignored.Unimplemented#
 #argv <- list(list(NULL), 0, NULL); .Internal(putconst(argv[[1]], argv[[2]], argv[[3]]))
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_putconst.testputconst2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_putconst.testputconst2#Ignored.Unimplemented#
 #argv <- list(list(list(), NULL), 1, list()); .Internal(putconst(argv[[1]], argv[[2]], argv[[3]]))
 [1] 0
 
@@ -45552,23 +46055,23 @@ x <- x + 1
 #{ typeof(quote(x)) }
 [1] "symbol"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort1#Ignored.ImplementationError#
 #argv <- list(structure(1L, .Label = c('Ctl', 'Trt'), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort2#Ignored.ImplementationError#
 #argv <- list(structure(c(2L, 1L, 3L), .Label = c('1', '2', NA), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort3#Ignored.ImplementationError#
 #argv <- list(structure(c(3L, 7L, 1L, 5L, 10L, 8L, 2L, 6L, 4L, 9L), .Label = c('Svansota', 'No. 462', 'Manchuria', 'No. 475', 'Velvet', 'Peatland', 'Glabron', 'No. 457', 'Wisconsin No. 38', 'Trebi'), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort5#Ignored.ImplementationError#
 #argv <- list(structure(c(64L, 67L, 92L, 71L, 74L, 69L, 78L, 94L, 95L, 80L, 119L, 114L, 97L, 72L, 75L, 96L, 99L, 54L, 101L, 93L, 58L, 138L, NA, 139L, 126L, 84L, 79L, 62L, 52L, 68L, 81L, 87L, 109L, 35L, 51L, 61L, 59L, 131L, 137L, 73L, 77L, 70L, 90L, 107L, 29L, 89L, 57L, 66L, 76L, 37L, 155L, 16L, 102L, 56L, 123L, 36L, 60L, 40L, 43L, 85L, 65L, 11L, 47L, 103L, 86L, 13L, 63L, 132L, 91L, 98L, 105L, 134L, 14L, 124L, 117L, 55L, 41L, 24L, 50L, 110L, 129L, 88L, 141L, 145L, 133L, 25L, 46L, 120L, 83L, 121L, 104L, 53L, 44L, 113L, 100L, 19L, 108L, 31L, 82L, 127L, 111L, 116L, 38L, 150L, 48L, 22L, 112L, 140L, 27L, 149L, 115L, 130L, 8L, 28L, 106L, 23L, 125L, 33L, 39L, 32L, 15L, 49L, 144L, 7L, 17L, 122L, 118L, 5L, 128L, 12L, 45L, 21L, 42L, 147L, 26L, 1L, 4L, 153L, 151L, 3L, 136L), .Label = c('(360,365]', '(365,370]', '(370,375]', '(375,380]', '(380,385]', '(385,390]', '(390,395]', '(395,400]', '(400,405]', '(405,410]', '(410,415]', '(415,420]', '(420,425]', '(425,430]', '(430,435]', '(435,440]', '(440,445]', '(445,450]', '(450,455]', '(455,460]', '(460,465]', '(465,470]', '(470,475]', '(475,480]', '(480,485]', '(485,490]', '(490,495]', '(495,500]', '(500,505]', '(505,510]', '(510,515]', '(515,520]', '(520,525]', '(525,530]', '(530,535]', '(535,540]', '(540,545]', '(545,550]', '(550,555]', '(555,560]', '(560,565]', '(565,570]', '(570,575]', '(575,580]', '(580,585]', '(585,590]', '(590,595]', '(595,600]', '(600,605]', '(605,610]', '(610,615]', '(615,620]', '(620,625]', '(625,630]', '(630,635]', '(635,640]', '(640,645]', '(645,650]', '(650,655]', '(655,660]', '(660,665]', '(665,670]', '(670,675]', '(675,680]', '(680,685]', '(685,690]', '(690,695]', '(695,700]', '(700,705]', '(705,710]', '(710,715]', '(715,720]', '(720,725]', '(725,730]', '(730,735]', '(735,740]', '(740,745]', '(745,750]', '(750,755]', '(755,760]', '(760,765]', '(765,770]', '(770,775]', '(775,780]', '(780,785]', '(785,790]', '(790,795]', '(795,800]', '(800,805]', '(805,810]', '(810,815]', '(815,820]', '(820,825]', '(825,830]', '(830,835]', '(835,840]', '(840,845]', '(845,850]', '(850,855]', '(855,860]', '(860,865]', '(865,870]', '(870,875]', '(875,880]', '(880,885]', '(885,890]', '(890,895]', '(895,900]', '(900,905]', '(905,910]', '(910,915]', '(915,920]', '(920,925]', '(925,930]', '(930,935]', '(935,940]', '(940,945]', '(945,950]', '(950,955]', '(955,960]', '(960,965]', '(965,970]', '(970,975]', '(975,980]', '(980,985]', '(985,990]', '(990,995]', '(995,1000]', '(1000,1005]', '(1005,1010]', '(1010,1015]', '(1015,1020]', '(1020,1025]', '(1025,1030]', '(1030,1035]', '(1035,1040]', '(1040,1045]', '(1045,1050]', '(1050,1055]', '(1055,1060]', '(1060,1065]', '(1065,1070]', '(1070,1075]', '(1075,1080]', '(1080,1085]', '(1085,1090]', '(1090,1095]', '(1095,1100]', '(1100,1105]', '(1105,1110]', '(1110,1115]', '(1115,1120]', '(1120,1125]', '(1125,1130]', '(1130,1135]'), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))
 NULL
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_radixsort.testradixsort6#Ignored.ImplementationError#
 #argv <- list(structure(integer(0), .Label = character(0), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))
 NULL
 
@@ -45632,6 +46135,30 @@ NULL
 #range(c(T, F, NA, NA, T), na.rm=T)
 [1] 0 1
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testRangeCharacter#
+#range(c('1', '2', '3'))
+[1] "1" "3"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testRangeCharacter#
+#range(c('1', '2', '3'), finite=T)
+[1] "1" "3"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testRangeCharacter#
+#range(c('1', '2', '3'), na.rm=T)
+[1] "1" "3"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testRangeCharacter#
+#range(c('a', 'b', 'c'))
+[1] "a" "c"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testRangeCharacter#
+#range(c('a', 'b', 'c'), finite=T)
+[1] "a" "c"
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testRangeCharacter#
+#range(c('a', 'b', 'c'), na.rm=T)
+[1] "a" "c"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_range.testrange1#
 #argv <- list(c(0.0303542455381287, 0.030376780241572, 0.030376780241572, 0.0317964665585001, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0332612222823148, 0.0334189652064179, 0.0352217414818821, 0.0354245538128718, 0.0354245538128718, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0376780241572021, 0.0406300703082748, 0.0406300703082748, 0.0406300703082748, 0.0440778799351001, 0.048021453037678, 0.0524607896160087, 0.0524607896160087, 0.0524607896160087, 0.0628267531999279, 0.0693167477915991, 0.0981611681990265, 0.134937804218497, 0.179646655850009, 0.437804218496485));range(argv[[1]][[1]],argv[[1]][[2]], na.rm = FALSE);
 [1] 0.03035425 0.03037678
@@ -47043,7 +47570,7 @@ structure(integer(0), .Dim = c(3L, 0L), .Dimnames = list(NULL,
 #readChar(as.raw(c(65,66,67)), nchars=3);
 [1] "ABC"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_regexec.testregexec1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_regexec.testregexec1#Ignored.ReferenceError#
 #argv <- list('^(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)', 'http://stat.umn.edu:80/xyz', FALSE, FALSE, FALSE); .Internal(regexec(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [[1]]
 [1]  1  1  1  8 20 21 23
@@ -47505,6 +48032,10 @@ Error in rep(c(7, 42), times = c(2, NA)) : invalid 'times' argument
 Error in rep(function() 42) :
   attempt to replicate an object of type 'closure'
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
+#{ rep.cls <- function(x) 42; rep(structure(c(1,2), class='cls')); }
+[1] 42
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep.testRep#
 #{ x <- 1 ; names(x) <- c("X") ; rep(x, times=0) }
 named numeric(0)
@@ -47815,6 +48346,10 @@ logical(0)
  [1] A B C D A B C D A B
 Levels: A B C D
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen#
+#rep_len(1L, 4L)
+[1] 1 1 1 1
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rep_len.testRepLen#
 #{ rep_len("RepeatTest", 5) }
 [1] "RepeatTest" "RepeatTest" "RepeatTest" "RepeatTest" "RepeatTest"
@@ -48057,7 +48592,7 @@ Error in rep.int(c(1 + (0+2i), 20 + (0+30i), 100 - (0+400i)), -3) :
 #argv <- list(NA_character_, 5L); .Internal(rep.int(argv[[1]], argv[[2]]))
 [1] NA NA NA NA NA
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testrepint13#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_repint.testrepint13#Ignored.OutputFormatting#
 #argv <- list(structure(1:4, .Label = c('A', 'B', 'C', 'D'), class = 'factor', .Names = c('a', 'b', 'c', 'd')), 2); .Internal(rep.int(argv[[1]], argv[[2]]))
 [1] A B C D A B C D
 Levels: A B C D
@@ -48482,7 +49017,7 @@ Error: a matrix-like object is required as argument to 'row'
 #{ rowMeans(matrix(as.complex(1:6), nrow=2)) }
 [1] 3+0i 4+0i
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_rowMeans.testRowMeans#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_rowMeans.testRowMeans#Ignored.OutputFormatting#
 #{rowMeans(matrix(NA,NA,NA),TRUE)}
 Error in matrix(NA, NA, NA) : invalid 'nrow' value (too large or NA)
 
@@ -48727,12 +49262,12 @@ numeric(0)
 [1] "1" "2"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" } else { x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, NULL, ug, FALSE,as.character(ug))) }
-Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" }"
+#if (!any(R.version$engine == "FastR")) { cat("Error: invalid 'g' argument\n") } else { x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, NULL, ug, FALSE,as.character(ug))) }
+Error: invalid 'g' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" } else { { x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug))); } }
-Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\n invalid 'g' argument" }"
+#if (!any(R.version$engine == "FastR")) { cat("Error: invalid 'g' argument\n") } else { x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug))); }
+Error: invalid 'g' argument
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_rowsum.testRowsumArgCoverage#Output.IgnoreErrorMessage#
 #x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, , ug, FALSE,as.character(ug)))
@@ -49040,7 +49575,7 @@ Error in sample.int(x, size, replace, prob) : invalid 'replace' argument
 #{ set.seed(4357, "default"); x <- 5 ; prob <- c(.5, .5, .5, .5, .5); sample(x, 5, FALSE, prob) ; }
 [1] 4 1 5 3 2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.ImplementationError#
 #{ set.seed(4357, "default"); x <- 5 ; sample(x, 6, FALSE, NULL) ;}
 Error in sample.int(x, size, replace, prob) :
   cannot take a sample larger than the population when 'replace = FALSE'
@@ -49050,11 +49585,11 @@ Error in sample.int(x, size, replace, prob) :
  [1] "Tails" "Heads" "Heads" "Tails" "Tails" "Heads" "Heads" "Tails" "Tails"
 [10] "Tails"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.ImplementationError#
 #{ set.seed(4357, "default"); x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, FALSE, prob) ; }
 [1] 4 2 3 5 1
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.ImplementationError#
 #{ set.seed(4357, "default"); x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, TRUE, prob) ; }
 [1] 4 2 2 3 4
 
@@ -49078,7 +49613,7 @@ Error in sample.int(x, size, replace, prob) :
 #{ set.seed(9567, "Marsaglia-Multicarry"); x <- 5 ; prob <- c(.5, .5, .5, .5, .5) ; sample(x, 5, FALSE, prob) ; }
 [1] 5 2 1 4 3
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.ImplementationError#
 #{ set.seed(9567, "Marsaglia-Multicarry"); x <- 5 ; sample(x, 6, FALSE, NULL) ;}
 Error in sample.int(x, size, replace, prob) :
   cannot take a sample larger than the population when 'replace = FALSE'
@@ -49108,11 +49643,11 @@ Error in sample.int(x, size, replace, prob) :
  [1] "Heads" "Tails" "Tails" "Heads" "Tails" "Tails" "Heads" "Heads" "Heads"
 [10] "Heads"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.ImplementationError#
 #{ set.seed(9567, "Marsaglia-Multicarry");x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, FALSE, prob) ; }
 [1] 3 5 2 1 4
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sample.testSample#Ignored.ImplementationError#
 #{ set.seed(9567, "Marsaglia-Multicarry");x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, TRUE, prob) ; }
 [1] 3 5 3 1 5
 
@@ -61819,6 +62354,10 @@ integer(0)
 #seq(integer())
 integer(0)
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_seq.testSeqArgMatching#
+#{ foo <- function(beg, end, by, len) seq(beg, end, by, length.out = len); foo(beg=1, by=1, len=10) }
+ [1]  1  2  3  4  5  6  7  8  9 10
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_seq.testSeqDispatch#
 #{ d <- as.Date(1, origin = "1970-01-01"); seq(d, by=1, length.out=4) }
 [1] "1970-01-02" "1970-01-03" "1970-01-04" "1970-01-05"
@@ -62446,6 +62985,14 @@ 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_seqint.testseqintGenericDispatch#
+#{ seq.int.cls <- function(x) 42; seq.int(structure(c(1,2), class='cls')); }
+[1] 1 2
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_serialize.testSerializeWithPromises#
+#{ f <- function(...) serialize(environment()[['...']],NULL); x <- unserialize(f(a=3,b=2,c=1)); typeof(x) }
+[1] "..."
+
 ##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
@@ -63091,7 +63638,7 @@ An object of class “signature”
              .Object
 "ObjectsWithPackage"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object10#Ignored.ImplementationError#
 #argv <- list(structure(function (object) cat('I am a \'foo\'\n'), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('MethodDefinition', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 Method Definition:
 
@@ -63103,7 +63650,7 @@ Signatures:
 target
 defined
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object11#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object11#Ignored.OutputFormatting#
 #argv <- list(structure(function (x = 1, nrow, ncol) standardGeneric('diag'), generic = character(0), package = character(0), group = list(), valueClass = character(0), signature = character(0), default = quote(`\001NULL\001`), skeleton = quote(`<undef>`()), class = structure('standardGeneric', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 standardGeneric for "" defined from package ""
 
@@ -63112,7 +63659,7 @@ standardGeneric("diag")
 Methods may be defined for arguments:
 Use  showMethods("")  for currently available ones.
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object12#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object12#Ignored.ImplementationError#
 #argv <- list(structure(list(`NA` = structure(function (object) cat('I am a \'foo\'\n'), target = structure('foo', .Names = 'object', package = 'myTst', class = structure('signature', package = 'methods')), defined = structure('foo', .Names = 'object', package = 'myTst', class = structure('signature', package = 'methods')), generic = structure('show', package = 'methods'), class = structure('MethodDefinition', package = 'methods'))), .Names = NA_character_, arguments = structure('object', simpleOnly = TRUE), signatures = list(), generic = structure(function (object) standardGeneric('show'), generic = structure('show', package = 'methods'), package = 'methods', group = list(), valueClass = character(0), signature = structure('object', simpleOnly = TRUE), default = structure(function (object) showDefault(object, FALSE), target = structure('ANY', class = structure('signature', package = 'methods'), .Names = 'object', package = 'methods'), defined = structure('ANY', class = structure('signature', package = 'methods'), .Names = 'object', package = 'methods'), generic = structure('show', package = 'methods'), class = structure('derivedDefaultMethod', package = 'methods')), skeleton = quote((function (object) showDefault(object, FALSE))(object)), class = structure('standardGeneric', package = 'methods')), class = structure('listOfMethods', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 An object of class  “listOfMethods”
 $<NA>
@@ -63155,7 +63702,7 @@ Slot generic:
 Error in cat(class(object), " for \"", object@generic, "\" defined from package \"",  :
   trying to get slot "generic" from an object (class "standardGeneric") that is not an S4 object
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object13#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object13#Ignored.OutputFormatting#
 #argv <- list(structure(function (x, type = c('O', 'I', 'F', 'M', '2')) {    if (identical('2', type)) {        svd(x, nu = 0L, nv = 0L)$d[1L]    } else .Internal(La_dlange(x, type))}, target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 Method Definition (Class "derivedDefaultMethod"):
 
@@ -63172,7 +63719,7 @@ Signatures:
 target
 defined
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object14#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object14#Ignored.OutputFormatting#
 #argv <- list(structure(function (x, y, ...) UseMethod('plot'), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 Method Definition (Class "derivedDefaultMethod"):
 
@@ -63184,7 +63731,7 @@ Signatures:
 target
 defined
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object2#Ignored.OutputFormatting#
 #argv <- list(structure(function (x, ...) standardGeneric('toeplitz'), generic = character(0), package = character(0), group = list(), valueClass = character(0), signature = character(0), default = quote(`\001NULL\001`), skeleton = quote(`<undef>`()), class = structure('standardGeneric', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 standardGeneric for "" defined from package ""
 
@@ -63193,14 +63740,14 @@ standardGeneric("toeplitz")
 Methods may be defined for arguments:
 Use  showMethods("")  for currently available ones.
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object3#Output.IgnoreWhitespace#
 #argv <- list(structure(character(0), package = character(0), class = structure('ObjectsWithPackage', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 An object of class "ObjectsWithPackage":
 
 Object:
 Package:
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object4#Ignored.OutputFormatting#
 #argv <- list(structure(function (qr, complete = FALSE, Dvec) standardGeneric('qr.Q'), generic = character(0), package = character(0), group = list(), valueClass = character(0), signature = character(0), default = quote(`\001NULL\001`), skeleton = quote(`<undef>`()), class = structure('standardGeneric', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 standardGeneric for "" defined from package ""
 
@@ -63215,7 +63762,7 @@ An object of class “signature”
           <NA>           <NA>           <NA>           <NA>
 "nonStructure"          "ANY"          "ANY"          "ANY"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object6#Ignored.ImplementationError#
 #argv <- list(structure(function (x) .Internal(drop(x)), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 Method Definition (Class "derivedDefaultMethod"):
 
@@ -63227,7 +63774,7 @@ Signatures:
 target
 defined
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object7#Ignored.ImplementationError#
 #argv <- list(structure(function (x, y = NULL) .Internal(crossprod(x, y)), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 Method Definition (Class "derivedDefaultMethod"):
 
@@ -63239,7 +63786,7 @@ Signatures:
 target
 defined
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object8#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setS4Object.testsetS4Object8#Ignored.ImplementationError#
 #argv <- list(structure(function (x, i, j, ...) x@aa[[i]], target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('MethodDefinition', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 Method Definition:
 
@@ -63255,10 +63802,10 @@ defined
 #argv <- list(numeric(0), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))
 numeric(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setSessionTimeLimit.testsetSessionTimeLimit1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setSessionTimeLimit.testsetSessionTimeLimit1#Ignored.Unimplemented#
 #argv <- list(NULL, NULL); .Internal(setSessionTimeLimit(argv[[1]], argv[[2]]))
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_setSessionTimeLimit.testsetSessionTimeLimit2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_setSessionTimeLimit.testsetSessionTimeLimit2#Ignored.Unimplemented#
 #argv <- list(FALSE, Inf); .Internal(setSessionTimeLimit(argv[[1]], argv[[2]]))
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_setTimeLimit.testsetTimeLimit1#
@@ -63564,6 +64111,14 @@ Error in signif(42.1234, character()) :
      [,1] [,2]
 [1,]   40   42
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif#
+#{ signif(8.125, 3) }
+[1] 8.12
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif#
+#{ signif(8.175, 3) }
+[1] 8.18
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testSignif#
 #{ signif(c(42.1234, 7.1234), 1) }
 [1] 40  7
@@ -63588,7 +64143,7 @@ attr(,"foo")
 attr(,"foo")
 [1] "foo"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testsignif1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_signif.testsignif1#Ignored.ImplementationError#
 #argv <- list(structure(c(0, NaN, 0, 4.94065645841247e-324), class = 'integer64'));do.call('signif', argv)
 [1]  0.000000e+00           NaN  0.000000e+00 4.940656e-324
 attr(,"class")
@@ -63930,11 +64485,11 @@ Error in sinpi() : 0 arguments passed to 'sinpi' which requires 1
 [4,]  0.77779571 -0.7607391 -0.2539115
 [5,]  0.12480246  0.8953586  0.6454113
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sinpi.testsin6#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sinpi.testsin6#
 #argv <- list(c(-0.560475646552213-0.710406563699301i, -0.23017748948328+0.25688370915653i, 1.55870831414912-0.24669187846237i, 0.070508391424576-0.347542599397733i, 0.129287735160946-0.951618567265016i, 1.71506498688328-0.04502772480892i, 0.460916205989202-0.784904469457076i, -1.26506123460653-1.66794193658814i, -0.686852851893526-0.380226520287762i, -0.445661970099958+0.918996609060766i, 1.22408179743946-0.57534696260839i, 0.359813827057364+0.607964322225033i, 0.40077145059405-1.61788270828916i, 0.11068271594512-0.055561965524539i, -0.555841134754075+0.519407203943462i, 1.78691313680308+0.30115336216671i, 0.497850478229239+0.105676194148943i, -1.96661715662964-0.64070600830538i, 0.701355901563686-0.849704346033582i, -0.47279140772793-1.02412879060491i, -1.06782370598685+0.11764659710013i, -0.217974914658295-0.947474614184802i, -1.02600444830724-0.49055744370067i, -0.72889122929114-0.256092192198247i, -0.62503926784926+1.84386200523221i, -1.68669331074241-0.65194990169546i, 0.837787044494525+0.235386572284857i, 0.153373117836515+0.077960849563711i, -1.13813693701195-0.96185663413013i, 1.25381492106993-0.0713080861236i, 0.42646422147681+1.44455085842335i, -0.295071482992271+0.451504053079215i, 0.895125661045022+0.04123292199294i, 0.878133487533042-0.422496832339625i, 0.82158108163749-2.05324722154052i, 0.68864025410009+1.13133721341418i, 0.55391765353759-1.46064007092482i, -0.061911710576722+0.739947510877334i, -0.30596266373992+1.90910356921748i, -0.38047100101238-1.4438931609718i, -0.694706978920513+0.701784335374711i, -0.207917278019599-0.262197489402468i, -1.26539635156826-1.57214415914549i, 2.16895596533851-1.51466765378175i, 1.20796199830499-1.60153617357459i, -1.12310858320335-0.5309065221703i, -0.40288483529908-1.4617555849959i, -0.466655353623219+0.687916772975828i, 0.77996511833632+2.10010894052567i, -0.08336906647183-1.28703047603518i, 0.253318513994755+0.787738847475178i, -0.028546755348703+0.76904224100091i, -0.042870457291316+0.332202578950118i, 1.36860228401446-1.00837660827701i, -0.225770985659268-0.119452606630659i, 1.51647060442954-0.28039533517025i, -1.54875280423022+0.56298953322048i, 0.584613749636069-0.372438756103829i, 0.123854243844614+0.976973386685621i, 0.215941568743973-0.374580857767014i, 0.37963948275988+1.05271146557933i, -0.5023234531093-1.04917700666607i, -0.33320738366942-1.26015524475811i, -1.01857538310709+3.2410399349424i, -1.07179122647558-0.41685758816043i, 0.303528641404258+0.298227591540715i, 0.448209778629426+0.636569674033849i, 0.053004226730504-0.483780625708744i, 0.922267467879738+0.516862044313609i, 2.05008468562714+0.36896452738509i, -0.491031166056535-0.215380507641693i, -2.30916887564081+0.06529303352532i, 1.00573852446226-0.03406725373846i, -0.70920076258239+2.12845189901618i, -0.688008616467358-0.741336096272828i, 1.0255713696967-1.09599626707466i, -0.284773007051009+0.037788399171079i, -1.22071771225454+0.31048074944314i, 0.18130347974915+0.436523478910183i, -0.138891362439045-0.458365332711106i, 0.00576418589989-1.06332613397119i, 0.38528040112633+1.26318517608949i, -0.370660031792409-0.349650387953555i, 0.644376548518833-0.865512862653374i, -0.220486561818751-0.236279568941097i, 0.331781963915697-0.197175894348552i, 1.09683901314935+1.10992028971364i, 0.435181490833803+0.084737292197196i, -0.325931585531227+0.754053785184521i, 1.14880761845109-0.49929201717226i, 0.993503855962119+0.214445309581601i, 0.54839695950807-0.324685911490835i, 0.238731735111441+0.094583528173571i, -0.627906076039371-0.895363357977542i, 1.36065244853001-1.31080153332797i, -0.60025958714713+1.99721338474797i, 2.18733299301658+0.60070882367242i, 1.53261062618519-1.25127136162494i, -0.235700359100477-0.611165916680421i, -1.02642090030678-1.18548008459731i));sinpi(argv[[1]]);
 Error in sinpi(argv[[1]]) : unimplemented complex function
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sinpi.testsin7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sinpi.testsin7#Output.MissingWarning#
 #argv <- list(Inf);sinpi(argv[[1]]);
 [1] NaN
 Warning message:
@@ -64401,7 +64956,7 @@ $`1`
 #argv <- list(character(0), structure(integer(0), .Label = character(0), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))
 named list()
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit16#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit16#
 #argv <- list(structure(c(47.432, 12.482), .Names = c('(Intercept)', 'group2')), structure(1:2, .Label = c('0', '1'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))
 $`0`
 (Intercept)
@@ -64547,7 +65102,7 @@ $`41`
 [1] 0.1158763
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit2#
 #argv <- list(structure(c(-1.13864415195445, 0.574433648632919, 0.61125743366192, 0.291104607198021, 1.44367450704693, 0.408616385050392, -0.252815027721455, 0.73544465026571, -0.711029326417947, -0.611820918993561, -0.963259276248408, -0.28935033673839, -0.482346616963731, 0.575284398820533, 0.0664802498883062, 0.0889008730409177, -0.527009741835806, -0.572160487726669, 0.458433701366337, 0.0259549922279207, 0.79246010222197, 0.200856719794408, 0.681708382019133, 1.24959713166139, 2.28504683598586, 0.885201117877485, 0.275047494865858, 0.0611635446204713, -0.226340664609402, -0.701634984067551, -1.36331112409512, -0.470720710127998, 0.0116712292760789, 0.680960771805182, 1.25010637890252, -0.168484448953506, -0.703880448859559, -0.342493773069341, -0.359950801091045, 0.187018301421814, 0.332611568778467, 0.418088885897922, 1.52526747601546, 1.23881025318897, 1.97893910443604, 1.67980257496383, -0.0423836378777035, -0.085940264442189, 0.0751591419566941, 1.33615888669544, 1.29143414265875, 0.211686019646981, 0.107754613497605, -0.842122877395922, -0.363550334633855, -1.04260396788242, -1.00216202750311, -0.725219786582336, -0.702075395338802, -0.0588517433215815, 0.676181221812652, 0.606054389584641, -0.0722001122493283, -0.565579974058951, -1.50420998542363, -1.38835023347894, -1.6387526999868, -1.22317617387598, -2.6439685322602, -1.50311594814139, 0.58539278534518, 0.476423420506994, -0.229810354321508, -0.669629539423225, -0.500767918117353, -1.30780681405878, -0.0658147956438969, 0.619743292251259, 0.947409254626009, 0.137968713284014, -0.0705143536229389, -0.316245167388448, 0.423768217540825, -1.77132723836955, 0.437524374017483, 1.05217040293853, 1.29145821945076, 0.189519814277623, 0.405463210651828, -1.10579240546022, 0.470126971026959, 1.3013241742778, 1.57690948154138, 0.836753145709701, -0.0990436481848584, 0.305059193206195, 0.722542224965483, 0.497020187014643, -0.798519685959293, -0.162044448918511, -0.268976403560686, 0.471344909208507, 1.07960447064393, 0.816448434674936, 1.01857006703316, -0.19352270657549, 0.193745914189151, -0.0118346974247015, 0.515110447770272, 1.29117007883295, 0.484844437955959, 0.357506193819553, -1.95817055695569, -1.62102859205691, -2.13900473718215, -2.19173201733318, -1.86372596557808, -1.18864210270607, -1.19890597040604, 0.432503235072499, 0.594410727524479, 1.21432538936706, 2.15795981275539, 1.31528364302187, 0.38422055227912, 0.786869292659675, -0.703717985086569, -0.535651668024763, 0.34627858116184, 0.537117318247469, 0.901014803953916, 1.2151594352426, 0.827351473348557, -0.682186392255085, -1.33342351753519, -1.26893821314864, -1.4632463728941, -1.64736130434257, -1.21073183651285, -0.643396605364174), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140')), structure(c(9L, 9L, 9L, 9L, 9L, 9L, 9L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 19L, 19L, 19L, 19L, 19L, 19L, 19L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 18L, 18L, 18L, 18L, 18L, 18L, 18L, 20L, 20L, 20L, 20L, 20L, 20L, 20L, 12L, 12L, 12L, 12L, 12L, 12L, 12L), .Label = c('10', '8', '2', '6', '3', '5', '9', '7', '1', '4', '17', '20', '11', '12', '16', '13', '14', '18', '15', '19'), class = c('ordered', 'factor'))); .Internal(split(argv[[1]], argv[[2]]))
 $`10`
        64        65        66        67        68        69        70
@@ -64642,7 +65197,29 @@ $`19`
 -0.7037180 -0.5356517  0.3462786  0.5371173  0.9010148  1.2151594  0.8273515
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit2#
+#{ .Internal(split(structure(1:4, names=c('a','b','c','d')), factor(c(1,2)))); }
+$`1`
+a c
+1 3
+
+$`2`
+b d
+2 4
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit2#
+#{ .Internal(split(structure(c(TRUE,FALSE,FALSE,FALSE), names=c('a','b','c','d')), factor(c(1,2)))); }
+$`1`
+    a     c
+ TRUE FALSE
+
+$`2`
+    b     d
+FALSE FALSE
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit3#
 #argv <- list(structure(c(1034.46153846154, 480.076923076923, 504.692307692308, 480.076923076923, 0, 0, 0, 0, 480.076923076923, 517.230769230769, 444.307692307692, 819.846153846154, 945.230769230769, 542.769230769231, 0, 0, 0, 1824.30769230769, 444.307692307692, 912.153846153846, 0, 0, 1514.07692307692, 0, 936, 0), .Dim = 26L, .Dimnames = list(c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('1', '2'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))
 $`1`
         1         1         1         1         1         1         1         1
@@ -64665,7 +65242,7 @@ $`1`
 [11]  0.000000e+00  0.000000e+00
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_split.testsplit5#Ignored.ImplementationError#
 #argv <- list(c(1, 3, 5, 7, 8, 3, 5, NA, 4, 5, 7, 9), structure(c(8L, 6L, 3L, 2L, NA, 5L, 1L, 4L, 7L, 3L, NA, NA), .Label = c('0', '2', '6', '8', '15', '22', '29', '35'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))
 $`0`
 [1] 5
@@ -65218,7 +65795,7 @@ character(0)
 #argv <- list('%s is not TRUE', 'identical(fxy, c(1, 2, 3))'); .Internal(sprintf(argv[[1]], argv[[2]]))
 [1] "identical(fxy, c(1, 2, 3)) is not TRUE"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf10#Ignored.ImplementationError#
 #argv <- list('%.0f%% said yes (out of a sample of size %.0f)', 66.666, 3); .Internal(sprintf(argv[[1]], argv[[2]], argv[[3]]))
 [1] "67% said yes (out of a sample of size 3)"
 
@@ -65293,7 +65870,7 @@ character(0)
 #argv <- list('tools:::check_compiled_code(\'%s\')', '/home/lzhao/hg/r-instrumented/library/foreign'); .Internal(sprintf(argv[[1]], argv[[2]]))
 [1] "tools:::check_compiled_code('/home/lzhao/hg/r-instrumented/library/foreign')"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf18#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf18#Ignored.ImplementationError#
 #argv <- list('%5g', structure(c(18, 18, 0, 14, 4, 12, 12, 0, 4, 8, 26, 23, 3, 18, 5, 8, 5, 3, 0, 5, 21, 0, 21, 0, 0), .Dim = c(5L, 5L), .Dimnames = list(NULL, c('', '', '', '', '')))); .Internal(sprintf(argv[[1]], argv[[2]]))
  [1] "   18" "   18" "    0" "   14" "    4" "   12" "   12" "    0" "    4"
 [10] "    8" "   26" "   23" "    3" "   18" "    5" "    8" "    5" "    3"
@@ -65303,7 +65880,7 @@ character(0)
 #argv <- list('%G', 3.14159265358979e-06); .Internal(sprintf(argv[[1]], argv[[2]]))
 [1] "3.14159E-06"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf2#Ignored.ImplementationError#
 #argv <- list('%1.0f', 3.14159265358979); .Internal(sprintf(argv[[1]], argv[[2]]))
 [1] "3"
 
@@ -65335,7 +65912,7 @@ character(0)
 #argv <- list('p,L,S = (%2d,%2d,%2d): ', TRUE, TRUE, FALSE); .Internal(sprintf(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] "p,L,S = ( 1, 1, 0): "
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sprintf.testsprintf7#Ignored.ImplementationError#
 #argv <- list('p,L,S = (%2d,%2d,%2d): ', TRUE, FALSE, NA); .Internal(sprintf(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))
 [1] "p,L,S = ( 1, 0,NA): "
 
@@ -65347,13 +65924,13 @@ character(0)
 #argv <- list('tools:::.createExdotR(\'%s\', \'%s\', silent = TRUE, use_gct = %s, addTiming = %s)', structure('KernSmooth', .Names = 'Package'), '/home/lzhao/hg/r-instrumented/library/KernSmooth', FALSE, FALSE); .Internal(sprintf(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))
 [1] "tools:::.createExdotR('KernSmooth', '/home/lzhao/hg/r-instrumented/library/KernSmooth', silent = TRUE, use_gct = FALSE, addTiming = FALSE)"
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testSqrt#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testSqrt#Output.MissingWarning#
 #{ sqrt(-1) }
 [1] NaN
 Warning message:
 In sqrt(-1) : NaNs produced
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testSqrt#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testSqrt#Output.MissingWarning#
 #{ sqrt(-1L) }
 [1] NaN
 Warning message:
@@ -65392,7 +65969,7 @@ a b
 #argv <- list(12.8025995273675);sqrt(argv[[1]]);
 [1] 3.578072
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testsqrt10#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testsqrt10#Output.MissingWarning#
 #argv <- list(c(6L, 5L, 4L, 3L, 2L, 1L, 0L, -1L, -2L, -3L, -4L));sqrt(argv[[1]]);
  [1] 2.449490 2.236068 2.000000 1.732051 1.414214 1.000000 0.000000      NaN
  [9]      NaN      NaN      NaN
@@ -65428,7 +66005,7 @@ numeric(0)
         ar1         ar2   intercept       trend
 0.100911916 0.103585134 0.246129163 0.008388095
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testsqrt7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sqrt.testsqrt7#Ignored.OutputFormatting#
 #argv <- list(structure(1:10, id = 'test 1', class = structure('withId', package = '.GlobalEnv')));sqrt(argv[[1]]);
  [1] 1.000000 1.414214 1.732051 2.000000 2.236068 2.449490 2.645751 2.828427
  [9] 3.000000 3.162278
@@ -65672,17 +66249,21 @@ B FALSE TRUE
 [2,]    1
 [3,]    2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#
-#{ .Internal(strptime('','',) }
-Error: unexpected '}' in "{ .Internal(strptime('','',) }"
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#Output.IgnoreErrorContext#
+#{ .Internal(strptime('','',)); }
+Error in .Internal(strptime("", "", )) : argument 3 is empty
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#
-#{ .Internal(strptime('',,'') }
-Error: unexpected '}' in "{ .Internal(strptime('',,'') }"
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#Output.IgnoreErrorContext#
+#{ .Internal(strptime('',,'')); }
+Error in .Internal(strptime("", , "")) : argument 2 is empty
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#
-#{ .Internal(strptime(,'','') }
-Error: unexpected '}' in "{ .Internal(strptime(,'','') }"
+#{ .Internal(strptime('1970-01-01 0:3:22', '%H:%M:%S', 'UTC')); }
+[1] NA
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.testArgsCasts#Output.IgnoreErrorContext#
+#{ .Internal(strptime(,'','')); }
+Error in .Internal(strptime(, "", "")) : argument 1 is empty
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strptime.teststrptime1#
 #argv <- list('2008-04-22 09:45', '%Y-%m-%d', ''); .Internal(strptime(argv[[1]], argv[[2]], argv[[3]]))
@@ -65751,12 +66332,12 @@ character(0)
 [5] "1894-01-01 GMT" "1895-01-01 GMT"
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep('aa', NULL) } }
-Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep('aa', NULL) }"
+#if (!any(R.version$engine == "FastR")) { cat("character(0)\n") } else { .Internal(strrep('aa', NULL)) }
+character(0)
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep(NULL, 5) } }
-Error: unexpected '}' in "if (length(grep("FastR", R.Version()$version.string)) != 1) { cat("character(0)") } else { { .Internal(strrep(NULL, 5) }"
+#if (!any(R.version$engine == "FastR")) { cat("character(0)\n") } else { .Internal(strrep(NULL, 5)) }
+character(0)
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strrep.testArgsCasts#
 #{ .Internal(strrep('', ) }
@@ -65852,6 +66433,15 @@ Error: unexpected '}' in "{ .Internal(strrep(, '') }"
 [1] "" ""
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_strsplit.testStrSplit#
+#strsplit(c('','a , b'), '[[:space:]]*,[[:space:]]*')
+[[1]]
+character(0)
+
+[[2]]
+[1] "a" "b"
+
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_strsplit.testStrSplit#
 #strsplit(c('1', ''), c('1', ''), fixed=FALSE)
 [[1]]
@@ -67460,6 +68050,10 @@ quote(x + 1)
 Error in substitute(quote(x + 1), setClass("a")) :
   invalid environment specified
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substitute.testSubstitute#
+#typeof(substitute(set))
+[1] "symbol"
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_substitute.testSubstitute#
 #{ delayedAssign("expr", a * b) ; substitute(expr) }
 expr
@@ -67804,7 +68398,7 @@ character(0)
 #argv <- list(c('        ', '        '), 1L, c(4L, -16L)); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))
 [1] "    " ""
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testsubstr3#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testsubstr3#
 #argv <- list(structure(c('as.formula', 'coef', 'makepredictcall', 'na.fail', 'predict'), .Names = c('as.formula', 'coef', 'makepredictcall', 'na.fail', 'predict')), 1L, 6L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))
      as.formula            coef makepredictcall         na.fail         predict
        "as.for"          "coef"        "makepr"        "na.fai"        "predic"
@@ -67813,7 +68407,7 @@ character(0)
 #argv <- list(character(0), 7L, 1000000L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))
 character(0)
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testsubstr5#Ignored.ReferenceError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testsubstr5#
 #argv <- list(structure('to be supported).', Rd_tag = 'TEXT'), 17L, 17L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))
 [1] "."
 attr(,"Rd_tag")
@@ -67827,7 +68421,7 @@ character(0)
 #argv <- list('', 1L, 2L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))
 [1] ""
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testsubstr8#Ignored.ImplementationError#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_substr.testsubstr8#
 #argv <- list(structure(c('model.frame', 'predict', 'residuals'), .Names = c('model.frame', 'predict', 'residuals')), 1L, 6L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))
 model.frame     predict   residuals
    "model."    "predic"    "residu"
@@ -68353,7 +68947,7 @@ In sum(argv[[1]]) : integer overflow - use sum(as.numeric(.))
 #sum( );
 [1] 0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_summary.testsummary1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_summary.testsummary1#Ignored.OutputFormatting#
 #argv <- structure(list(object = structure(c(4L, 4L, 4L, 4L, 4L,     3L, 4L, 4L, 4L, 4L, 3L, 4L, 3L, 4L, 4L, 4L, 4L, 2L, 4L, 3L,     4L, 4L, 4L, 2L), .Dim = c(6L, 4L), .Dimnames = structure(list(c('25-34',     '35-44', '45-54', '55-64', '65-74', '75+'), c('0-39g/day',     '40-79', '80-119', '120+')), .Names = c('', '')), class = 'table')),     .Names = 'object');do.call('summary', argv)
 Number of cases in table: 88
 Number of factors: 2
@@ -68414,7 +69008,7 @@ $`can write`
 [2,] 0.3333333 0.3333333 0.3333333 0.3333333 0.3333333
 [3,] 0.5000000 0.4000000 0.3750000 0.3636364 0.3571429
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sweep.testSweep#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sweep.testSweep#Output.MissingWarning#
 #{ A <- matrix(1:50, nrow=4); sweep(A, 1, 5, '-') }
      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11] [,12] [,13]
 [1,]   -4    0    4    8   12   16   20   24   28    32    36    40    44
@@ -68425,7 +69019,7 @@ Warning message:
 In matrix(1:50, nrow = 4) :
   data length [50] is not a sub-multiple or multiple of the number of rows [4]
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sweep.testSweep#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sweep.testSweep#Output.MissingWarning#
 #{ A <- matrix(7:1, nrow=5); sweep(A, 1, -1, '*') }
      [,1] [,2]
 [1,]   -7   -2
@@ -68494,7 +69088,7 @@ In matrix(7:1, nrow = 5) :
 [4,]   11   15   19
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sweep.testsweep1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sweep.testsweep1#Ignored.OutputFormatting#
 #argv <- structure(list(x = structure(integer(0), .Dim = c(5L,     0L)), MARGIN = 2, STATS = integer(0)), .Names = c('x', 'MARGIN',     'STATS'));do.call('sweep', argv)
 
 [1,]
@@ -68594,7 +69188,7 @@ In switch(3L) : 'switch' with no alternatives
 #argv <- list(2L, TRUE, FALSE, FALSE);do.call('switch', argv)
 [1] FALSE
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_syscall.testSysCall#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_syscall.testSysCall#Output.IgnoreWhitespace#
 #{ (function() sys.call())() }
 (function() sys.call())()
 
@@ -68778,7 +69372,7 @@ v()
 #{ u <- function() sys.nframe() ; f <- function(x) x ; g <- function(y) f(y) ; h <- function(z=u()) g(z) ; h() }
 [1] 4
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_sysonexit.testsysonexit1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_sysonexit.testsysonexit1#Ignored.Unimplemented#
 # .Internal(sys.on.exit())
 NULL
 
@@ -68883,6 +69477,13 @@ integer(0)
      [,1] [,2] [,3] [,4]
 [1,]   01   02   03   04
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose#
+#t(matrix(1:6, 3, 2, dimnames=list(x=c("x1","x2","x3"),y=c("y1","y2"))))
+    x
+y    x1 x2 x3
+  y1  1  2  3
+  y2  4  5  6
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_t.testTranspose#
 #t(new.env())
 Error in t.default(new.env()) : argument is not a matrix
@@ -69209,7 +69810,7 @@ Error in tanpi() : 0 arguments passed to 'tanpi' which requires 1
 #{ tanpi(1.2) }
 [1] 0.7265425
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tanpi.testTrigExp#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tanpi.testTrigExp#Output.IgnoreWarningMessage#
 #{ tanpi(c(0,0.5,-0.5)) }
 [1]   0 NaN NaN
 Warning message:
@@ -69306,27 +69907,34 @@ In tanpi(c(0, 0.5, -0.5)) : NaNs produced
 #argv <- list(c(-0.560475646552213-0.710406563699301i, -0.23017748948328+0.25688370915653i, 1.55870831414912-0.24669187846237i, 0.070508391424576-0.347542599397733i, 0.129287735160946-0.951618567265016i, 1.71506498688328-0.04502772480892i, 0.460916205989202-0.784904469457076i, -1.26506123460653-1.66794193658814i, -0.686852851893526-0.380226520287762i, -0.445661970099958+0.918996609060766i, 1.22408179743946-0.57534696260839i, 0.359813827057364+0.607964322225033i, 0.40077145059405-1.61788270828916i, 0.11068271594512-0.055561965524539i, -0.555841134754075+0.519407203943462i, 1.78691313680308+0.30115336216671i, 0.497850478229239+0.105676194148943i, -1.96661715662964-0.64070600830538i, 0.701355901563686-0.849704346033582i, -0.47279140772793-1.02412879060491i, -1.06782370598685+0.11764659710013i, -0.217974914658295-0.947474614184802i, -1.02600444830724-0.49055744370067i, -0.72889122929114-0.256092192198247i, -0.62503926784926+1.84386200523221i, -1.68669331074241-0.65194990169546i, 0.837787044494525+0.235386572284857i, 0.153373117836515+0.077960849563711i, -1.13813693701195-0.96185663413013i, 1.25381492106993-0.0713080861236i, 0.42646422147681+1.44455085842335i, -0.295071482992271+0.451504053079215i, 0.895125661045022+0.04123292199294i, 0.878133487533042-0.422496832339625i, 0.82158108163749-2.05324722154052i, 0.68864025410009+1.13133721341418i, 0.55391765353759-1.46064007092482i, -0.061911710576722+0.739947510877334i, -0.30596266373992+1.90910356921748i, -0.38047100101238-1.4438931609718i, -0.694706978920513+0.701784335374711i, -0.207917278019599-0.262197489402468i, -1.26539635156826-1.57214415914549i, 2.16895596533851-1.51466765378175i, 1.20796199830499-1.60153617357459i, -1.12310858320335-0.5309065221703i, -0.40288483529908-1.4617555849959i, -0.466655353623219+0.687916772975828i, 0.77996511833632+2.10010894052567i, -0.08336906647183-1.28703047603518i, 0.253318513994755+0.787738847475178i, -0.028546755348703+0.76904224100091i, -0.042870457291316+0.332202578950118i, 1.36860228401446-1.00837660827701i, -0.225770985659268-0.119452606630659i, 1.51647060442954-0.28039533517025i, -1.54875280423022+0.56298953322048i, 0.584613749636069-0.372438756103829i, 0.123854243844614+0.976973386685621i, 0.215941568743973-0.374580857767014i, 0.37963948275988+1.05271146557933i, -0.5023234531093-1.04917700666607i, -0.33320738366942-1.26015524475811i, -1.01857538310709+3.2410399349424i, -1.07179122647558-0.41685758816043i, 0.303528641404258+0.298227591540715i, 0.448209778629426+0.636569674033849i, 0.053004226730504-0.483780625708744i, 0.922267467879738+0.516862044313609i, 2.05008468562714+0.36896452738509i, -0.491031166056535-0.215380507641693i, -2.30916887564081+0.06529303352532i, 1.00573852446226-0.03406725373846i, -0.70920076258239+2.12845189901618i, -0.688008616467358-0.741336096272828i, 1.0255713696967-1.09599626707466i, -0.284773007051009+0.037788399171079i, -1.22071771225454+0.31048074944314i, 0.18130347974915+0.436523478910183i, -0.138891362439045-0.458365332711106i, 0.00576418589989-1.06332613397119i, 0.38528040112633+1.26318517608949i, -0.370660031792409-0.349650387953555i, 0.644376548518833-0.865512862653374i, -0.220486561818751-0.236279568941097i, 0.331781963915697-0.197175894348552i, 1.09683901314935+1.10992028971364i, 0.435181490833803+0.084737292197196i, -0.325931585531227+0.754053785184521i, 1.14880761845109-0.49929201717226i, 0.993503855962119+0.214445309581601i, 0.54839695950807-0.324685911490835i, 0.238731735111441+0.094583528173571i, -0.627906076039371-0.895363357977542i, 1.36065244853001-1.31080153332797i, -0.60025958714713+1.99721338474797i, 2.18733299301658+0.60070882367242i, 1.53261062618519-1.25127136162494i, -0.235700359100477-0.611165916680421i, -1.02642090030678-1.18548008459731i));tanpi(argv[[1]]);
 Error in tanpi(argv[[1]]) : unimplemented complex function
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tanpi.testtan7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tanpi.testtan7#Output.IgnoreWarningMessage#
 #argv <- list(Inf);tanpi(argv[[1]]);
 [1] NaN
 Warning message:
 In tanpi(argv[[1]]) : NaNs produced
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testTCrossprodDimnames#
+#{ tcrossprod(structure(1:9, .Dim=c(3L,3L), .Dimnames=list(c('a', 'b', 'c'), c('A', 'B', 'C'))), structure(1:9, .Dim=c(3L,3L), .Dimnames=list(c('d', 'e', 'f'), c('D', 'E', 'F')))) }
+   d   e   f
+a 66  78  90
+b 78  93 108
+c 90 108 126
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod1#
 #argv <- list(structure(c(5, 2, 0, 2, 5, 2, 0, 2, 5), .Dim = c(3L, 3L)), structure(c(0, 1, 0, 0, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0), .Dim = c(5L, 3L), .Dimnames = list(c('a', 'b', 'c', 'd', 'e'), NULL))); .Internal(tcrossprod(argv[[1]], argv[[2]]))
       a b  c d  e
 [1,]  0 5  4 0 12
 [2,]  4 2 12 0  9
 [3,] 10 0  9 0  2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod2#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod2#
 #argv <- list(structure(c(5, 2, 0, 2, 5, 2, 0, 2, 5), .Dim = c(3L, 3L), .Dimnames = list(c('A', 'B', 'C'), c('A', 'B', 'C'))), structure(c(0, 1, 0, 0, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0), .Dim = c(5L, 3L), .Dimnames = list(NULL, c('A', 'B', 'C')))); .Internal(tcrossprod(argv[[1]], argv[[2]]))
   [,1] [,2] [,3] [,4] [,5]
 A    0    5    4    0   12
 B    4    2   12    0    9
 C   10    0    9    0    2
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod3#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod3#
 #argv <- list(structure(c(-1.67712982705863, -1.48498667828929, -1.66855080519244, -1.58355627712096, -1.82359988031979, -1.9949008033236, -0.0318360538544526, -0.560218641212122, 0.066207937805176, 0.499775901814107, -0.00128363357081381, -0.00713986667014182, 0.296776079992064, -0.138150806520963, 0.253601178172029, -0.170225064799926, -0.240191246767341, -0.00408674943172847, -0.242382276284081, 0.0729153527553058, 0.269807081327349, 0.0299339639014576, -0.077267349576335, -0.0293027062153706, -0.0099926992270607, 0.0334924583850379, -0.0453336990810482, 0.0438958486872448, -0.112099180250145, 0.089015596249019), .Dim = c(6L, 5L)), structure(c(-0.399602067979347, -0.353820997034499, -0.397557983601584, -0.377306725388702, -0.434500818950138, -0.47531590790431, -0.0422023061126668, -0.742633452454394, 0.087766143100416, 0.662509734796894, -0.00170160212505116, -0.00946470439441127, 0.584095849615428, -0.271899651454647, 0.499121747385523, -0.335026171424641, -0.472729171281292, -0.00804328091925277, -0.637436340955898, 0.191758639997983, 0.70956029179181, 0.0787227379500612, -0.2032038701195, -0.0770626058818733, -0.062340518587102, 0.208946269374942, -0.282819110829524, 0.273848927982668, -0.699342677207614, 0.555333279468297), .Dim = c(6L, 5L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))
           [,1]      [,2]      [,3]      [,4]      [,5]      [,6]
 [1,] 1.0000000 0.4877861 0.6429309 0.4904554 0.6447151 0.8082101
@@ -69336,12 +69944,12 @@ C   10    0    9    0    2
 [5,] 0.6447151 0.6732497 0.5818673 0.7308955 1.0000000 0.8124321
 [6,] 0.8082101 0.7252317 0.7444550 0.7713985 0.8124321 1.0000000
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod4#
 #argv <- list(c(2, 3), structure(c(0, 0, 1, 0), .Dim = c(2L, 2L), .Dimnames = list(NULL, NULL))); .Internal(tcrossprod(argv[[1]], argv[[2]]))
      [,1] [,2]
 [1,]    3    0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod5#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod5#
 #argv <- list(structure(c(-0.106539372596213, -2.87400113021639, 0.341152775291742, 1.88577541025803, 0.842201032082677, -1.43117364207636, -0.69348461621825, -2.41970841038843, -3.02719090531729, -0.226641199170227, -0.332680183991575, -1.62371869115524, -1.66979618600051, -1.10431770731054, 1.88731633228519, 2.05877121721062, -0.223853590000374, 2.00359231906507, 2.73128102907396, 0.539089155601206, -0.199828039026098, -1.05787977326062, 0.306997029957149, 1.45711168105796, 1.49857746263809, -0.757919845814536, 0.268252398125501, -0.535834002202256, -0.271560453176356, -2.05847896960824, 0.980553291004929, 0.685818887220841, -0.522933983909647, -0.337189871316714, 0.191459457586776, 1.89272736696455, -0.453746315234956, 0.612338437255857, 1.37687299952389, -1.15071450872488, -0.20817483353688, -0.081142998844394, -0.253631714967276, -0.410462721238244, -0.68459626706876, -0.624834027577721, 0.00753430632431097, -0.0556623066116985, -0.563702942039652, 0.0408500401240061, -0.420302429975138, 0.033747665813787, 0.339840694442255, -0.250248532584852, -0.31434827109732, 0.378366203759376, -0.193977362697154, -0.518701418701189, 1.24086430187875, 0.0626244079886504, -0.168813902431602, -0.233723461170579, -0.0800002226605061, -0.0555238917407563, -0.947495254278566, -0.0485572234634504, -0.0296030565974314, -0.095544458696536, 0.0295824037592777, 0.194854132525369, 0.267233992325682, -0.087254491408015, 0.126110082843019, 0.159157280802928, -0.155595903815538, 0.170585777111235, -0.160659663851048, -0.059679874503493, 0.0114766797349517, -0.288711739670586, 0.192267902822735, -0.558695699349865, -0.0862396209998433, 0.00725278175306798, -0.128294571915242, -0.130284537275488, -0.0857140300930927, -0.0514859262258765, -0.0490801347386973, 0.0204665694600954, -0.14875269796722, 0.196176132315475, -0.0529883263026191, -0.132778199491125, -0.228017010951841, 0.0529472898389869), .Dim = c(12L, 8L)), structure(c(-0.0185462290552347, -0.500302207222603, 0.059387411050087, 0.328273218183171, 0.146609210012521, -0.249136760776327, -0.120720858638907, -0.421219548532773, -0.526969274886959, -0.0394533916498165, -0.057912513881884, -0.282654740999492, -0.321354169237256, -0.212527194864884, 0.363216168017541, 0.396212855019715, -0.0430808772043306, 0.385593613508892, 0.525638130815129, 0.103748319223306, -0.0384571326787796, -0.203590161804909, 0.0590819264933657, 0.28042279511599, 0.416779971858557, -0.210790446196582, 0.0746055707690415, -0.149024582263218, -0.0755255973444945, -0.572498138010465, 0.272708607475933, 0.190737938906932, -0.145436866983219, -0.0937782587701373, 0.0532481432121619, 0.52639978807016, -0.204031585044791, 0.275344124552216, 0.61912476435818, -0.517430328944052, -0.0936079034183924, -0.0364867638890611, -0.114048046419078, -0.184568682552654, -0.307835583002935, -0.280962892162748, 0.0033878764630103, -0.0250291148686315, -0.338839482109357, 0.0245547883601272, -0.252642033739931, 0.0202855808510911, 0.204276820851501, -0.150423346865756, -0.188953431740463, 0.227434343460447, -0.116598981866977, -0.311789254542753, 0.745878344887204, 0.0376432698639114, -0.159472254176866, -0.220789915226282, -0.0755732534972413, -0.0524513683353668, -0.895063746796005, -0.0458702143055051, -0.0279649134231136, -0.0902573187573718, 0.0279454034502495, 0.184071497085901, 0.252446075441722, -0.0824260930614398, 0.167922807083695, 0.211927046257706, -0.207184868571959, 0.227144744458931, -0.21392755544038, -0.0794671752416819, 0.0152818571968794, -0.384436237535829, 0.256015738204522, -0.743935362069355, -0.114833000769291, 0.00965749481472171, -0.300640883681616, -0.30530409690622, -0.200859174058623, -0.120650267011609, -0.115012621802916, 0.0479606224687302, -0.348581720171566, 0.459712089888966, -0.124170937293853, -0.311147655218321, -0.534326859224339, 0.124074773921503), .Dim = c(12L, 8L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))
               [,1]        [,2]        [,3]          [,4]         [,5]
  [1,]  1.533400821  0.05668259 -0.62713351 -0.6435680166  0.009334747
@@ -69383,7 +69991,7 @@ C   10    0    9    0    2
 [11,]  1.1723594597  0.27627736
 [12,]  0.2762773554  1.88147248
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod6#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod6#
 #argv <- list(structure(c(-1.22589324018138, -0.740548974281808, -0.54768368397833, -0.441021701509591, -0.370068251595057, -0.319690799411412, -0.282987166340516, -0.254112864677485, -0.230083320312515, 0.203647970189376, -0.0305516337408725, -0.0825170335109532, -0.0984577177107505, -0.100129992839015, -0.0988979642888749, -0.0945771185256416, -0.0902309571831907, -0.0871241228998968, -0.00955870050771132, 0.0197754782700907, 0.0125304440435148, 0.00419858922572787, -0.00191073996840182, -0.0061756059258365, -0.00956682744689523, -0.0127366531032827, -0.0131079781713544, 0.000214464770644159, -0.000956552371122151, 5.72249143534175e-05, 0.00029865136977495, 0.00077852017665313, 0.00142425180877207, 0.000491677810053133, -0.000120006753650731, -0.00247588122373662, 4.2574997724815e-05, -0.000297064220851874, 0.000399761711902461, 5.67830351414009e-05, -0.00026523273781528, 0.000320119491527155, -0.00026454073650643, -0.000195756422133707, 0.000192249930248858, -4.94461924222768e-07, 2.80125995838013e-05, -0.000119138513940463, 0.000151917649712048, -7.31975645151543e-05, 4.92140187851149e-05, -1.13604576670922e-05, -3.74519303853871e-05, 9.55915555684852e-06), .Dim = c(9L, 6L)), structure(c(-0.709851441473678, -0.428813651666777, -0.317135326144804, -0.255372882626744, -0.214287405483635, -0.185116425598763, -0.163863247924954, -0.147143631578904, -0.133229363887123, 0.633337192677659, -0.0950143815681878, -0.256624734846691, -0.306199636924392, -0.311400346924765, -0.307568786499592, -0.294131125799441, -0.280614734641737, -0.270952601985731, -0.28505721606605, 0.58973945020027, 0.373679821042009, 0.125209295460755, -0.0569816174886273, -0.184167401344961, -0.285299575647986, -0.379829336915808, -0.390902901787376, 0.0675695685124445, -0.301372718615498, 0.0180293609967187, 0.0940935153626058, 0.245281648154537, 0.448726753036158, 0.154908693733931, -0.0378094944843564, -0.780054577138554, 0.056333641054865, -0.393064241503382, 0.528949712019966, 0.0751331835725979, -0.350946016360591, 0.423570111428232, -0.350030386168567, -0.259017559788085, 0.254377901167792, -0.00226968135332679, 0.128583560874789, -0.546870143699694, 0.697333080468545, -0.335991790571385, 0.225902410856869, -0.0521468239901137, -0.171912019667483, 0.0438784789244046), .Dim = c(9L, 6L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))
            [,1]       [,2]       [,3]       [,4]       [,5]       [,6]
  [1,] 1.0019216 0.50061170 0.33296771 0.24952915 0.19985993 0.16617177
@@ -69406,12 +70014,12 @@ C   10    0    9    0    2
  [8,] 0.07186514 0.06761066 0.06332457
  [9,] 0.06661649 0.06332457 0.06136495
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod7#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod7#
 #argv <- list(0, 0); .Internal(tcrossprod(argv[[1]], argv[[2]]))
      [,1]
 [1,]    0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod8#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tcrossprod.testtcrossprod8#
 #argv <- list(structure(c(1.1173625565162, 1.46907016195074, 1.1173625565162, -0.59596185089264, -1.32605913508878e-308, 0.595961850892641), .Dim = c(3L, 2L)), structure(c(0.517876924314756, 0.680886908762812, 0.517876924314755, -0.707106781186547, -1.57336481399136e-308, 0.707106781186548), .Dim = c(3L, 2L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))
           [,1]      [,2]      [,3]
 [1,] 1.0000650 0.7607975 0.1572476
@@ -69515,7 +70123,7 @@ attr(,"assign")
      [,1] [,2] [,3] [,4] [,5] [,6]          [,7] [,8] [,9] [,10] [,11] [,12]
 [1,]    0    0    0    0    0    0 3.952525e-323    0    0     0     0     0
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_tdefault.testtdefault14#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_tdefault.testtdefault14#
 #argv <- list(structure(c(794, 86, 150, 570), .Dim = c(2L, 2L), .Dimnames = structure(list(`1st Survey` = c('Approve', 'Disapprove'), `2nd Survey` = c('Approve', 'Disapprove')), .Names = c('1st Survey', '2nd Survey')))); .Internal(t.default(argv[[1]]))
             1st Survey
 2nd Survey   Approve Disapprove
@@ -70094,7 +70702,7 @@ tracemem[0x7faf191a98a8 -> 0x7faf191a98e0]:
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.retracemem#Output.ContainsReferences#
 #x<-1:10; retracemem(x, c("first", "second")) 
-tracemem[first -> 0x1d805c0]:
+tracemem[first -> 0x7ffe0227b550]:
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.vectors#Output.ContainsReferences#
 #v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; untracemem(v); y[[2]] <- 84
@@ -70182,12 +70790,12 @@ tracemem[0x7f818486bc90 -> 0x7f818486ba50]:
 [71]   0.21654883   0.01307171
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_trunc.testTrunc#
-#{ trunc("aaa"); }
-Error in trunc("aaa") : non-numeric argument to mathematical function
+#if (!any(R.version$engine == "FastR")) { 1+1i } else { { trunc(1.1+1.9i); } }
+[1] 1+1i
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_trunc.testTrunc#
-#{ trunc(1+1i); }
-Error in trunc(1 + (0+1i)) : unimplemented complex function
+#{ trunc("aaa"); }
+Error in trunc("aaa") : non-numeric argument to mathematical function
 
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_trunc.testTrunc#
 #{ typeof(trunc(42L)); }
@@ -72046,7 +72654,7 @@ attr(,"package")
 #argv <- list(list(c(TRUE, TRUE), c(TRUE, TRUE), c(TRUE, TRUE), c(TRUE, TRUE), c(1, 2, 3)), TRUE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))
  [1] 1 1 1 1 1 1 1 1 1 2 3
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist32#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist32#Ignored.ImplementationError#
 #argv <- list(structure(list(mean = c(0, 1), vcov = structure(c(1, 1, 1, 0), .Dim = c(2L, 2L))), .Names = c('mean', 'vcov'), class = c('relistable', 'list')), TRUE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))
 mean1 mean2 vcov1 vcov2 vcov3 vcov4
     0     1     1     1     1     0
@@ -72157,7 +72765,7 @@ Levels: C D
 [1] NA
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist4#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unlist.testunlist4#Ignored.ImplementationError#
 #argv <- list(list(list(structure(function (e1, e2) standardGeneric('Ops'), generic = structure('Ops', package = 'base'), package = 'base', group = list(), valueClass = character(0), signature = c('e1', 'e2'), default = quote(`\001NULL\001`), skeleton = quote((function (e1, e2) stop('invalid call in method dispatch to \'Ops\' (no default method)', domain = NA))(e1, e2)), groupMembers = list('Arith', 'Compare', 'Logic'), class = structure('groupGenericFunction', package = 'methods')))), FALSE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))
 [[1]]
 function (e1, e2)
@@ -72735,6 +73343,21 @@ Slot "y":
 [1] 77 88
 
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_unzip.testunzip#
+#n <- tempfile(); writeBin(con=n,as.raw(c(0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0xf3, 0x4a, 0xb7, 0xef, 0xdc, 0x83, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x66, 0x6f, 0x6f, 0x31, 0x55, 0x54, 0x09, 0x00, 0x03, 0xa3, 0x47, 0x6f, 0x59, 0xad, 0x47, 0x6f, 0x59, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xf5, 0x01, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x31, 0x50, 0x4b, 0x01, 0x02, 0x1e, 0x03, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0xf3, 0x4a, 0xb7, 0xef, 0xdc, 0x83, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x6f, 0x31, 0x55, 0x54, 0x05, 0x00, 0x03, 0xa3, 0x47, 0x6f, 0x59, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xf5, 0x01, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00)))<<<NEWLINE>>>length(unzip(n,list=T))<<<NEWLINE>>>names(unzip(n,list=T))<<<NEWLINE>>>unzip(n,list=T)[1:2]<<<NEWLINE>>>target <- tempdir()<<<NEWLINE>>>v <- unzip(n,exdir=target, files=c('bar','baz'))<<<NEWLINE>>>v<<<NEWLINE>>>file.exists(paste0(target, '/foo1'))<<<NEWLINE>>>v <- unzip(n,exdir=target)<<<NEWLINE>>>length(v)<<<NEWLINE>>>file.exists(v)<<<NEWLINE>>>readBin(paste0(target, '/foo1'), what='raw', n=1000)
+[1] 3
+[1] "Name"   "Length" "Date"
+  Name Length
+1 foo1      1
+Warning message:
+In unzip(n, exdir = target, files = c("bar", "baz")) :
+  requested file not found in the zip file
+character(0)
+[1] FALSE
+[1] 1
+[1] TRUE
+[1] 31
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_utf8ToInt.testUtf8ToInt#
 #utf8ToInt('')
 integer(0)
@@ -72897,6 +73520,14 @@ Error in match.fun(FUN) : '42' is not a function, character or symbol
 Error in vapply(quote(a), function(x) quote(b), quote(a)) :
   'FUN.VALUE' must be a vector
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapplyNames#
+#{ a <- vapply(list(a=1:20,b=1:20), function (x) x, FUN.VALUE=1:20); attributes(a); a[1:5] }
+[1] 1 2 3 4 5
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_vapply.testVapplyNames#
+#{ b <- list(a=structure(c(1:3), names=c('x','y')),b=structure(c(1:3), names=c('x2','y2','z2'))); a <- vapply(b, function (x) x, FUN.VALUE=1:3); attributes(a); a[1:5] }
+[1] 1 2 3 1 2
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_vector.testVectorConstructor#
 #{  vector("numeric", c(7, 42)) }
 Error in vector("numeric", c(7, 42)) : invalid 'length' argument
@@ -73277,7 +73908,7 @@ $visible
 [1] -59.790247  16.824684  -4.832654
 
 
-##com.oracle.truffle.r.test.builtins.TestBuiltin_within.testwithin1#Ignored.Unknown#
+##com.oracle.truffle.r.test.builtins.TestBuiltin_within.testwithin1#Output.IgnoreErrorMessage#
 #argv <- structure(list(data = structure(list(a = 1:5, b = 2:6,     c = 3:7), .Names = c('a', 'b', 'c'), row.names = c(NA, -5L),     class = 'data.frame')), .Names = 'data');do.call('within', argv)
 Error in eval(expr, envir, enclos) : argument is missing, with no default
 
@@ -76313,7 +76944,7 @@ Hello world
 [1] 5
 [1] 6
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testDots#Ignored.Unknown#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testDots#Ignored.ImplementationError#
 #{ f <- function(...) { ..1 + ..2 } ; f(1,,3) }
 Error in ..1 + ..2 : non-numeric argument to binary operator
 
@@ -76341,7 +76972,7 @@ Error in f() : 'nthcdr' needs a list to CDR down
 #{ f <- function(...) { ..1 } ;  f(10) }
 [1] 10
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testDots#Ignored.Unknown#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testDots#Output.IgnoreErrorMessage#
 #{ f <- function(...) { ..2 + ..2 } ; f(1,,2) }
 Error in ..2 + ..2 : non-numeric argument to binary operator
 
@@ -76427,7 +77058,7 @@ Error in f(a = 1, ...) :
 #{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ..., x=2) } ; g(1) }
 Error in f(a = 1, ..., x = 2) : unused argument (x = 2)
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testDots#Ignored.Unknown#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testDots#Output.IgnoreErrorMessage#
 #{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ..., x=2,z=3) } ; g(1) }
 Error in f(a = 1, ..., x = 2, z = 3) : unused arguments (x = 2, z = 3)
 
@@ -76532,7 +77163,7 @@ Error in g(x = 4, ..., 10) : unused argument (10)
 #{ h<-function(x,...) f(x,...); f<-function(x, ...) { sum(x, ...) }; h(7) }
 [1] 7
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testDots#Ignored.Unknown#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testDots#Output.IgnoreErrorMessage#
 #{ lapply(1:3, "dummy") }
 Error in get(as.character(FUN), mode = "function", envir = envir) :
   object 'dummy' of mode 'function' was not found
@@ -76565,7 +77196,7 @@ Error: attempt to use zero-length variable name
 #{ function(''=123) 4 }
 Error: unexpected string constant in "{ function(''"
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testErrors#Ignored.Unknown#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testErrors#Ignored.ImplementationError#Output.IgnoreErrorContext#
 #{ f <- function(a,a) {1} }
 Error: repeated formal argument 'a' on line 1
 
@@ -76598,7 +77229,7 @@ Error in x(1, ) : unused argument ()
 Error in x(fo = 10, f = 1, 2) :
   formal argument "foo" matched by multiple actual arguments
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testErrors#Ignored.Unknown#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testErrors#Ignored.ImplementationError#
 #{ x<-function(y, b){1} ; x(y=1, 2, 3, z = 5) }
 Error in x(y = 1, 2, 3, z = 5) : unused arguments (3, z = 5)
 
@@ -76757,7 +77388,7 @@ Error in matrix(1:4, n = 2) :
 #{ matrix(x=1) }
 Error in matrix(x = 1) : unused argument (x = 1)
 
-##com.oracle.truffle.r.test.functions.TestFunctions.testInvocation#Ignored.Unknown#Output.IgnoreErrorContext#
+##com.oracle.truffle.r.test.functions.TestFunctions.testInvocation#Ignored.ImplementationError#
 #{ max(1,2,) }
 Error in max(1, 2, ) : argument 3 is empty
 
@@ -76898,6 +77529,23 @@ Error in foo(xa = 4, xaa = 5) :
 #{ x<-function(foo,bar){foo*bar} ; x(fo=10, bar=2) }
 [1] 20
 
+##com.oracle.truffle.r.test.functions.TestFunctions.testPromises#
+#foo <- function(a,b) { x<<-4; b; }; x <- 0; foo(2, x > 2);
+[1] TRUE
+
+##com.oracle.truffle.r.test.functions.TestFunctions.testPromises#Ignored.ImplementationError#
+#foo <- function(x,z) list(x,z); x <- 4; bar <- function() { x <<- 10; 1; }; foo(bar(), x > 5);
+[[1]]
+[1] 1
+
+[[2]]
+[1] TRUE
+
+
+##com.oracle.truffle.r.test.functions.TestFunctions.testPromises#Ignored.ImplementationError#
+#foo <- function(x,z) x + z; x <- 4; bar <- function() { x <<- 10; 1; }; foo(bar(), x);
+[1] 11
+
 ##com.oracle.truffle.r.test.functions.TestFunctions.testPromises#
 #{ f <- function(a) { g <- function(b) { a <<- 3; b } ; g(a) } ; x <- 1 ; f(x) }
 [1] 3
@@ -76944,8 +77592,8 @@ Error in f() :
 [1] 3628800
 
 ##com.oracle.truffle.r.test.functions.TestFunctions.testRecursion#
-#{ f<-function(i) { if(i<=1) 1 else i*f(i-1) } ; g<-function(n, f, a) { if (n==1) { f(a) } else { f(a) ; g(n-1, f, a) } } ; g(100,f,120) }
-[1] 6.689503e+198
+#{ f<-function(i) { if(i<=1) 1 else i*f(i-1) } ; g<-function(n, f, a) { if (n==1) { f(a) } else { f(a) ; g(n-1, f, a) } } ; g(100,f,100) }
+[1] 9.332622e+157
 
 ##com.oracle.truffle.r.test.functions.TestFunctions.testRecursion#
 #{ f<-function(i) { if(i<=1L) 1L else i*f(i-1L) } ; f(10L) }
@@ -77015,8 +77663,22 @@ Error in foo(1, 2, 3) : unused arguments (2, 3)
 [1] "isa"
 [1] TRUE
 
+##com.oracle.truffle.r.test.functions.TestFunctions.testVarArgPromises#
+#rule <- 1; stopifnot((lenR <- length(rule)) >= 1L, lenR <= 2L)
+
+##com.oracle.truffle.r.test.functions.TestFunctions.testVarArgPromises#
+#{ seq((abc <- 1), abc + 10) }
+ [1]  1  2  3  4  5  6  7  8  9 10 11
+
+##com.oracle.truffle.r.test.functions.TestFunctions.testVarArgPromises#
+#{ seq((abc <- 1), length.out = abc + 1) }
+[1] 1 2
+
+##com.oracle.truffle.r.test.functions.TestFunctions.testVarArgPromises#
+#{ x <- 3; stopifnot((x <- 5) < 10, x == 5); }
+
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/argMatching.R") }
+#{ source("tmptest/S3/argMatching.R") }
 dispatch
 g.c args:
 [[1]]
@@ -77101,7 +77763,7 @@ NULL
 
 
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/nextMethod.R") }
+#{ source("tmptest/S3/nextMethod.R") }
 called foo.default with  42
 with '' as class
 called foo.default with  42
@@ -77110,7 +77772,7 @@ called foo.baz with  42
 called foo.bar with  42
 
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/nextMethodAdditionalArgs1.R") }
+#{ source("tmptest/S3/nextMethodAdditionalArgs1.R") }
 called foo.baz with  42
 list()
 called foo.bar with  42
@@ -77119,7 +77781,7 @@ called foo.bar with  42
 
 
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/nextMethodAdditionalArgs2.R") }
+#{ source("tmptest/S3/nextMethodAdditionalArgs2.R") }
 foo.bar with:
 $x
 [1] 42
@@ -77203,7 +77865,7 @@ $named$f
 
 
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/nextMethodAdditionalArgs3.R") }
+#{ source("tmptest/S3/nextMethodAdditionalArgs3.R") }
 foo.baz
 foo.bar with:
 evaluated  b-from-caller
@@ -77254,7 +77916,7 @@ list()
 
 
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/nextMethodAdditionalArgs4.R") }
+#{ source("tmptest/S3/nextMethodAdditionalArgs4.R") }
 foo.baz
 foo.bar with:
 $x
@@ -77273,7 +77935,7 @@ $mynamed
 
 
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#Ignored.Unknown#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/nextMethodAdditionalArgsPromises1.R") }
+#{ source("tmptest/S3/nextMethodAdditionalArgsPromises1.R") }
 foo.bar with:
 $x
 [1] 42
@@ -77358,7 +78020,7 @@ $named$f
 
 
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/nextMethodArgsMatching.R") }
+#{ source("tmptest/S3/nextMethodArgsMatching.R") }
 foo.bar with:
 $x
 [1] 42
@@ -77430,7 +78092,7 @@ $named$e
 
 
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/functions/S3/R/numericTypes.R") }
+#{ source("tmptest/S3/numericTypes.R") }
 integer
 double
 logical
@@ -77621,7 +78283,7 @@ $c
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.testUseMethodEnclFuncArgs#
 #{f <- function(x,y,z){ UseMethod("f"); }; f.second <- function(x,y,z){cat("f second",x,y,z)}; obj <-1; attr(obj,"class") <- "second"; arg2=2; arg3=3; f(obj,arg2,arg3);}
 f second 1 2 3
-##com.oracle.truffle.r.test.functions.TestS3Dispatch.testUseMethodLocalVars#Ignored.Unknown#
+##com.oracle.truffle.r.test.functions.TestS3Dispatch.testUseMethodLocalVars#Ignored.ImplementationError#
 #{f <- function(x){ y<-2;locFun <- function(){cat("local")}; UseMethod("f"); }; f.second <- function(x){cat("f second",x);locFun();}; obj <-1; attr(obj,"class")  <- "second"; f(obj);}
 f second 1local
 ##com.oracle.truffle.r.test.functions.TestS3Dispatch.testUseMethodNested#
@@ -77641,7 +78303,7 @@ f first 1
 [1] "logical"
 
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers0.R") }
+#{ source("tmptest/condition/withCallingHandlers0.R") }
 {
     fun1("first")
     fun1("second")
@@ -77667,7 +78329,7 @@ NULL
 [1] "exit fun0"
 
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/library/base/condition/R/withCallingHandlers1.R") }
+#{ source("tmptest/condition/withCallingHandlers1.R") }
 {
     fun1("first")
     fun1("second")
@@ -77700,6 +78362,15 @@ NULL
 NULL
 [1] "exit fun0"
 
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#
+#my.error <- function(war) cat('my.error:', war$message, '\n'); f <- function() print(g); tryCatch({f()}, error=my.error)
+my.error: object 'g' not found
+
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#
+#x <- { tryCatch(stop('fred'), error = function(e) e, finally = print('Hello'))}; x$call <- NULL; x
+[1] "Hello"
+<simpleError: fred>
+
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#
 #{ e <- simpleError("test error"); f <- function() { tryCatch(1, finally = print("Hello")); stop(e)}; f() }
 [1] "Hello"
@@ -77728,11 +78399,6 @@ Error in f() : fred
 [1] "Hello"
 [1] 1
 
-##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#Ignored.ImplementationError#
-#{ tryCatch(stop("fred"), error = function(e) e, finally = print("Hello"))}
-[1] "Hello"
-<simpleError in doTryCatch(return(expr), name, parentenv, handler): fred>
-
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#Output.IgnoreErrorContext#
 #{ tryCatch(stop("fred"), finally = print("Hello")) }
 Error in tryCatchList(expr, classes, parentenv, handlers) : fred
@@ -77742,6 +78408,19 @@ Error in tryCatchList(expr, classes, parentenv, handlers) : fred
 #{ tryCatch(stop("xyz"), error=function(e) { cat("<error>");123L }, finally=function() { cat("<finally>")}) }
 <error>[1] 123
 
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testTryCatch#Ignored.ImplementationError#
+#{ tryCatch(stop('fred'), error = function(e) e, finally = print('Hello'))}
+[1] "Hello"
+<simpleError in doTryCatch(return(expr), name, parentenv, handler): fred>
+
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWarning#
+#my.warning <- function(war) cat('my.warning:', war$message, '\n'); f <- function()  warning('from f'); tryCatch({f()}, warning=my.warning)
+my.warning: from f
+
+##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWarning#
+#tryCatch(warning('some warning text'), warning = function(w) {print('WARNING')})
+[1] "WARNING"
+
 ##com.oracle.truffle.r.test.library.base.TestConditionHandling.testWithCallingHandlers#Output.IgnoreErrorContext#
 #withCallingHandlers(stop('error message'), error=function(e) {})
 Error in withCallingHandlers(stop("error message"), error = function(e) { :
@@ -77806,30 +78485,30 @@ NULL
 <start>[1] 123 456
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#Ignored.Unknown#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R") }
+#{ source("tmptest/connections/fifo_GnuR_example.R") }
 [1] "abc"
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R") }
+#{ source("tmptest/connections/rawConnection_readBin.R") }
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R") }
+#{ source("tmptest/connections/rawConnection_readWriteBin.R") }
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R") }
+#{ source("tmptest/connections/rawConnection_seek.R") }
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R") }
+#{ source("tmptest/connections/rawConnection_writeBin.R") }
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R") }
+#{ source("tmptest/connections/readLines_GnuR_example.R") }
 [1] "TITLE extra line" "2 3 5 7"          ""                 "11 13 17"
 [5] "123"              "abc"              "123"              "abc def"
 Warning message:
 In readLines("test1") : incomplete final line found on 'test1'
 
 ##com.oracle.truffle.r.test.library.base.TestConnections.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R") }
+#{ source("tmptest/connections/textConnection.R") }
 Read 4 items
 Read 4 items
 
@@ -79211,40 +79890,31 @@ Error in get("x") : object 'x' not found
 [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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(1, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(2, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(3, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(4, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(5, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(6, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(7, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(8, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##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"
+#library(parallel); fun <- function(data) { cl <- makeCluster(9, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); parLapply(cl, data, function(x) x+1); stopCluster(cl) }; fun(1:100)
 
 ##com.oracle.truffle.r.test.library.base.TestSimpleArithmetic.testArithmeticUpdate#
 #{ x <- 3 ; f <- function(z) { if (z) { x <- 1 } ; x <- 1L + x ; x } ; f(FALSE) }
@@ -82570,6 +83240,46 @@ Error: attempt to use zero-length variable name
 #{ `` <- 123 }
 Error: attempt to use zero-length variable name
 
+##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
+#proto <- c(11,11); f <- function() { for (i in 1:2) print(proto[[i]] <- i); proto }; f()
+[1] 1
+[1] 2
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
+#proto <- c(11,11); f <- function() { for (i in 1:2) print(proto[[i]] <<- i); proto }; f()
+[1] 1
+[1] 2
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
+#proto <- c(11,11); f <- function() { for (i in 1:2) proto[[i]] <- i; proto }; f()
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
+#proto <- c(11,11); f <- function() { for (i in 1:2) proto[[i]] <<- i; proto }; f()
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
+#proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) print(proto[[i]] <- i); proto }; f()
+[1] 1
+[1] 2
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
+#proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) print(proto[[i]] <<- i); proto }; f()
+[1] 1
+[1] 2
+[1] 4 5
+
+##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
+#proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) proto[[i]] <- i; proto }; f()
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
+#proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) proto[[i]] <<- i; proto }; f()
+[1] 4 5
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleAssignment.testMisc#
 #{ `f<-` <- function(x, y=42, value) { x[1]<-value+y; x }; y<-1:10; f(y)<-7; y }
  [1] 49  2  3  4  5  6  7  8  9 10
@@ -85338,15 +86048,15 @@ list()
 
 
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListDuplication#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l$x); l$x <- 1:10; id == .fastr.identity(l$x) }
+#if (!any(R.version$engine == "FastR")) { FALSE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l$x); l$x <- 1:10; id == .fastr.identity(l$x) }
 [1] FALSE
 
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListDuplication#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l$x); l$x[2] <- 10; id == .fastr.identity(l$x) }
+#if (!any(R.version$engine == "FastR")) { TRUE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l$x); l$x[2] <- 10; id == .fastr.identity(l$x) }
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListDuplication#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l); l$x[2] <- 10; id == .fastr.identity(l) }
+#if (!any(R.version$engine == "FastR")) { TRUE } else { l <- list(x=c(3,4,5)); id <- .fastr.identity(l); l$x[2] <- 10; id == .fastr.identity(l) }
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.base.TestSimpleLists.testListRefcounting#
@@ -87673,6 +88383,14 @@ NULL
 #{ (0-5):(0-9) }
 [1] -5 -6 -7 -8 -9
 
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ (0/0):(0/0) }
+Error in (0/0):(0/0) : NA/NaN argument
+
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ (0/0):1L }
+Error in (0/0):1L : NA/NaN argument
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
 #{ (1:3):(1:3) }
 [1] 1
@@ -87688,6 +88406,34 @@ Warning messages:
 Warning message:
 In (1:3):3 : numerical expression has 3 elements: only the first used
 
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ -Inf:0 }
+Error in -Inf:0 : result would be too long a vector
+
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ -Inf:0L }
+Error in -Inf:0L : result would be too long a vector
+
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ -Inf:Inf }
+Error in -Inf:Inf : result would be too long a vector
+
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ 0:-Inf }
+Error in 0:-Inf : result would be too long a vector
+
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ 0:Inf }
+Error in 0:Inf : result would be too long a vector
+
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ 0L:-Inf }
+Error in 0L:-Inf : result would be too long a vector
+
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ 0L:Inf }
+Error in 0L:Inf : result would be too long a vector
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
 #{ 1.1:3.1 }
 [1] 1.1 2.1 3.1
@@ -87735,6 +88481,10 @@ Error in 1:NA : NA/NaN argument
 #{ 1L:(0-10) }
  [1]   1   0  -1  -2  -3  -4  -5  -6  -7  -8  -9 -10
 
+##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
+#{ 1L:(0/0) }
+Error in 1L:(0/0) : NA/NaN argument
+
 ##com.oracle.truffle.r.test.library.base.TestSimpleSequences.testSequenceConstruction#
 #{ 3.1:1 }
 [1] 3.1 2.1 1.1
@@ -124711,7 +125461,7 @@ Error in x[[0]] <- c(5) :
 #{ x <- NULL; x[[1]] <- c(); x; }
 NULL
 
-##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#Ignored.Unimplemented#
+##com.oracle.truffle.r.test.library.base.TestSimpleVectors.testNullUpdate#
 #{ x <- NULL; x[[1]] <- c(1,5); x; }
 [[1]]
 [1] 1 5
@@ -130445,19 +131195,19 @@ a b c d e
 [1] 42
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels1.R") }
+#{ source("tmptest/channels/channels1.R") }
 [1]  7 42
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels10.R") }
+#{ source("tmptest/channels/channels10.R") }
 [1]  7 42
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels11.R") }
+#{ source("tmptest/channels/channels11.R") }
 [1]  7 42
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels12.R") }
+#{ source("tmptest/channels/channels12.R") }
 [[1]]
 [1] 7
 
@@ -130466,7 +131216,7 @@ a b c d e
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels13.R") }
+#{ source("tmptest/channels/channels13.R") }
 [[1]]
 [1]  7 42
 
@@ -130475,11 +131225,11 @@ a b c d e
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels14.R") }
+#{ source("tmptest/channels/channels14.R") }
 [1] 42  7
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels15.R") }
+#{ source("tmptest/channels/channels15.R") }
 [[1]]
 [1] "baz" "bar"
 
@@ -130488,15 +131238,15 @@ a b c d e
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels16.R") }
+#{ source("tmptest/channels/channels16.R") }
 [1] 7 7
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels17.R") }
+#{ source("tmptest/channels/channels17.R") }
 [1] 42  7
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels2.R") }
+#{ source("tmptest/channels/channels2.R") }
 [[1]]
 [1] 7
 
@@ -130505,11 +131255,11 @@ a b c d e
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels3.R") }
+#{ source("tmptest/channels/channels3.R") }
 [1] 49
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels4.R") }
+#{ source("tmptest/channels/channels4.R") }
 [[1]]
 [1] 7
 
@@ -130518,7 +131268,7 @@ a b c d e
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels5.R") }
+#{ source("tmptest/channels/channels5.R") }
 [[1]]
 [1] 7
 
@@ -130527,7 +131277,7 @@ a b c d e
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels6.R") }
+#{ source("tmptest/channels/channels6.R") }
 [[1]]
 [1] 7
 
@@ -130536,1497 +131286,10515 @@ a b c d e
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels7.R") }
+#{ source("tmptest/channels/channels7.R") }
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels8.R") }
+#{ source("tmptest/channels/channels8.R") }
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/channels9.R") }
+#{ source("tmptest/channels/channels9.R") }
 [1]  TRUE FALSE
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing1.R") }
+#{ source("tmptest/channels/contexts1.R") }
+[1]  7 42
+
+##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
+#{ source("tmptest/channels/sharing1.R") }
 [1] 42  7
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing2.R") }
+#{ source("tmptest/channels/sharing2.R") }
 [1] "object 'x' not found"
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing3.R") }
+#{ source("tmptest/channels/sharing3.R") }
 [1] 42  7
 
 ##com.oracle.truffle.r.test.library.fastr.TestChannels.runRSourceTests#
-#{ source("mxbuild/com.oracle.truffle.r.test/bin/com/oracle/truffle/r/test/channels/R/sharing4.R") }
+#{ source("tmptest/channels/sharing4.R") }
 [1] 24 42
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testChannelConnection#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('hi there', zz); close(zz); NULL  }
+#if (!any(R.version$engine == "FastR")) { NULL } else { v <- import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('hi there', zz); close(zz); NULL  }
 NULL
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testChannelConnection#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('Hello, World!', 'second line') } else { v <- .fastr.interop.import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res }
+#if (!any(R.version$engine == "FastR")) { c('Hello, World!', 'second line') } else { v <- import('_fastr_channel0'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res }
 [1] "Hello, World!" "second line"
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { .fastr.interop.eval('application/x-r', '1') }
+#if (!any(R.version$engine == "FastR")) { 1 } else { eval.external('application/x-r', '1') }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 16 } else { .fastr.interop.eval('application/x-r', '14 + 2') }
+#if (!any(R.version$engine == "FastR")) { 16 } else { eval.external('application/x-r', '14 + 2') }
 [1] 16
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1L } else { .fastr.interop.eval('application/x-r', '1L') }
+#if (!any(R.version$engine == "FastR")) { 1L } else { eval.external('application/x-r', '1L') }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { .fastr.interop.eval('application/x-r', 'TRUE') }
+#if (!any(R.version$engine == "FastR")) { TRUE } else { eval.external('application/x-r', 'TRUE') }
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEval#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { as.character(123) } else { .fastr.interop.eval('application/x-r', 'as.character(123)') }
+#if (!any(R.version$engine == "FastR")) { as.character(123) } else { eval.external('application/x-r', 'as.character(123)') }
 [1] "123"
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[1] "Error reading file: /a/b.R"\n') } else { tryCatch(.fastr.interop.evalFile("/a/b.R"),  error = function(e) e$message) }
+#if (!any(R.version$engine == "FastR")) { cat('Error in eval.external() : invalid \'source\' or \'path\' argument\n') } else { eval.external() }
+Error in eval.external() : invalid 'source' or 'path' argument
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile#
+#if (!any(R.version$engine == "FastR")) { cat('Error in eval.external(, "abc", ) : invalid mimeType argument\n') } else { eval.external(,'abc',) }
+Error in eval.external(, "abc", ) : invalid mimeType argument
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropEvalFile#
+#if (!any(R.version$engine == "FastR")) { cat('[1] "Error reading file: /a/b.R"\n') } else { tryCatch(eval.external(path="/a/b.R"),  error = function(e) e$message) }
 [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("_testInteropEvalFile_testScript_.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("_testInteropEvalFile_testScript_.R") }
+#if (!any(R.version$engine == "FastR")) { x<-c(1);cat(x) } else { fileConn<-file("_testInteropEvalFile_testScript_.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);eval.external(mimeType="application/x-r", path="_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("_testInteropEvalFile_testScript_.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);.fastr.interop.evalFile("_testInteropEvalFile_testScript_.R","application/x-r") }
+#if (!any(R.version$engine == "FastR")) { x<-c(1);cat(x) } else { fileConn<-file("_testInteropEvalFile_testScript_.R");writeLines(c("x<-c(1)","cat(x)"), fileConn);close(fileConn);eval.external(path="_testInteropEvalFile_testScript_.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') }
+#if (!any(R.version$engine == "FastR")) { invisible() } else { export('foo', 'foo') }
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 14 + 2) }
+#if (!any(R.version$engine == "FastR")) { invisible() } else { export('foo', 14 + 2) }
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', 1:100) }
+#if (!any(R.version$engine == "FastR")) { invisible() } else { export('foo', 1:100) }
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testInteropExport#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { invisible() } else { .fastr.interop.export('foo', new.env()) }
+#if (!any(R.version$engine == "FastR")) { invisible() } else { export('foo', new.env()) }
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.executable() }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.executable(NULL) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.executable(c(1)) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.executable(list(1)) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalExecutable#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { is.external.executable(sum) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalNull#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.null() }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalNull#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.null(c(1)) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalNull#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { is.external.null(list(1)) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestInterop.testIsExternalNull#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { is.external.null(NULL) }
+[1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('intValue', 'longValue', 'charValue', 'shortValue', 'booleanValue', 'stringValue') } else { v <- .fastr.interop.import('testPOJO'); names(v) }
-[1] "intValue"     "longValue"    "charValue"    "shortValue"   "booleanValue"
-[6] "stringValue"
+#if (!any(R.version$engine == "FastR")) { c('stringValue', 'charValue', 'intValue', 'shortValue', 'booleanValue', 'longValue') } else { v <- import('testPOJO'); names(v) }
+[1] "stringValue"  "charValue"    "intValue"     "shortValue"   "booleanValue"
+[6] "longValue"
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#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) }
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n$stringValue\n[1] "foo"\n\n$charValue\n[1] "R"\n\n$intValue\n[1] 1\n\n$shortValue\n[1] -100\n\n$booleanValue\n[1] TRUE\n\n$longValue\n[1] 123412341234\n\n') } else { v <- import('testPOJO'); print(v) }
 [external object]
-$intValue
-[1] 1
-
-$longValue
-[1] 123412341234
+$stringValue
+[1] "foo"
 
 $charValue
 [1] "R"
 
+$intValue
+[1] 1
+
 $shortValue
 [1] -100
 
 $booleanValue
 [1] TRUE
 
-$stringValue
-[1] "foo"
+$longValue
+[1] 123412341234
 
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#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) }
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1]   1  -5 199\n') } else { v <- import('testIntArray'); print(v) }
 [external object]
 [1]   1  -5 199
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#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 }
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1]   1  -5 199\n') } else { v <- import('testIntArray'); v }
 [external object]
 [1]   1  -5 199
 
 ##com.oracle.truffle.r.test.library.fastr.TestInterop.testPrinting#
-#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) }
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a"   ""    "foo"\n') } else { v <- import('testStringArray'); print(v) }
 [external object]
 [1] "a"   ""    "foo"
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAddToList#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l <- list();  l$foreignobject <- to; identical(to, l$foreignobject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAddToList#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l <- list(1); l$foreignobject <- 1; l$foreignobject <- to; identical(to, l$foreignobject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAddToList#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l <- list(1); l$foreignobject <- to; identical(to, l$foreignobject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAddToList#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l <- list(to); is.list(l) }
+[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") }
+#if (!any(R.version$engine == "FastR")) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$allTypesMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
 [1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
 
 ##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$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
+#if (!any(R.version$engine == "FastR")) { "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$allTypesStaticMethod(TRUE,127,"a",32767,2147483647,9223372036854775807,1.7976931348623157E308,3.4028235E38,"testString") }
 [1] "true127a32767214748364792233720368547758071.7976931348623157E3083.4028235E38testString"
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAsParameter#
+#if (!any(R.version$engine == "FastR")) { '[I' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));ja <- as.java.array(c(1L, 2L, 3L), 'int'); to$isIntArray(ja) }
+[1] "[I"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayAsParameter#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Integer;' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));ja <- as.java.array(c(1L, 2L, 3L), 'java.lang.Integer'); to$isIntegerArray(ja) }
+[1] "[Ljava.lang.Integer;"
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { a <- .fastr.java.toArray(c(1,2,3)); a[1] }
+#if (!any(R.version$engine == "FastR")) { 1 } else { a <- as.java.array(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 { a <- .fastr.java.toArray(c(1,2,3)); a[[1]] }
+#if (!any(R.version$engine == "FastR")) { 1 } else { a <- as.java.array(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 (!any(R.version$engine == "FastR")) { 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldIntegerArray[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 (!any(R.version$engine == "FastR")) { 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldIntegerArray[[1]]; }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 123 } else { a <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1] }
+#if (!any(R.version$engine == "FastR")) { 123 } else { a <- as.java.array(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 { a <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]] }
+#if (!any(R.version$engine == "FastR")) { 123 } else { a <- as.java.array(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.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1] }
+#if (!any(R.version$engine == "FastR")) { 123 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldIntegerArray[1] <- 123L; to$fieldIntegerArray[1] }
 [1] 123
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]] <- 1234L; t$fieldIntArray[[1]] }
+#if (!any(R.version$engine == "FastR")) { 1234 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldIntegerArray[[1]] <- 1234L; to$fieldIntegerArray[[1]] }
 [1] 1234
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1234 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] <- 1234L; t$int2DimArray[1,2] }
+#if (!any(R.version$engine == "FastR")) { 1234 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$int2DimArray[1,2] <- 1234L; to$int2DimArray[1,2] }
 [1] 1234
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 12345 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] <- 12345L; t$int2DimArray[[1,2]] }
+#if (!any(R.version$engine == "FastR")) { 12345 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$int2DimArray[[1,2]] <- 12345L; to$int2DimArray[[1,2]] }
 [1] 12345
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] }
+#if (!any(R.version$engine == "FastR")) { 2 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$int2DimArray[1,2] }
 [1] 2
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] }
+#if (!any(R.version$engine == "FastR")) { 2 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$int2DimArray[[1,2]] }
 [1] 2
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringArray[1] <- NULL; t$fieldStringArray[1] }
+#if (!any(R.version$engine == "FastR")) { NULL } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStringArray[1] <- NULL; to$fieldStringArray[1] }
 NULL
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#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] }
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$int2DimArray[1] }
 [external object]
 [1] 1 2 3
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testArrayReadWrite#
-#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]] }
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$int2DimArray[[1]] }
 [external object]
 [1] 1 2 3
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 'a' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$arrayObject); l[[1]]$data }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 'a' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$fieldStringArray); l[[1]] }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 'a' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listObject); l[[1]]$data }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 'a' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listString); l[[1]] }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 'b' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$arrayObject); l[[2]]$data }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 'b' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$fieldStringArray); l[[2]] }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 'b' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listObject); l[[2]]$data }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 'b' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listString); l[[2]] }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 3 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$fieldStringArray); length(l) }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 3 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listString); length(l) }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 4 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$arrayObject); length(l) }
+[1] 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { 4 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listObject); length(l) }
+[1] 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { NULL } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$arrayObject); l[[4]]$data }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { NULL } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listObject); l[[4]]$data }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$arrayObject); is.list(l) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$fieldStringArray); is.list(l) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listObject); is.list(l) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to$listString); is.list(l) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsList#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.list(to) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a list', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); l<-as.list(to); }
+Error in as.list(to) :
+  no method for coercing this external object to a list
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "character" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticCharArray); typeof(v) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "character" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticStringArray); typeof(v) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "double" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticDoubleArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "double" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticFloatArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "double" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticLongArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "double" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectDoubleArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "integer" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticByteArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "integer" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticIntegerArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "integer" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticShortArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "integer" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectIntArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { "logical" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticBooleanArray); typeof(v) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticBooleanArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticByteArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticCharArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticDoubleArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticFloatArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticIntegerArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticLongArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticShortArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticStringArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$hasNullIntArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$mixedTypesArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectDoubleArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectIntArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { list(1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$hasNullIntArray); v[1] }
+[[1]]
+[1] 1
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { list(3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$hasNullIntArray); v[3] }
+[[1]]
+[1] 3
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsVectorFromArray#
+#if (!any(R.version$engine == "FastR")) { list(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$hasNullIntArray); v[2] }
+[[1]]
+NULL
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character("1.10000002384186") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticFloatObject) }
+[1] "1.10000002384186"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character("1.79769313486231e+308") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticDoubleObject) }
+[1] "1.79769313486231e+308"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character("NaN") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticNaNObject) }
+[1] "NaN"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticStringObject) }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticCharObject) }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticByteObject) }
+[1] "127"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticIntegerObject) }
+[1] "2147483647"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticShortObject) }
+[1] "32767"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Ignored.ImplementationError#
+#if (!any(R.version$engine == "FastR")) { as.character(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticLongObject) }
+[1] "9223372036854775808"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticNullObject) }
+character(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStaticBooleanObject) }
+[1] "TRUE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStringIntArray); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listStringInt); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("1.1","2.1","3.1")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldDoubleArray); }
+[1] "1.1" "2.1" "3.1"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("1.1","2.1","3.1")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listDouble); }
+[1] "1.1" "2.1" "3.1"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("1.10000002384186","2.09999990463257","3.09999990463257")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldFloatArray); }
+[1] "1.10000002384186" "2.09999990463257" "3.09999990463257"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("1.10000002384186","2.09999990463257","3.09999990463257")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listFloat); }
+[1] "1.10000002384186" "2.09999990463257" "3.09999990463257"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStringBooleanArray); }
+[1] "TRUE"  "TRUE"  "FALSE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listStringBoolean); }
+[1] "TRUE"  "TRUE"  "FALSE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldCharArray); }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldStringArray); }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listChar); }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listString); }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldByteArray); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldIntegerArray); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldLongArray); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldShortArray); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listByte); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listInteger); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listLong); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listShort); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$fieldBooleanArray); }
+[1] "TRUE"  "FALSE" "TRUE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.character(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listBoolean); }
+[1] "TRUE"  "FALSE" "TRUE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.complex("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticStringObject) }
+[1] NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.complex("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticCharObject) }
+[1] NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(1.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticFloatObject) }
+[1] 1.1+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(1.7976931348623157E308) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticDoubleObject) }
+[1] 1.797693e+308+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticByteObject) }
+[1] 127+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticIntegerObject) }
+[1] 2147483647+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticShortObject) }
+[1] 32767+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticLongObject) }
+[1] 9.223372e+18+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticNullObject) }
+complex(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(NaN) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticNaNObject) }
+[1] NaN+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStaticBooleanObject) }
+[1] 1+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStringIntArray); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listStringInt); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.complex(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStringBooleanArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.complex(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listStringBoolean); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.complex(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldCharArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.complex(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldStringArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.complex(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listChar); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.complex(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listString); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldByteArray); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldIntegerArray); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldLongArray); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldShortArray); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listByte); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listInteger); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listLong); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listShort); }
+[1] 1+0i 2+0i 3+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldDoubleArray); }
+[1] 1.1+0i 2.1+0i 3.1+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldFloatArray); }
+[1] 1.1+0i 2.1+0i 3.1+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listDouble); }
+[1] 1.1+0i 2.1+0i 3.1+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listFloat); }
+[1] 1.1+0i 2.1+0i 3.1+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$fieldBooleanArray); }
+[1] 1+0i 0+0i 1+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.complex(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to$listBoolean); }
+[1] 1+0i 0+0i 1+0i
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.double("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticStringObject) }
+[1] NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.double("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticCharObject) }
+[1] NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(1.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticFloatObject) }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(1.7976931348623157E308) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticDoubleObject) }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticByteObject) }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticIntegerObject) }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticShortObject) }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticLongObject) }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticNullObject) }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(NaN) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticNaNObject) }
+[1] NaN
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStaticBooleanObject) }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStringIntArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listStringInt); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.double(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStringBooleanArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.double(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listStringBoolean); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.double(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldCharArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.double(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldStringArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.double(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listChar); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.double(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listString); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldByteArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldIntegerArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldLongArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldShortArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listByte); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listInteger); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listLong); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listShort); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldDoubleArray); }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldFloatArray); }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listDouble); }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listFloat); }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$fieldBooleanArray); }
+[1] 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.double(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to$listBoolean); }
+[1] 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticStringObject) }
+expression("a string")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticCharObject) }
+expression("a")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(1.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticFloatObject) }
+expression(1.1)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Ignored.ImplementationError#
+#if (!any(R.version$engine == "FastR")) { as.expression(1.7976931348623157E308) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticDoubleObject) }
+expression(1.79769313486232e+308)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticByteObject) }
+expression(127)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticIntegerObject) }
+expression(2147483647)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticShortObject) }
+expression(32767)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Ignored.ImplementationError#
+#if (!any(R.version$engine == "FastR")) { as.expression(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticLongObject) }
+expression(9223372036854775808)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticNullObject) }
+expression(NULL)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(NaN) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticNaNObject) }
+expression(NaN)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStaticBooleanObject) }
+expression(TRUE)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStringIntArray); }
+expression("1", "2", "3")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listStringInt); }
+expression("1", "2", "3")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStringBooleanArray); }
+expression("TRUE", "TRUE", "FALSE")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listStringBoolean); }
+expression("TRUE", "TRUE", "FALSE")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldCharArray); }
+expression("a", "b", "c")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldStringArray); }
+expression("a", "b", "c")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listChar); }
+expression("a", "b", "c")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listString); }
+expression("a", "b", "c")
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldByteArray); }
+expression(1, 2, 3)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldIntegerArray); }
+expression(1, 2, 3)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldLongArray); }
+expression(1, 2, 3)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldShortArray); }
+expression(1, 2, 3)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listByte); }
+expression(1, 2, 3)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listInteger); }
+expression(1, 2, 3)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listLong); }
+expression(1, 2, 3)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listShort); }
+expression(1, 2, 3)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldDoubleArray); }
+expression(1.1, 2.1, 3.1)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldFloatArray); }
+expression(1.1, 2.1, 3.1)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listDouble); }
+expression(1.1, 2.1, 3.1)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listFloat); }
+expression(1.1, 2.1, 3.1)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$fieldBooleanArray); }
+expression(TRUE, FALSE, TRUE)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.expression(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to$listBoolean); }
+expression(TRUE, FALSE, TRUE)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.integer("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticStringObject) }
+[1] NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.integer("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticCharObject) }
+[1] NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(1.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticFloatObject) }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(1.7976931348623157E308) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticDoubleObject) }
+[1] NA
+Warning message:
+NAs introduced by coercion to integer range
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticByteObject) }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticIntegerObject) }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticShortObject) }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticLongObject) }
+[1] NA
+Warning message:
+NAs introduced by coercion to integer range
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticNullObject) }
+integer(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(NaN) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticNaNObject) }
+[1] NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStaticBooleanObject) }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStringIntArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listStringInt); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.integer(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStringBooleanArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.integer(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listStringBoolean); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.integer(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldCharArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.integer(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldStringArray); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.integer(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listChar); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.integer(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listString); }
+[1] NA NA NA
+Warning message:
+NAs introduced by coercion
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldByteArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldIntegerArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldLongArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldShortArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listByte); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listInteger); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listLong); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listShort); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldDoubleArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldFloatArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listDouble); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listFloat); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$fieldBooleanArray); }
+[1] 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.integer(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to$listBoolean); }
+[1] 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticStringObject) }
+[1] NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticCharObject) }
+[1] NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(1.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticFloatObject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(1.7976931348623157E308) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticDoubleObject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticByteObject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticIntegerObject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticShortObject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticLongObject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticNullObject) }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(NaN) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticNaNObject) }
+[1] NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStaticBooleanObject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStringIntArray); }
+[1] NA NA NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listStringInt); }
+[1] NA NA NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStringBooleanArray); }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listStringBoolean); }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldCharArray); }
+[1] NA NA NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldStringArray); }
+[1] NA NA NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listChar); }
+[1] NA NA NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listString); }
+[1] NA NA NA
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldByteArray); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldIntegerArray); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldLongArray); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldShortArray); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listByte); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listInteger); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listLong); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listShort); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldDoubleArray); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldFloatArray); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listDouble); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listFloat); }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$fieldBooleanArray); }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.logical(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to$listBoolean); }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticStringObject) }
+[1] 00
+Warning messages:
+1: NAs introduced by coercion
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticCharObject) }
+[1] 00
+Warning messages:
+1: NAs introduced by coercion
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(1.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticFloatObject) }
+[1] 01
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw(1.7976931348623157E308) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticDoubleObject) }
+[1] 00
+Warning messages:
+1: NAs introduced by coercion to integer range
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticByteObject) }
+[1] 7f
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticIntegerObject) }
+[1] 00
+Warning message:
+out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticShortObject) }
+[1] 00
+Warning message:
+out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticLongObject) }
+[1] 00
+Warning messages:
+1: NAs introduced by coercion to integer range
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticNullObject) }
+raw(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw(NaN) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticNaNObject) }
+[1] 00
+Warning message:
+out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStaticBooleanObject) }
+[1] 01
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStringIntArray); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listStringInt); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.raw(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStringBooleanArray); }
+[1] 00 00 00
+Warning messages:
+1: NAs introduced by coercion
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.raw(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listStringBoolean); }
+[1] 00 00 00
+Warning messages:
+1: NAs introduced by coercion
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldCharArray); }
+[1] 00 00 00
+Warning messages:
+1: NAs introduced by coercion
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldStringArray); }
+[1] 00 00 00
+Warning messages:
+1: NAs introduced by coercion
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningMessage#
+#if (!any(R.version$engine == "FastR")) { as.raw(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listChar); }
+[1] 00 00 00
+Warning messages:
+1: NAs introduced by coercion
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { as.raw(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listString); }
+[1] 00 00 00
+Warning messages:
+1: NAs introduced by coercion
+2: out-of-range values treated as 0 in coercion to raw
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldByteArray); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldIntegerArray); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldLongArray); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldShortArray); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listByte); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listInteger); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listLong); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listShort); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldDoubleArray); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldFloatArray); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listDouble); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listFloat); }
+[1] 01 02 03
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$fieldBooleanArray); }
+[1] 01 00 01
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.raw(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to$listBoolean); }
+[1] 01 00 01
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticStringObject) }
+`a string`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticCharObject) }
+a
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Ignored.ImplementationError#
+#if (!any(R.version$engine == "FastR")) { as.symbol(1.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticFloatObject) }
+`1.1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Ignored.ImplementationError#
+#if (!any(R.version$engine == "FastR")) { as.symbol(1.7976931348623157E308) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticDoubleObject) }
+`1.797693e+308`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticByteObject) }
+`127`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticIntegerObject) }
+`2147483647`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticShortObject) }
+`32767`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Ignored.ImplementationError#
+#if (!any(R.version$engine == "FastR")) { as.symbol(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticLongObject) }
+`9.223372e+18`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { as.symbol(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticNullObject) }
+Error in as.symbol(NULL) :
+  invalid type/length (symbol/0) in vector allocation
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(NaN) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticNaNObject) }
+`NaN`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStaticBooleanObject) }
+`TRUE`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStringIntArray); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listStringInt); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStringBooleanArray); }
+`TRUE`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listStringBoolean); }
+`TRUE`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldCharArray); }
+a
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldStringArray); }
+a
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listChar); }
+a
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listString); }
+a
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldByteArray); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldIntegerArray); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldLongArray); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldShortArray); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listByte); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listInteger); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listLong); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listShort); }
+`1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldDoubleArray); }
+`1.1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Ignored.ImplementationError#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldFloatArray); }
+`1.1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listDouble); }
+`1.1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Ignored.ImplementationError#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listFloat); }
+`1.1`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$fieldBooleanArray); }
+`TRUE`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.symbol(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to$listBoolean); }
+`TRUE`
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector("a string") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticStringObject) }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector("a") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticCharObject) }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(1.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticFloatObject) }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(1.7976931348623157E308) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticDoubleObject) }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(127) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticByteObject) }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticIntegerObject) }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(32767) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticShortObject) }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(9223372036854775807) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticLongObject) }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticNullObject) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(NaN) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticNaNObject) }
+[1] NaN
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStaticBooleanObject) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStringIntArray); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c("1","2","3")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listStringInt); }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStringBooleanArray); }
+[1] "TRUE"  "TRUE"  "FALSE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c("TRUE","TRUE","FALSE")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listStringBoolean); }
+[1] "TRUE"  "TRUE"  "FALSE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldCharArray); }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldStringArray); }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listChar); }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c("a","b","c")) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listString); }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldByteArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldIntegerArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldLongArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldShortArray); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listByte); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listInteger); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listLong); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1,2,3)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listShort); }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldDoubleArray); }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldFloatArray); }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listDouble); }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(1.1,2.1,3.1)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listFloat); }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$fieldBooleanArray); }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { as.vector(c(TRUE,FALSE,TRUE)) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to$listBoolean); }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.character(to) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a vector', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to); }
+Error in as.character(to) :
+  no method for coercing this external object to a vector
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.complex(to) :', '<<<NEWLINE>>>', ' cannot coerce type \'truffleobject\' to vector of type \'complex\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.complex(to); }
+Error in as.complex(to) :
+  cannot coerce type 'truffleobject' to vector of type 'complex'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.double(to) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a vector', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.double(to); }
+Error in as.double(to) :
+  no method for coercing this external object to a vector
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.expression(to) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a vector', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.expression(to); }
+Error in as.expression(to) :
+  no method for coercing this external object to a vector
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.integer(to) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a vector', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.integer(to); }
+Error in as.integer(to) :
+  no method for coercing this external object to a vector
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.logical(to) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a vector', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.logical(to); }
+Error in as.logical(to) :
+  no method for coercing this external object to a vector
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.raw(to) :', '<<<NEWLINE>>>', ' cannot coerce type \'truffleobject\' to vector of type \'raw\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.raw(to); }
+Error in as.raw(to) :
+  cannot coerce type 'truffleobject' to vector of type 'raw'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.symbol(to) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a vector', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.symbol(to); }
+Error in as.symbol(to) :
+  no method for coercing this external object to a vector
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testAsXXX#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.vector(to) :', '<<<NEWLINE>>>', ' no method for coercing this external object to a vector', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.vector(to); }
+Error in as.vector(to) :
+  no method for coercing this external object to a vector
+
 ##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) }
+#if (!any(R.version$engine == "FastR")) { NULL } else { to <- new.external(new.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' }
+#if (!any(R.version$engine == "FastR")) { cat('Error in attr(to, "a") <- "a" : external object cannot be attributed', '<<<NEWLINE>>>') } else { to <- new.external(new.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') }
+#if (!any(R.version$engine == "FastR")) { cat('Error in attr(to, which = "a") : external object cannot be attributed', '<<<NEWLINE>>>') } else { to <- new.external(new.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#Ignored.ImplementationError#
-#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) }
+#if (!any(R.version$engine == "FastR")) { "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$classAsArg(new.java.class(com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass)) }
 [1] "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { class(c(.fastr.interop.toByte(123))) }
-[1] "interopt.byte"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { 'list' } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- new.external(tc); t1 <- new.external(tc); class(c(t, t1)) }
+[1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234))) }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { 'list' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); class(c(1, t)) }
 [1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(.fastr.interop.toByte(123), 1)) }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { 'list' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); class(c(t, 1)) }
 [1] "list"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { class(c(1, .fastr.interop.toByte(123))) }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { 'list' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); class(c(to)) }
 [1] "list"
 
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("1","2","3") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listStringInt) }
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("1","2","3","1","2","3") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listStringInt, to$listStringInt) }
+[1] "1" "2" "3" "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("TRUE","TRUE","FALSE") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listStringBoolean) }
+[1] "TRUE"  "TRUE"  "FALSE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("TRUE","TRUE","FALSE","TRUE","TRUE","FALSE") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listStringBoolean, to$listStringBoolean) }
+[1] "TRUE"  "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldCharArray) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldStringArray) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listChar) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listString) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("a","b","c","a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldCharArray, to$fieldCharArray) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("a","b","c","a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldStringArray, to$fieldStringArray) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("a","b","c","a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listChar, to$listChar) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c("a","b","c","a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listString, to$listString) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c() } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listEmpty) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c() } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listEmpty, to$listEmpty) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldByteArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldIntegerArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldLongArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldShortArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listByte) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listInteger) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listLong) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listShort) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3,1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldByteArray, to$fieldByteArray) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3,1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldIntegerArray, to$fieldIntegerArray) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3,1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldLongArray, to$fieldLongArray) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3,1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldShortArray, to$fieldShortArray) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3,1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listByte, to$listByte) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3,1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listInteger, to$listInteger) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3,1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listLong, to$listLong) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3,1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listShort, to$listShort) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldDoubleArray) }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldFloatArray) }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listDouble) }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listFloat) }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1,1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldDoubleArray, to$fieldDoubleArray) }
+[1] 1.1 2.1 3.1 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1,1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldFloatArray, to$fieldFloatArray) }
+[1] 1.1 2.1 3.1 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1,1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listDouble, to$listDouble) }
+[1] 1.1 2.1 3.1 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1,1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listFloat, to$listFloat) }
+[1] 1.1 2.1 3.1 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldBooleanArray) }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listBoolean) }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE,TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$fieldBooleanArray, to$fieldBooleanArray) }
+[1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineForeignObjects#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE,TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(to$listBoolean, to$listBoolean) }
+[1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(1, t)) }
-[1] "list"
+#if (!any(R.version$engine == "FastR")) { 'interopt.byte' } else { class(c(as.external.byte(123))) }
+[1] "interopt.byte"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(t, 1)) }
+#if (!any(R.version$engine == "FastR")) { 'list' } else { class(c(1, as.external.byte(123))) }
 [1] "list"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'list' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t1 <- .fastr.interop.new(tc); class(c(t, t1)) }
+#if (!any(R.version$engine == "FastR")) { 'list' } else { class(c(as.external.byte(123), 1)) }
 [1] "list"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testCombineInteropTypes#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'truffle.object' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); class(c(t)) }
-[1] "truffle.object"
+#if (!any(R.version$engine == "FastR")) { 'list' } else { class(c(as.external.byte(123), as.external.byte(234))) }
+[1] "list"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testConvertEmptyList#
+#if (!any(R.version$engine == "FastR")) { as.character(list()) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));as.character(to$listEmpty); }
+character(0)
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticStringObject }
+#if (!any(R.version$engine == "FastR")) { "a string" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticStringObject }
 [1] "a string"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStringObject }
+#if (!any(R.version$engine == "FastR")) { "a string" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStringObject }
 [1] "a string"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldChar }
+#if (!any(R.version$engine == "FastR")) { "a" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldChar }
 [1] "a"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldCharObject }
+#if (!any(R.version$engine == "FastR")) { "a" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldCharObject }
 [1] "a"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticChar }
+#if (!any(R.version$engine == "FastR")) { "a" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticChar }
 [1] "a"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticCharObject }
+#if (!any(R.version$engine == "FastR")) { "a" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticCharObject }
 [1] "a"
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDouble }
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldFloat }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldFloatObject }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticFloat }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticFloatObject }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 1.7976931348623157E308 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldDouble }
 [1] 1.797693e+308
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldDoubleObject }
+#if (!any(R.version$engine == "FastR")) { 1.7976931348623157E308 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldDoubleObject }
 [1] 1.797693e+308
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDouble }
+#if (!any(R.version$engine == "FastR")) { 1.7976931348623157E308 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticDouble }
 [1] 1.797693e+308
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticDoubleObject }
+#if (!any(R.version$engine == "FastR")) { 1.7976931348623157E308 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticDoubleObject }
 [1] 1.797693e+308
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByte }
+#if (!any(R.version$engine == "FastR")) { 127 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldByte }
 [1] 127
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldByteObject }
+#if (!any(R.version$engine == "FastR")) { 127 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldByteObject }
 [1] 127
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByte }
+#if (!any(R.version$engine == "FastR")) { 127 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticByte }
 [1] 127
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticByteObject }
+#if (!any(R.version$engine == "FastR")) { 127 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticByteObject }
 [1] 127
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldInteger }
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldInteger }
 [1] 2147483647
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldIntegerObject }
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldIntegerObject }
 [1] 2147483647
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticInteger }
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticInteger }
 [1] 2147483647
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticIntegerObject }
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticIntegerObject }
 [1] 2147483647
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloat }
-[1] 3.402823e+38
+#if (!any(R.version$engine == "FastR")) { 32767 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldShort }
+[1] 32767
 
 ##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldFloatObject }
-[1] 3.402823e+38
+#if (!any(R.version$engine == "FastR")) { 32767 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldShortObject }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 32767 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticShort }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 32767 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticShortObject }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldLong }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldLongObject }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticLong }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticLongObject }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { NULL } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldNullObject }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { NULL } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticNullObject }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { NaN } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticNaN }
+[1] NaN
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { NaN } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticNaNObject }
+[1] NaN
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldBooleanObject }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticBooleanObject }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1]  TRUE FALSE  TRUE\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldBooleanArray }
+[external object]
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1]  TRUE FALSE  TRUE\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticBooleanArray }
+[external object]
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "1" "2" "3"\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStringIntArray }
+[external object]
+[1] "1" "2" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "TRUE"  "TRUE"  "FALSE"\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStringBooleanArray }
+[external object]
+[1] "TRUE"  "TRUE"  "FALSE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b" "c"\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldCharArray }
+[external object]
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b" "c"\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticCharArray }
+[external object]
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b" "c"\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticStringArray }
+[external object]
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b" "c"\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStringArray }
+[external object]
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldByteArray }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldIntegerArray }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldLongArray }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldShortArray }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticByteArray }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticIntegerArray }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticLongArray }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticShortArray }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldDoubleArray }
+[external object]
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldFloatArray }
+[external object]
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticDoubleArray }
+[external object]
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1 2.1 3.1\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStaticFloatArray }
+[external object]
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 0, 1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldBooleanArray) }
+[1] 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 0, 1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listBoolean) }
+[1] 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldByteArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldIntegerArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldLongArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldShortArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listByte) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listInteger) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listLong) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listShort) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldDoubleArray) }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldFloatArray) }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listDouble) }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listFloat) }
+[1] 1.1 2.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in abs(to$fieldCharArray) :', '<<<NEWLINE>>>', ' non-numeric argument to mathematical function', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldCharArray) }
+Error in abs(to$fieldCharArray) :
+  non-numeric argument to mathematical function
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in abs(to$fieldStringArray) :', '<<<NEWLINE>>>', ' non-numeric argument to mathematical function', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$fieldStringArray) }
+Error in abs(to$fieldStringArray) :
+  non-numeric argument to mathematical function
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in abs(to$listChar) : non-numeric argument to mathematical function', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listChar) }
+Error in abs(to$listChar) : non-numeric argument to mathematical function
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in abs(to$listString) :', '<<<NEWLINE>>>', ' non-numeric argument to mathematical function', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listString) }
+Error in abs(to$listString) :
+  non-numeric argument to mathematical function
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in abs(to$listStringInt) :', '<<<NEWLINE>>>', ' non-numeric argument to mathematical function', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to$listStringInt) }
+Error in abs(to$listStringInt) :
+  non-numeric argument to mathematical function
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in abs(to) : non-numeric argument to mathematical function', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));abs(to) }
+Error in abs(to) : non-numeric argument to mathematical function
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c('1', '3') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listStringInt) }
+[1] "1" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c('a', 'c') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldCharArray) }
+[1] "a" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c('a', 'c') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldStringArray) }
+[1] "a" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c('a', 'c') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listChar) }
+[1] "a" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c('a', 'c') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listString) }
+[1] "a" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(0, 1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldBooleanArray) }
+[1] 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(0, 1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listBoolean) }
+[1] 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldByteArray) }
+[1] 1 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldIntegerArray) }
+[1] 1 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldLongArray) }
+[1] 1 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldShortArray) }
+[1] 1 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listByte) }
+[1] 1 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listInteger) }
+[1] 1 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listLong) }
+[1] 1 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listShort) }
+[1] 1 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldDoubleArray) }
+[1] 1.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$fieldFloatArray) }
+[1] 1.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listDouble) }
+[1] 1.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to$listFloat) }
+[1] 1.1 3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignUnaryArithmeticReduceOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in min(x, na.rm = na.rm) : invalid \'type\' (list) of argument', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));range(to) }
+Error in min(x, na.rm = na.rm) : invalid 'type' (list) of argument
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldByteArray) }
+[1] -1 -2 -3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldIntegerArray) }
+[1] -1 -2 -3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldLongArray) }
+[1] -1 -2 -3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldShortArray) }
+[1] -1 -2 -3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listByte) }
+[1] -1 -2 -3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listInteger) }
+[1] -1 -2 -3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listLong) }
+[1] -1 -2 -3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listShort) }
+[1] -1 -2 -3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldDoubleArray) }
+[1] -1.1 -2.1 -3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldFloatArray) }
+[1] -1.1 -2.1 -3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listDouble) }
+[1] -1.1 -2.1 -3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listFloat) }
+[1] -1.1 -2.1 -3.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldBooleanArray) }
+[1] -1  0 -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { -c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listBoolean) }
+[1] -1  0 -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldByteArray }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldIntegerArray }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldLongArray }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldShortArray }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listByte }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listInteger }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listLong }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listShort }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldDoubleArray }
+[1] 2.1 3.1 4.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldFloatArray }
+[1] 2.1 3.1 4.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listDouble }
+[1] 2.1 3.1 4.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listFloat }
+[1] 2.1 3.1 4.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldBooleanArray }
+[1] 2 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { 1 + c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listBoolean }
+[1] 2 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldByteArray }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldIntegerArray }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldLongArray }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldShortArray }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listByte }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listInteger }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listLong }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listShort }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldDoubleArray }
+[1] 2.1 4.1 6.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldFloatArray }
+[1] 2.1 4.1 6.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listDouble }
+[1] 2.1 4.1 6.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listFloat }
+[1] 2.1 4.1 6.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldBooleanArray }
+[1] 2 2 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) + c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listBoolean }
+[1] 2 2 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray + 1 }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray + 1 }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray + 1 }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray + 1 }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte + 1 }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger + 1 }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong + 1 }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort + 1 }
+[1] 2 3 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray + c(1, 2, 3) }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray + c(1, 2, 3) }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray + c(1, 2, 3) }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray + c(1, 2, 3) }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte + c(1, 2, 3) }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger + c(1, 2, 3) }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong + c(1, 2, 3) }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort + c(1, 2, 3) }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray + to$fieldByteArray }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray + to$fieldIntegerArray }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray + to$fieldLongArray }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray + to$fieldShortArray }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte + to$listByte }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger + to$listInteger }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong + to$listLong }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) + c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort + to$listShort }
+[1] 2 4 6
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray + 1 }
+[1] 2.1 3.1 4.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray + 1 }
+[1] 2.1 3.1 4.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble + 1 }
+[1] 2.1 3.1 4.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat + 1 }
+[1] 2.1 3.1 4.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray + c(1, 2, 3) }
+[1] 2.1 4.1 6.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray + c(1, 2, 3) }
+[1] 2.1 4.1 6.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble + c(1, 2, 3) }
+[1] 2.1 4.1 6.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat + c(1, 2, 3) }
+[1] 2.1 4.1 6.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray + to$fieldDoubleArray }
+[1] 2.2 4.2 6.2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray + to$fieldFloatArray }
+[1] 2.2 4.2 6.2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble + to$listDouble }
+[1] 2.2 4.2 6.2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) + c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat + to$listFloat }
+[1] 2.2 4.2 6.2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray + 1 }
+[1] 2 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) + 1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean + 1 }
+[1] 2 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray + c(1, 2, 3) }
+[1] 2 2 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) + c(1, 2, 3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean + c(1, 2, 3) }
+[1] 2 2 4
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) + c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray + to$fieldBooleanArray }
+[1] 2 0 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) + c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean + to$listBoolean }
+[1] 2 0 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in -(to$fieldCharArray) : invalid argument to unary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldCharArray) }
+Error in -(to$fieldCharArray) : invalid argument to unary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in -(to$fieldStringArray) : invalid argument to unary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$fieldStringArray) }
+Error in -(to$fieldStringArray) : invalid argument to unary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in -(to$listChar) : invalid argument to unary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listChar) }
+Error in -(to$listChar) : invalid argument to unary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in -(to$listString) : invalid argument to unary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listString) }
+Error in -(to$listString) : invalid argument to unary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in -(to$listStringInt) : invalid argument to unary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));-(to$listStringInt) }
+Error in -(to$listStringInt) : invalid argument to unary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in 1 + to : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to }
+Error in 1 + to : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in 1 + to$fieldCharArray : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldCharArray }
+Error in 1 + to$fieldCharArray : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in 1 + to$fieldStringArray :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$fieldStringArray }
+Error in 1 + to$fieldStringArray :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in 1 + to$listChar : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listChar }
+Error in 1 + to$listChar : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in 1 + to$listString : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listString }
+Error in 1 + to$listString : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in 1 + to$listStringInt : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));1 + to$listStringInt }
+Error in 1 + to$listStringInt : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL + to$fieldCharArray :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldCharArray }
+Error in NULL + to$fieldCharArray :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL + to$fieldStringArray :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldStringArray }
+Error in NULL + to$fieldStringArray :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL + to$listChar : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listChar }
+Error in NULL + to$listChar : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL + to$listString : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listString }
+Error in NULL + to$listString : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL + to$listStringInt :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listStringInt }
+Error in NULL + to$listStringInt :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(1, 2, 3) + to$fieldCharArray :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldCharArray }
+Error in c(1, 2, 3) + to$fieldCharArray :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(1, 2, 3) + to$fieldStringArray :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$fieldStringArray }
+Error in c(1, 2, 3) + to$fieldStringArray :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(1, 2, 3) + to$listChar :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listChar }
+Error in c(1, 2, 3) + to$listChar :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(1, 2, 3) + to$listString :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listString }
+Error in c(1, 2, 3) + to$listString :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(1, 2, 3) + to$listStringInt :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(1, 2, 3) + to$listStringInt }
+Error in c(1, 2, 3) + to$listStringInt :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to + 1 : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to + 1 }
+Error in to + 1 : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to + to : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to + to }
+Error in to + to : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray + 1 : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray + 1 }
+Error in to$fieldCharArray + 1 : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray + NULL :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray + NULL }
+Error in to$fieldCharArray + NULL :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray + c(1, 2, 3) :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray + c(1, 2, 3) }
+Error in to$fieldCharArray + c(1, 2, 3) :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray + to$fieldCharArray :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray + to$fieldCharArray }
+Error in to$fieldCharArray + to$fieldCharArray :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray + 1 :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray + 1 }
+Error in to$fieldStringArray + 1 :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray + NULL :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray + NULL }
+Error in to$fieldStringArray + NULL :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray + c(1, 2, 3) :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray + c(1, 2, 3) }
+Error in to$fieldStringArray + c(1, 2, 3) :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray + to$fieldStringArray :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray + to$fieldStringArray }
+Error in to$fieldStringArray + to$fieldStringArray :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar + 1 : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar + 1 }
+Error in to$listChar + 1 : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar + NULL : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar + NULL }
+Error in to$listChar + NULL : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar + c(1, 2, 3) :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar + c(1, 2, 3) }
+Error in to$listChar + c(1, 2, 3) :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar + to$listChar :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar + to$listChar }
+Error in to$listChar + to$listChar :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString + 1 : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString + 1 }
+Error in to$listString + 1 : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString + NULL : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString + NULL }
+Error in to$listString + NULL : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString + c(1, 2, 3) :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString + c(1, 2, 3) }
+Error in to$listString + c(1, 2, 3) :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString + to$listString :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString + to$listString }
+Error in to$listString + to$listString :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt + 1 : non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt + 1 }
+Error in to$listStringInt + 1 : non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt + NULL :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt + NULL }
+Error in to$listStringInt + NULL :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt + c(1, 2, 3) :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt + c(1, 2, 3) }
+Error in to$listStringInt + c(1, 2, 3) :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt + to$listStringInt :', '<<<NEWLINE>>>', ' non-numeric argument to binary operator', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt + to$listStringInt }
+Error in to$listStringInt + to$listStringInt :
+  non-numeric argument to binary operator
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldBooleanArray }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldByteArray }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldDoubleArray }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldFloatArray }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldIntegerArray }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldLongArray }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$fieldShortArray }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listBoolean }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listByte }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listDouble }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listFloat }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listInteger }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listLong }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL + to$listShort }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorArithmeticOp#
+#if (!any(R.version$engine == "FastR")) { numeric(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort + NULL }
+numeric(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldByteArray) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldIntegerArray) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldLongArray) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldShortArray) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listByte) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listInteger) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listLong) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listShort) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldDoubleArray) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldFloatArray) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listDouble) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listFloat) }
+[1] FALSE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldBooleanArray) }
+[1] FALSE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { !c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listBoolean) }
+[1] FALSE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldByteArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldIntegerArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldLongArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldShortArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listByte }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listInteger }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listLong }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listShort }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldDoubleArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldFloatArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listDouble }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listFloat }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldBooleanArray }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T & c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listBoolean }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray & to$fieldByteArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray & to$fieldIntegerArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray & to$fieldLongArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray & to$fieldShortArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte & to$listByte }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger & to$listInteger }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong & to$listLong }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort & to$listShort }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat & T }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray & to$fieldDoubleArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray & to$fieldFloatArray }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble & to$listDouble }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat & to$listFloat }
+[1] TRUE TRUE TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat & c(T, T, F) }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldByteArray }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldIntegerArray }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldLongArray }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldShortArray }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listByte }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listInteger }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listLong }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listShort }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldDoubleArray }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldFloatArray }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listDouble }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listFloat }
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldBooleanArray }
+[1]  TRUE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) & c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listBoolean }
+[1]  TRUE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray & T }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) & T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean & T }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray & c(T, T, F) }
+[1]  TRUE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) & c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean & c(T, T, F) }
+[1]  TRUE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) & c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray & to$fieldBooleanArray }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) & c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean & to$listBoolean }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in !(to$fieldCharArray) : invalid argument type', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldCharArray) }
+Error in !(to$fieldCharArray) : invalid argument type
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in !(to$fieldStringArray) : invalid argument type', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$fieldStringArray) }
+Error in !(to$fieldStringArray) : invalid argument type
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in !(to$listChar) : invalid argument type', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listChar) }
+Error in !(to$listChar) : invalid argument type
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in !(to$listString) : invalid argument type', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listString) }
+Error in !(to$listString) : invalid argument type
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in !(to$listStringInt) : invalid argument type', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));!(to$listStringInt) }
+Error in !(to$listStringInt) : invalid argument type
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T & to :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to }
+Error in T & to :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T & to$fieldCharArray :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldCharArray }
+Error in T & to$fieldCharArray :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T & to$fieldStringArray :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$fieldStringArray }
+Error in T & to$fieldStringArray :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T & to$listChar :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listChar }
+Error in T & to$listChar :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T & to$listString :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listString }
+Error in T & to$listString :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T & to$listStringInt :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T & to$listStringInt }
+Error in T & to$listStringInt :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) & to$fieldCharArray :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldCharArray }
+Error in c(T, T, F) & to$fieldCharArray :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) & to$fieldStringArray :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$fieldStringArray }
+Error in c(T, T, F) & to$fieldStringArray :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) & to$listChar :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listChar }
+Error in c(T, T, F) & to$listChar :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) & to$listString :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listString }
+Error in c(T, T, F) & to$listString :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) & to$listStringInt :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) & to$listStringInt }
+Error in c(T, T, F) & to$listStringInt :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to & T :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to & T }
+Error in to & T :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to & to :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to & to }
+Error in to & to :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray & T :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray & T }
+Error in to$fieldCharArray & T :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray & c(T, T, F) :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray & c(T, T, F) }
+Error in to$fieldCharArray & c(T, T, F) :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray & to$fieldCharArray :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray & to$fieldCharArray }
+Error in to$fieldCharArray & to$fieldCharArray :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray & T :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray & T }
+Error in to$fieldStringArray & T :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray & c(T, T, F) :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray & c(T, T, F) }
+Error in to$fieldStringArray & c(T, T, F) :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray & to$fieldStringArray :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray & to$fieldStringArray }
+Error in to$fieldStringArray & to$fieldStringArray :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar & T :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar & T }
+Error in to$listChar & T :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar & c(T, T, F) :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar & c(T, T, F) }
+Error in to$listChar & c(T, T, F) :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar & to$listChar :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar & to$listChar }
+Error in to$listChar & to$listChar :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString & T :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString & T }
+Error in to$listString & T :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString & c(T, T, F) :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString & c(T, T, F) }
+Error in to$listString & c(T, T, F) :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString & to$listString :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString & to$listString }
+Error in to$listString & to$listString :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt & T :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt & T }
+Error in to$listStringInt & T :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt & c(T, T, F) :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt & c(T, T, F) }
+Error in to$listStringInt & c(T, T, F) :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt & to$listStringInt :', '<<<NEWLINE>>>', ' operations are possible only for numeric, logical or complex types', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt & to$listStringInt }
+Error in to$listStringInt & to$listStringInt :
+  operations are possible only for numeric, logical or complex types
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldBooleanArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldByteArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldCharArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldDoubleArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldFloatArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldIntegerArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldLongArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldShortArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$fieldStringArray }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listBoolean }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listByte }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listChar }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listDouble }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listFloat }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listInteger }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listLong }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listShort }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listString }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL & to$listStringInt }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorBooleanOp#
+#if (!any(R.version$engine == "FastR")) { logical(0) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt & NULL }
+logical(0)
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldByteArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldIntegerArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldLongArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldShortArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listByte }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listInteger }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listLong }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listShort }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldDoubleArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldFloatArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listDouble }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listFloat }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldBooleanArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T && c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c("1","2","3") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listStringInt }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldCharArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldStringArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listChar }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listString }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldByteArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldIntegerArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldLongArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldShortArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listByte }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listInteger }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listLong }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listShort }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldDoubleArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldFloatArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listDouble }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listFloat }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$fieldBooleanArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { T || c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to$listBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T || to }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort || NULL }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray && to$fieldByteArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray && to$fieldIntegerArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray && to$fieldLongArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray && to$fieldShortArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte && to$listByte }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger && to$listInteger }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong && to$listLong }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort && to$listShort }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray || to$fieldByteArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray || to$fieldIntegerArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray || to$fieldLongArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray || to$fieldShortArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte || to$listByte }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger || to$listInteger }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong || to$listLong }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort || to$listShort }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1,2,3)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray && to$fieldDoubleArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray && to$fieldFloatArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble && to$listDouble }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat && to$listFloat }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray || to$fieldDoubleArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray || to$fieldFloatArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble || to$listDouble }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1) || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat || to$listFloat }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(1.1,2.1,3.1)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldByteArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldIntegerArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldLongArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldShortArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listByte }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listInteger }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listLong }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listShort }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldDoubleArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldFloatArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listDouble }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listFloat }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldBooleanArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) && c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c("1","2","3") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listStringInt }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldCharArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldStringArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listChar }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c("a","b","c") } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listString }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldByteArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldIntegerArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldLongArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldShortArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listByte }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listInteger }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listLong }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1,2,3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listShort }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldDoubleArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldFloatArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listDouble }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(1.1,2.1,3.1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listFloat }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$fieldBooleanArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(T, T, F) || c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) || to$listBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) && c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray && to$fieldBooleanArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) && c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean && to$listBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) || c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray || to$fieldBooleanArray }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE) || c(TRUE,FALSE,TRUE) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean || to$listBoolean }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE)&& T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean && T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE)&& c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean && c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE)|| T } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean || T }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { c(TRUE,FALSE,TRUE)|| c(T, T, F) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean || c(T, T, F) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldBooleanArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldBooleanArray }
+Error in NULL && to$fieldBooleanArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldByteArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldByteArray }
+Error in NULL && to$fieldByteArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldCharArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldCharArray }
+Error in NULL && to$fieldCharArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldDoubleArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldDoubleArray }
+Error in NULL && to$fieldDoubleArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldFloatArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldFloatArray }
+Error in NULL && to$fieldFloatArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldIntegerArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldIntegerArray }
+Error in NULL && to$fieldIntegerArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldLongArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldLongArray }
+Error in NULL && to$fieldLongArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldShortArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldShortArray }
+Error in NULL && to$fieldShortArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$fieldStringArray : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$fieldStringArray }
+Error in NULL && to$fieldStringArray : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listBoolean : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listBoolean }
+Error in NULL && to$listBoolean : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listByte : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listByte }
+Error in NULL && to$listByte : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listChar : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listChar }
+Error in NULL && to$listChar : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listDouble : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listDouble }
+Error in NULL && to$listDouble : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listFloat : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listFloat }
+Error in NULL && to$listFloat : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listInteger : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listInteger }
+Error in NULL && to$listInteger : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listLong : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listLong }
+Error in NULL && to$listLong : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listShort : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listShort }
+Error in NULL && to$listShort : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listString : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listString }
+Error in NULL && to$listString : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL && to$listStringInt : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL && to$listStringInt }
+Error in NULL && to$listStringInt : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldBooleanArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldBooleanArray }
+Error in NULL || to$fieldBooleanArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldByteArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldByteArray }
+Error in NULL || to$fieldByteArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldCharArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldCharArray }
+Error in NULL || to$fieldCharArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldDoubleArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldDoubleArray }
+Error in NULL || to$fieldDoubleArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldFloatArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldFloatArray }
+Error in NULL || to$fieldFloatArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldIntegerArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldIntegerArray }
+Error in NULL || to$fieldIntegerArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldLongArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldLongArray }
+Error in NULL || to$fieldLongArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldShortArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldShortArray }
+Error in NULL || to$fieldShortArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$fieldStringArray : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$fieldStringArray }
+Error in NULL || to$fieldStringArray : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listBoolean : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listBoolean }
+Error in NULL || to$listBoolean : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listByte : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listByte }
+Error in NULL || to$listByte : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listChar : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listChar }
+Error in NULL || to$listChar : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listDouble : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listDouble }
+Error in NULL || to$listDouble : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listFloat : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listFloat }
+Error in NULL || to$listFloat : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listInteger : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listInteger }
+Error in NULL || to$listInteger : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listLong : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listLong }
+Error in NULL || to$listLong : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listShort : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listShort }
+Error in NULL || to$listShort : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listString : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listString }
+Error in NULL || to$listString : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in NULL || to$listStringInt : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));NULL || to$listStringInt }
+Error in NULL || to$listStringInt : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T && to : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to }
+Error in T && to : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T && to$fieldCharArray : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldCharArray }
+Error in T && to$fieldCharArray : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T && to$fieldStringArray : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$fieldStringArray }
+Error in T && to$fieldStringArray : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T && to$listChar : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listChar }
+Error in T && to$listChar : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T && to$listString : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listString }
+Error in T && to$listString : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in T && to$listStringInt : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));T && to$listStringInt }
+Error in T && to$listStringInt : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) && to$fieldCharArray : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldCharArray }
+Error in c(T, T, F) && to$fieldCharArray : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) && to$fieldStringArray : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$fieldStringArray }
+Error in c(T, T, F) && to$fieldStringArray : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) && to$listChar : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listChar }
+Error in c(T, T, F) && to$listChar : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) && to$listString : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listString }
+Error in c(T, T, F) && to$listString : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in c(T, T, F) && to$listStringInt : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); c(T, T, F) && to$listStringInt }
+Error in c(T, T, F) && to$listStringInt : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to && T : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to && T }
+Error in to && T : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to && to : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to && to }
+Error in to && to : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to || T : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to || T }
+Error in to || T : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to || to : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to || to }
+Error in to || to : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldBooleanArray && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldBooleanArray && NULL }
+Error in to$fieldBooleanArray && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldByteArray && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldByteArray && NULL }
+Error in to$fieldByteArray && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray && NULL : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray && NULL }
+Error in to$fieldCharArray && NULL : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray && T : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray && T }
+Error in to$fieldCharArray && T : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray && c(T, T, F) : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray && c(T, T, F) }
+Error in to$fieldCharArray && c(T, T, F) : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray && to$fieldCharArray :', '<<<NEWLINE>>>', ' invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray && to$fieldCharArray }
+Error in to$fieldCharArray && to$fieldCharArray :
+  invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray || NULL : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray || NULL }
+Error in to$fieldCharArray || NULL : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray || T : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray || T }
+Error in to$fieldCharArray || T : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray || c(T, T, F) : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray || c(T, T, F) }
+Error in to$fieldCharArray || c(T, T, F) : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldCharArray || to$fieldCharArray :', '<<<NEWLINE>>>', ' invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldCharArray || to$fieldCharArray }
+Error in to$fieldCharArray || to$fieldCharArray :
+  invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldDoubleArray && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldDoubleArray && NULL }
+Error in to$fieldDoubleArray && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldFloatArray && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldFloatArray && NULL }
+Error in to$fieldFloatArray && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldIntegerArray && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldIntegerArray && NULL }
+Error in to$fieldIntegerArray && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldLongArray && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldLongArray && NULL }
+Error in to$fieldLongArray && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldShortArray && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldShortArray && NULL }
+Error in to$fieldShortArray && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray && NULL : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray && NULL }
+Error in to$fieldStringArray && NULL : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray && T : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray && T }
+Error in to$fieldStringArray && T : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray && c(T, T, F) : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray && c(T, T, F) }
+Error in to$fieldStringArray && c(T, T, F) : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray && to$fieldStringArray :', '<<<NEWLINE>>>', ' invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray && to$fieldStringArray }
+Error in to$fieldStringArray && to$fieldStringArray :
+  invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray || NULL : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray || NULL }
+Error in to$fieldStringArray || NULL : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray || T : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray || T }
+Error in to$fieldStringArray || T : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray || c(T, T, F) : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray || c(T, T, F) }
+Error in to$fieldStringArray || c(T, T, F) : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$fieldStringArray || to$fieldStringArray :', '<<<NEWLINE>>>', ' invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$fieldStringArray || to$fieldStringArray }
+Error in to$fieldStringArray || to$fieldStringArray :
+  invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listBoolean && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listBoolean && NULL }
+Error in to$listBoolean && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listByte && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listByte && NULL }
+Error in to$listByte && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar && NULL : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar && NULL }
+Error in to$listChar && NULL : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar && T : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar && T }
+Error in to$listChar && T : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar && c(T, T, F) : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar && c(T, T, F) }
+Error in to$listChar && c(T, T, F) : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar && to$listChar : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar && to$listChar }
+Error in to$listChar && to$listChar : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar || NULL : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar || NULL }
+Error in to$listChar || NULL : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar || T : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar || T }
+Error in to$listChar || T : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar || c(T, T, F) : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar || c(T, T, F) }
+Error in to$listChar || c(T, T, F) : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listChar || to$listChar : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listChar || to$listChar }
+Error in to$listChar || to$listChar : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listDouble && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listDouble && NULL }
+Error in to$listDouble && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listFloat && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listFloat && NULL }
+Error in to$listFloat && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listInteger && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listInteger && NULL }
+Error in to$listInteger && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listLong && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listLong && NULL }
+Error in to$listLong && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listShort && NULL : invalid \'y\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listShort && NULL }
+Error in to$listShort && NULL : invalid 'y' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString && NULL : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString && NULL }
+Error in to$listString && NULL : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString && T : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString && T }
+Error in to$listString && T : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString && c(T, T, F) : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString && c(T, T, F) }
+Error in to$listString && c(T, T, F) : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString && to$listString : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString && to$listString }
+Error in to$listString && to$listString : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString || NULL : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString || NULL }
+Error in to$listString || NULL : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString || T : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString || T }
+Error in to$listString || T : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString || c(T, T, F) : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString || c(T, T, F) }
+Error in to$listString || c(T, T, F) : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listString || to$listString : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listString || to$listString }
+Error in to$listString || to$listString : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt && NULL : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt && NULL }
+Error in to$listStringInt && NULL : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt && T : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt && T }
+Error in to$listStringInt && T : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt && c(T, T, F) : invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt && c(T, T, F) }
+Error in to$listStringInt && c(T, T, F) : invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt && to$listStringInt :', '<<<NEWLINE>>>', ' invalid \'x\' type in \'x && y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt && to$listStringInt }
+Error in to$listStringInt && to$listStringInt :
+  invalid 'x' type in 'x && y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt || NULL : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt || NULL }
+Error in to$listStringInt || NULL : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt || T : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt || T }
+Error in to$listStringInt || T : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt || c(T, T, F) : invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt || c(T, T, F) }
+Error in to$listStringInt || c(T, T, F) : invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testForeignVectorScalarBooleanOp#
+#if (!any(R.version$engine == "FastR")) { cat('Error in to$listStringInt || to$listStringInt :', '<<<NEWLINE>>>', ' invalid \'x\' type in \'x || y\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));to$listStringInt || to$listStringInt }
+Error in to$listStringInt || to$listStringInt :
+  invalid 'x' type in 'x || y'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "character" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticCharArray); typeof(v) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "character" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticStringArray); typeof(v) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "double" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticDoubleArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "double" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticFloatArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "double" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticLongArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "double" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectDoubleArray); typeof(v) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "integer" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticByteArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "integer" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticIntegerArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "integer" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticShortArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "integer" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectIntArray); typeof(v) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { "logical" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticBooleanArray); typeof(v) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.interop.fromArray(to$hasNullIntArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.interop.fromArray(to$mixedTypesArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.interop.fromArray(to$objectArray); is.list(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticBooleanArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticByteArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticCharArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticDoubleArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticFloatArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticIntegerArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticLongArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticShortArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$fieldStaticStringArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectDoubleArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- as.vector(to$objectIntArray); is.vector(v) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { list() } else { ja <- new.java.array('java.lang.String', 0L); .fastr.interop.fromArray(ja) }
+list()
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { list(1) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.interop.fromArray(to$hasNullIntArray); v[1] }
+[[1]]
+[1] 1
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { list(3) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.interop.fromArray(to$hasNullIntArray); v[3] }
+[[1]]
+[1] 3
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
+#if (!any(R.version$engine == "FastR")) { list(NULL) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.interop.fromArray(to$hasNullIntArray); v[2] }
+[[1]]
+NULL
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testGetClass#
+#if (!any(R.version$engine == "FastR")) { 'com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass' } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));java.class(to) }
+[1] "com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testGetClass#
+#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(1) : unsupported type', '<<<NEWLINE>>>') } else { java.class(1) }
+Error in java.class(1) : unsupported type
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testGetClass#
+#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(NULL) : unsupported type', '<<<NEWLINE>>>') } else { java.class(NULL) }
+Error in java.class(NULL) : unsupported type
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testGetClass#
+#if (!any(R.version$engine == "FastR")) { cat('Error in java.class(to$methodReturnsNull()) : unsupported type', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));java.class(to$methodReturnsNull()) }
+Error in java.class(to$methodReturnsNull()) : unsupported type
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIdentical#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { b1 <- as.external.byte(1); b2 <- as.external.byte(1); identical(b1, b2) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIdentical#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { b1 <- as.external.byte(1); s1 <- as.external.short(1); identical(b1, s1) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIdentical#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { ll <- new.external(new.java.class('java.util.LinkedList')); al <- new.external(new.java.class('java.util.ArrayList')); identical(al, ll) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIdentical#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { al <- new.external(new.java.class('java.util.ArrayList')); identical(t, t) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIdentical#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { b1 <- as.external.byte(1); identical(b1, b1) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { cat('Error in if (T) print(\'OK\') :  argument is not interpretable as logical', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to) print('OK') }
+Error in if (T) print('OK') :  argument is not interpretable as logical
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#
+#if (!any(R.version$engine == "FastR")) { if(1) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$fieldInteger) print('OK') }
+[1] "OK"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#
+#if (!any(R.version$engine == "FastR")) { if(T) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$fieldBoolean) print('OK') }
+[1] "OK"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { if(c("TRUE","TRUE","FALSE")) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$listStringBoolean) print('OK') }
+[1] "OK"
+Warning message:
+In if (c("TRUE", "TRUE", "FALSE")) print("OK") :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { if(c('A', 'B')) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$listString) print('OK') }
+Error in if (c("A", "B")) print("OK") :
+  argument is not interpretable as logical
+In addition: Warning message:
+In if (c("A", "B")) print("OK") :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { if(c('TRUE', 'TRUE', 'FALSE')) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$fieldStringBooleanArray) print('OK') }
+[1] "OK"
+Warning message:
+In if (c("TRUE", "TRUE", "FALSE")) print("OK") :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreWarningContext#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { if(c('a', 'b')) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$fieldStringArray) print('OK') }
+Error in if (c("a", "b")) print("OK") :
+  argument is not interpretable as logical
+In addition: Warning message:
+In if (c("a", "b")) print("OK") :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { if(c(T, F)) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$fieldBooleanArray) print('OK') }
+[1] "OK"
+Warning message:
+In if (c(T, F)) print("OK") :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { if(c(T, F)) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$fieldIntegerArray) print('OK') }
+[1] "OK"
+Warning message:
+In if (c(T, F)) print("OK") :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { if(c(T, F)) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$listBoolean) print('OK') }
+[1] "OK"
+Warning message:
+In if (c(T, F)) print("OK") :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIf#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { if(c(T, F)) print('OK') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$listInteger) print('OK') }
+[1] "OK"
+Warning message:
+In if (c(T, F)) print("OK") :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 'a' } else { tc <- new.java.class('java.lang.Character'); t <- new.external(tc, as.external.char(97)); t }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 'abc' } else { tc <- new.java.class('java.lang.String'); t <- new.external(tc, 'abc'); t }
+[1] "abc"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 'truffle.object' } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNullClass'); t <- new.external(tc, NULL); class(t) }
+[1] "truffle.object"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 1 } else { tc <- new.java.class('java.lang.Byte'); t <- new.external(tc, as.external.byte(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 1 } else { tc <- new.java.class('java.lang.Integer'); t <- new.external(tc, 1L); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 1 } else { tc <- new.java.class('java.lang.Long'); t <- new.external(tc, as.external.long(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 1 } else { tc <- new.java.class('java.lang.Short'); t <- new.external(tc, as.external.short(1)); t }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { tc <- new.java.class('java.lang.Double'); t <- new.external(tc, 1.1); t }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { tc <- new.java.class('java.lang.Float'); t <- new.external(tc, as.external.float(1.1)); t }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { tc <- new.java.class('java.lang.Boolean'); t <- new.external(tc, TRUE); t }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { tc <- new.java.class('java/lang/Boolean'); t <- new(tc, TRUE); t }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalExecutable#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.executable(to$fieldBoolean) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalExecutable#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.executable(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalExecutable#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.executable(to$methodBoolean) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalNull#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.null(to$methodReturnsNull) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalNull#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.null(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsExternalNull#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));is.external.null(to$methodReturnsNull()) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.array(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.atomic(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.call(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.character(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.complex(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.data.frame(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.double(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.environment(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.expression(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.factor(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.function(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.integer(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.language(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.logical(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.matrix(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.mts(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.na(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.name(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.null(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric.Date(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric.POSIXt(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric.difftime(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric_version(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.object(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.ordered(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.package_version(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.pairlist(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.primitive(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.qr(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.raster(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.raw(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.recursive(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.relistable(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.stepfun(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.symbol(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.table(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.ts(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.tskernel(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.unsorted(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { FALSE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.vector(to) }
+[1] FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { cat('Error in is.finite(to) :', '<<<NEWLINE>>>', ' default method not implemented for type \'external object\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.finite(to) }
+Error in is.finite(to) :
+  default method not implemented for type 'external object'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { cat('Error in is.infinite(to) :', '<<<NEWLINE>>>', ' default method not implemented for type \'external object\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.infinite(to) }
+Error in is.infinite(to) :
+  default method not implemented for type 'external object'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
+#if (!any(R.version$engine == "FastR")) { cat('Error in is.nan(to) :', '<<<NEWLINE>>>', ' default method not implemented for type \'external object\'', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.nan(to) }
+Error in is.nan(to) :
+  default method not implemented for type 'external object'
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthArray#
+#if (!any(R.version$engine == "FastR")) { 0 } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); length(ta$objectEmpty) }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthArray#
+#if (!any(R.version$engine == "FastR")) { 2 } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); length(ta$booleanArray2) }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthArray#
+#if (!any(R.version$engine == "FastR")) { 2 } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); length(ta$booleanArray3) }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthArray#
+#if (!any(R.version$engine == "FastR")) { 3 } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); length(ta$booleanArray) }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthIterable#
+#if (!any(R.version$engine == "FastR")) { 123 } else { ti <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestIterableGetLength', 123); length(ti) }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthIterable#
+#if (!any(R.version$engine == "FastR")) { 123 } else { ti <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestIterableGetSize', 123); length(ti) }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthIterable#
+#if (!any(R.version$engine == "FastR")) { 123 } else { ti <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestIterableLength', 123); length(ti) }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthIterable#
+#if (!any(R.version$engine == "FastR")) { 123 } else { ti <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestIterableNoSizeMethod', 123); length(ti) }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testLengthIterable#
+#if (!any(R.version$engine == "FastR")) { 123 } else { ti <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestIterableSize', 123); length(ti) }
+[1] 123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { "a string" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticStringObject() }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { "a string" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStringObject() }
+[1] "a string"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { "a" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodChar() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { "a" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodCharObject() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { "a" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticChar() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { "a" } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticCharObject() }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodFloat() }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodFloatObject() }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticFloat() }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticFloatObject() }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 1.7976931348623157E308 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodDouble() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 1.7976931348623157E308 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodDoubleObject() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 1.7976931348623157E308 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticDouble() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 1.7976931348623157E308 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticDoubleObject() }
+[1] 1.797693e+308
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 127 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodByte() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 127 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodByteObject() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 127 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticByte() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 127 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticByteObject() }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodInteger() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodIntegerObject() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticInteger() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticIntegerObject() }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 32767 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodShort() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 32767 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodShortObject() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 32767 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticShort() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 32767 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticShortObject() }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodLong() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodLongObject() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticLong() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticLongObject() }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { NULL } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodReturnsNull() }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { NULL } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticReturnsNull() }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodBoolean() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodBooleanObject() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticBoolean() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticBooleanObject() }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b" "c"\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticStringArray() }
+[external object]
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b" "c"\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStringArray() }
+[external object]
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodIntArray() }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2 3\n') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodStaticIntArray() }
+[external object]
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#Ignored.Unstable#
+#if (!any(R.version$engine == "FastR")) { NULL } else { cl <- new.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
+#if (!any(R.version$engine == "FastR")) { NULL } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); names(tc$staticField) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
+#if (!any(R.version$engine == "FastR")) { NULL } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); names(tc$staticMethod) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
+#if (!any(R.version$engine == "FastR")) { NULL } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassNoMembers'); t <- new.external(tc); names(t) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
+#if (!any(R.version$engine == "FastR")) { NULL } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassNoPublicMembers'); t <- new.external(tc); names(t) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
+#if (!any(R.version$engine == "FastR")) { c('field', 'method', 'staticField', 'staticMethod') } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); t <- new.external(tc); sort(names(t)) }
+[1] "field"        "method"       "staticField"  "staticMethod"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#Ignored.Unstable#
+#if (!any(R.version$engine == "FastR")) { c('one', 'two') } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassMap'); to <- new.external(tc); sort(names(to$m())) }
+[1] "one" "two"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
+#if (!any(R.version$engine == "FastR")) { c('staticField', 'staticMethod') } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); sort(names(tc)) }
+[1] "staticField"  "staticMethod"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[B' } else { a <- new.java.array('byte', 10L); java.class(a); }
+[1] "[B"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[C' } else { a <- new.java.array('char', 10L); java.class(a); }
+[1] "[C"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[D' } else { a <- new.java.array('double', 10L); java.class(a); }
+[1] "[D"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[F' } else { a <- new.java.array('float', 10L); java.class(a); }
+[1] "[F"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[I' } else { a <- new.java.array('int', 10L); java.class(a); }
+[1] "[I"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[J' } else { a <- new.java.array('long', 10L); java.class(a); }
+[1] "[J"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Lcom.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass;' } else { a <- new.java.array('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass', 10L); java.class(a); }
+[1] "[Lcom.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Boolean;' } else { a <- new.java.array('java.lang.Boolean', 10L); java.class(a); }
+[1] "[Ljava.lang.Boolean;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Byte;' } else { a <- new.java.array('java.lang.Byte', 10L); java.class(a); }
+[1] "[Ljava.lang.Byte;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Character;' } else { a <- new.java.array('java.lang.Character', 10L); java.class(a); }
+[1] "[Ljava.lang.Character;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Double;' } else { a <- new.java.array('java.lang.Double', 10L); java.class(a); }
+[1] "[Ljava.lang.Double;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Float;' } else { a <- new.java.array('java.lang.Float', 10L); java.class(a); }
+[1] "[Ljava.lang.Float;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Integer;' } else { a <- new.java.array('java.lang.Integer', 10L); java.class(a); }
+[1] "[Ljava.lang.Integer;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Long;' } else { a <- new.java.array('java.lang.Long', 10L); java.class(a); }
+[1] "[Ljava.lang.Long;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.Short;' } else { a <- new.java.array('java.lang.Short', 10L); java.class(a); }
+[1] "[Ljava.lang.Short;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.String;' } else { a <- new.java.array('java.lang.String', 10.9); java.class(a); }
+[1] "[Ljava.lang.String;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.String;' } else { a <- new.java.array('java.lang.String', 10L); java.class(a); }
+[1] "[Ljava.lang.String;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[S' } else { a <- new.java.array('short', 10L); java.class(a); }
+[1] "[S"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[Z' } else { a <- new.java.array('boolean', 10L); java.class(a); }
+[1] "[Z"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[B' } else { a <- new.java.array('byte', c(2L, 3L)); java.class(a); }
+[1] "[[B"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[C' } else { a <- new.java.array('char', c(2L, 3L)); java.class(a); }
+[1] "[[C"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[D' } else { a <- new.java.array('double', c(2L, 3L)); java.class(a); }
+[1] "[[D"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[F' } else { a <- new.java.array('float', c(2L, 3L)); java.class(a); }
+[1] "[[F"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[I' } else { a <- new.java.array('int', c(2L, 3L)); java.class(a); }
+[1] "[[I"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[J' } else { a <- new.java.array('long', c(2L, 3L)); java.class(a); }
+[1] "[[J"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Lcom.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass;' } else { a <- new.java.array('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass', c(2L, 3L)); java.class(a); }
+[1] "[[Lcom.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.Boolean;' } else { a <- new.java.array('java.lang.Boolean', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.Boolean;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.Byte;' } else { a <- new.java.array('java.lang.Byte', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.Byte;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.Character;' } else { a <- new.java.array('java.lang.Character', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.Character;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.Double;' } else { a <- new.java.array('java.lang.Double', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.Double;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.Float;' } else { a <- new.java.array('java.lang.Float', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.Float;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.Integer;' } else { a <- new.java.array('java.lang.Integer', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.Integer;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.Long;' } else { a <- new.java.array('java.lang.Long', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.Long;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.Short;' } else { a <- new.java.array('java.lang.Short', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.Short;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.String;' } else { a <- new.java.array('java.lang.String', c(2.9, 3.9)); java.class(a); }
+[1] "[[Ljava.lang.String;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Ljava.lang.String;' } else { a <- new.java.array('java.lang.String', c(2L, 3L)); java.class(a); }
+[1] "[[Ljava.lang.String;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[S' } else { a <- new.java.array('short', c(2L, 3L)); java.class(a); }
+[1] "[[S"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { '[[Z' } else { a <- new.java.array('boolean', c(2L, 3L)); java.class(a); }
+[1] "[[Z"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('boolean', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('byte', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('char', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('double', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('float', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('int', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.Boolean', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.Byte', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.Character', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.Double', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.Float', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.Integer', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.Long', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.Short', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.String', 10.9); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('java.lang.String', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('long', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 10 } else { a <- new.java.array('short', 10L); length(a); }
+[1] 10
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('boolean', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('byte', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('char', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('double', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('float', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('int', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.Boolean', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.Byte', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.Character', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.Double', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.Float', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.Integer', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.Long', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.Short', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.String', c(2.9, 3.9)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('java.lang.String', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('long', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 2L } else { a <- new.java.array('short', c(2L, 3L)); length(a); }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('boolean', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('byte', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('char', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('double', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('float', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('int', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.Boolean', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.Byte', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.Character', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.Double', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.Float', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.Integer', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.Long', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.Short', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.String', c(2.9, 3.9)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('java.lang.String', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('long', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { 3L } else { a <- new.java.array('short', c(2L, 3L)); length(a[1]); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('boolean', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('boolean', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('byte', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('byte', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('char', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('char', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('double', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('double', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('float', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('float', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('int', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('int', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Boolean', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Boolean', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Byte', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Byte', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Character', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Character', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Double', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Double', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Float', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Float', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Integer', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Integer', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Long', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Long', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Short', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.Short', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.String', 10.9); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.String', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.String', c(2.9, 3.9)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('java.lang.String', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('long', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('long', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('short', 10L); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { a <- new.java.array('short', c(2L, 3L)); is.external.array(a); }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- new(tc); to$fieldInteger }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { to <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to$fieldStaticInteger }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { tc <- new.java.class('java.lang.Boolean'); to <- new(tc, TRUE); to }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new('java.lang.Boolean', TRUE); to }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new('java/lang/Boolean', TRUE); to }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
+#if (!any(R.version$engine == "FastR")) { cat('Error in getClass(Class, where = topenv(parent.frame())) :', '<<<NEWLINE>>>', ' “__bogus_class_name__” is not a defined class', '<<<NEWLINE>>>') } else { to <- new('__bogus_class_name__'); }
+Error in getClass(Class, where = topenv(parent.frame())) :
+  “__bogus_class_name__” is not a defined class
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
+#if (!any(R.version$engine == "FastR")) { cat('Error in new.external(Class, ...) :', '<<<NEWLINE>>>', ' error during Java object instantiation', '<<<NEWLINE>>>') } else { to <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); new(to) }
+Error in new.external(Class, ...) :
+  error during Java object instantiation
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNonPrimitiveParameter#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$equals(to) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#
+#if (!any(R.version$engine == "FastR")) {  } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$methodAcceptsOnlyNull(NULL) }
+NULL
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented#
+#if (!any(R.version$engine == "FastR")) { java.lang.Long } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$isNull(1) }
+Error: object 'java.lang.Long' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented#
+#if (!any(R.version$engine == "FastR")) { java.lang.String } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$isNull('string') }
+Error: object 'java.lang.String' not found
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { "java.lang.String" } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', 'string')$type }
+[1] "java.lang.String"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { "java.lang.String" } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded('string') }
+[1] "java.lang.String"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'boolean' } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', TRUE)$type }
+[1] "boolean"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'boolean' } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded(TRUE) }
+[1] "boolean"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'byte' } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', as.external.byte(1))$type }
+[1] "byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'byte' } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded(as.external.byte(1)) }
+[1] "byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'char' } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', as.external.char('a'))$type }
+[1] "char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'char' } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded(as.external.char('a')) }
+[1] "char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'double' } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', 1)$type }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'double' } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded(1) }
+[1] "double"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'float' } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', as.external.float(1))$type }
+[1] "float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'float' } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded(as.external.float(1)) }
+[1] "float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'int' } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', 1L)$type }
+[1] "int"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'int' } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded(1L) }
+[1] "int"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'long' } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', as.external.long(1))$type }
+[1] "long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'long' } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded(as.external.long(1)) }
+[1] "long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'short' } else { new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload', as.external.short(1))$type }
+[1] "short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#
+#if (!any(R.version$engine == "FastR")) { 'short' } else { toc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestOverload');  toc$isOverloaded(as.external.short(1)) }
+[1] "short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testReadByVector#
+#if (!any(R.version$engine == "FastR")) { c('1', '3') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$map[c('one', 'three')] }
+[1] "1" "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testReadByVector#
+#if (!any(R.version$engine == "FastR")) { c('a string', 'a') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to[c('fieldStringObject', 'fieldChar')] }
+[1] "a string" "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testReadByVector#
+#if (!any(R.version$engine == "FastR")) { c('a', 'c') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to$fieldStringArray[c(1, 3)] }
+[1] "a" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testReadByVector#
+#if (!any(R.version$engine == "FastR")) { list('a string', 2147483647) } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); to[c('fieldStringObject', 'fieldInteger')] }
+[[1]]
+[1] "a string"
+
+[[2]]
+[1] 2147483647
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { '[B' } else { a <- as.java.array(as.raw(1)); java.class(a); }
+[1] "[B"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { '[B' } else { a <- as.java.array(as.raw(c(1, 2, 3))); java.class(a); }
+[1] "[B"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { '[D' } else { a <- as.java.array(1.1); java.class(a); }
+[1] "[D"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { '[I' } else { a <- as.java.array(1L); java.class(a); }
+[1] "[I"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { '[I' } else { a <- as.java.array(as.raw(c(1, 2, 3)), 'int'); java.class(a); }
+[1] "[I"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { '[Ljava.lang.String;' } else { a <- as.java.array('a'); java.class(a); }
+[1] "[Ljava.lang.String;"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { '[S' } else { a <- as.java.array(as.external.short(1)); java.class(a); }
+[1] "[S"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { '[Z' } else { a <- as.java.array(T); java.class(a); }
+[1] "[Z"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { 1 } else { a <- as.java.array(as.raw(1)); length(a); }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { 2 } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- new.external(tc); a <- as.java.array(c(to, to)); length(a) }
+[1] 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { 3 } else { a <- as.java.array(as.raw(c(1, 2, 3))); length(a); }
+[1] 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- new.external(tc); a <- as.java.array(c(to, to)); is.external.array(a) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- new.external(tc); a <- as.java.array(to); is.external.array(a) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { [Lcom.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass; } else { tc <- new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- new.external(tc); a <- as.java.array(c(to, to)); java.class(a); }
+Error: unexpected '[' in "if (!any(R.version$engine == "FastR")) { ["
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1]  TRUE FALSE\n') } else { a <- as.java.array(c(T, F)); a; }
+[external object]
+[1]  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1]  TRUE FALSE\n') } else { a <- as.java.array(c(T, F),'boolean',T); a; }
+[external object]
+[1]  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1]  TRUE FALSE\n') } else { a <- as.java.array(c(T, F),,T); a; }
+[external object]
+[1]  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b"\n') } else { a <- as.java.array(c('a', 'b')); a; }
+[external object]
+[1] "a" "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b"\n') } else { a <- as.java.array(c('a', 'b'),'java.lang.String',T); a; }
+[external object]
+[1] "a" "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a" "b"\n') } else { a <- as.java.array(c('a', 'b'),,T); a; }
+[external object]
+[1] "a" "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a"\n') } else { a <- as.java.array('a'); a; }
+[external object]
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] "a"\n') } else { a <- as.java.array('a',,T); a; }
+[external object]
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(1L, 2L)); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(1L, 2L),'double',T); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(1L, 2L),,T); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(as.external.short(1), as.external.short(2))); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(as.external.short(1), as.external.short(2)), 'int'); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(as.external.short(1), as.external.short(2)), 'java.lang.Short'); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(as.external.short(1), as.external.short(2)), 'java.lang.Short', T); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(as.external.short(1), as.external.short(2)),'int',T); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1 2\n') } else { a <- as.java.array(c(as.external.short(1), as.external.short(2)),,T); a; }
+[external object]
+[1] 1 2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1 1.2\n') } else { a <- as.java.array(c(1.1, 1.2)); a; }
+[external object]
+[1] 1.1 1.2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1 1.2\n') } else { a <- as.java.array(c(1.1, 1.2),'double',T); a; }
+[external object]
+[1] 1.1 1.2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1 1.2\n') } else { a <- as.java.array(c(1.1, 1.2),,T); a; }
+[external object]
+[1] 1.1 1.2
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.123 2.123\n') } else { a <- as.java.array(c(1.123, 2.123), 'double'); a; }
+[external object]
+[1] 1.123 2.123
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1\n') } else { a <- as.java.array(1.1); a; }
+[external object]
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1.1\n') } else { a <- as.java.array(1.1,,T); a; }
+[external object]
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(1L); a; }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(1L); as.java.array(a); }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(1L); as.java.array(a,,T); }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(1L,,F); a; }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(1L,,T); a; }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(as.external.short(1)); a; }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(as.external.short(1)); as.java.array(a); }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(as.external.short(1), 'double'); a; }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(as.external.short(1), 'java.lang.Short'); a; }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(as.external.short(1), 'java.lang.Short', T); a; }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(as.external.short(1),,T); a; }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] 1\n') } else { a <- as.java.array(as.raw(1)); a }
+[external object]
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] TRUE\n') } else { a <- as.java.array(T); a; }
+[external object]
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
+#if (!any(R.version$engine == "FastR")) { cat('[external object]\n[1] TRUE\n') } else { a <- as.java.array(T,,T); a; }
+[external object]
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { 'interopt.byte' } else { v <- as.external.byte(1.1); class(v); }
+[1] "interopt.byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { 'interopt.byte' } else { v <- as.external.byte(1.1); typeof(v); }
+[1] "interopt.byte"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { -1 } else { v <- as.external.byte(1.7976931348623157E308); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { -1 } else { v <- as.external.byte(2147483647); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { -128 } else { v <- as.external.byte(-128); v; }
+[1] -128
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { 0 } else { v <- as.external.byte(-2147483648); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { 0 } else { v <- as.external.byte(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.byte(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.byte(1L); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.byte(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
+#if (!any(R.version$engine == "FastR")) { 127 } else { v <- as.external.byte(127); v; }
+[1] 127
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'a' } else { v <- as.external.char('a'); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'a' } else { v <- as.external.char(97.1); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'a' } else { v <- as.external.char(97L); v; }
+[1] "a"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'b' } else { v <- as.external.char('abc', 1); v; }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'b' } else { v <- as.external.char('abc', 1.1); v; }
+[1] "b"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'interopt.char' } else { v <- as.external.char(97.1); class(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'interopt.char' } else { v <- as.external.char(97.1); typeof(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'interopt.char' } else { v <- as.external.char(97L); class(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { 'interopt.char' } else { v <- as.external.char(97L); typeof(v); }
+[1] "interopt.char"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.external.char(97.1, 1) :', '<<<NEWLINE>>>', ' pos argument not allowed with a numeric value', '<<<NEWLINE>>>') } else { v <- as.external.char(97.1, 1); v; }
+Error in as.external.char(97.1, 1) :
+  pos argument not allowed with a numeric value
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
+#if (!any(R.version$engine == "FastR")) { cat('Error in as.external.char(97L, 1) :', '<<<NEWLINE>>>', ' pos argument not allowed with a numeric value', '<<<NEWLINE>>>') } else { v <- as.external.char(97L, 1); v; }
+Error in as.external.char(97L, 1) :
+  pos argument not allowed with a numeric value
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 'interopt.float' } else { v <- as.external.float(1.1); class(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 'interopt.float' } else { v <- as.external.float(1.1); typeof(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 'interopt.float' } else { v <- as.external.float(1L); class(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 'interopt.float' } else { v <- as.external.float(1L); typeof(v); }
+[1] "interopt.float"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 0.0 } else { v <- as.external.float(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.float(1L); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.float(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 1.1 } else { v <- as.external.float(1.1); v; }
+[1] 1.1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 1.401298464324817E-45 } else { v <- as.external.float(1.4E-45); v; }
+[1] 1.401298e-45
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { 3.4028235E38 } else { v <- as.external.float(3.4028235E38); v; }
+[1] 3.402823e+38
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
+#if (!any(R.version$engine == "FastR")) { Inf } else { v <- as.external.float(1.7976931348623157E308); v; }
+[1] Inf
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 'interopt.long' } else { v <- as.external.long(1.1); class(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 'interopt.long' } else { v <- as.external.long(1.1); typeof(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 'interopt.long' } else { v <- as.external.long(1L); class(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 'interopt.long' } else { v <- as.external.long(1L); typeof(v); }
+[1] "interopt.long"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { -2147483648 } else { v <- as.external.long(-2147483648); v; }
+[1] -2147483648
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 0 } else { v <- as.external.long(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.long(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.long(1L); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.long(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 2147483647 } else { v <- as.external.long(2147483647); v; }
+[1] 2147483647
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
+#if (!any(R.version$engine == "FastR")) { 9223372036854775807 } else { v <- as.external.long(1.7976931348623157E308); v; }
+[1] 9.223372e+18
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 'interopt.short' } else { v <- as.external.short(1.1); class(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 'interopt.short' } else { v <- as.external.short(1.1); typeof(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 'interopt.short' } else { v <- as.external.short(1L); class(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 'interopt.short' } else { v <- as.external.short(1L); typeof(v); }
+[1] "interopt.short"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { -1 } else { v <- as.external.short(1.7976931348623157E308); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { -1 } else { v <- as.external.short(2147483647); v; }
+[1] -1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { -32768 } else { v <- as.external.short(-32768); v; }
+[1] -32768
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 0 } else { v <- as.external.short(-2147483648); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 0 } else { v <- as.external.short(4.9E-324); v; }
+[1] 0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.short(1.1); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.short(1L); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 1 } else { v <- as.external.short(as.raw(1)); v; }
+[1] 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
+#if (!any(R.version$engine == "FastR")) { 32767 } else { v <- as.external.short(32767); v; }
+[1] 32767
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray, ta$booleanList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray2, ta$booleanList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray3, ta$booleanList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$byteArray, ta$byteList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$byteArray2, ta$byteList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$byteArray3, ta$byteList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray, ta$doubleList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray2, ta$doubleList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray3, ta$doubleList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$floatArray, ta$floatList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$floatArray2, ta$floatList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$floatArray3, ta$floatList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$integerArray, ta$integerList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$integerArray2, ta$integerList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$integerArray3, ta$integerList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$longArray, ta$longList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$longArray2, ta$longList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$longArray3, ta$longList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$shortArray, ta$shortList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$shortArray2, ta$shortList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$shortArray3, ta$shortList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$stringArray, ta$stringList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$stringArray2, ta$stringList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c('a', 'aa', 'aaa'), ta$stringArray3, ta$stringList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$stringArray, ta$stringList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$stringArray2, ta$stringList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$stringArray3, ta$stringList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$stringArray, ta$stringList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$stringArray2, ta$stringList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$stringArray3, ta$stringList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray, ta$stringList))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray2, ta$stringList2))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray3, ta$stringList3))) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charArray)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charArray2)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charArray3)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charList)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charList2)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charList3)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charObjectArray)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charObjectArray2)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$charObjectArray3)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$mixedObjectArray)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$stringArray)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$stringArray2)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$stringArray3)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$stringList)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$stringList2)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'character' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$stringList3)) }
+[1] "character"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$booleanArray, ta$booleanList))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$booleanArray2, ta$booleanList2))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$booleanArray3, ta$booleanList3))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$byteArray, ta$byteList))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$byteArray2, ta$byteList2))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$byteArray3, ta$byteList3))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$integerArray, ta$integerList))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$integerArray2, ta$integerList2))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$integerArray3, ta$integerList3))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$shortArray, ta$shortList))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$shortArray2, ta$shortList2))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$shortArray3, ta$shortList3))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray, ta$byteList))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray2, ta$byteList2))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray3, ta$byteList3))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray, ta$integerList))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray2, ta$integerList2))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray3, ta$integerList3))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray, ta$shortList))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray2, ta$shortList2))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray3, ta$shortList3))) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteArray)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteArray2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteArray3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteList)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteList2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteList3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteObjectArray)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteObjectArray2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$byteObjectArray3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerArray)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerArray2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerArray3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerList)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerList2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerList3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerObjectArray)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerObjectArray2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$integerObjectArray3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$mixedIntegerList)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$onlyIntegerObjectArray)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortArray)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortArray2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortArray3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortList)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortList2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortList3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortObjectArray)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortObjectArray2)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'integer' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$shortObjectArray3)) }
+[1] "integer"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray, ta$booleanList))) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray2, ta$booleanList2))) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray3, ta$booleanList3))) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanArray)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanArray2)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanArray3)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanList)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanList2)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanList3)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanObjectArray)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanObjectArray2)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'logical' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$booleanObjectArray3)) }
+[1] "logical"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray, ta$booleanList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray2, ta$booleanList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray3, ta$booleanList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$integerArray, ta$integerList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$integerArray2, ta$integerList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$integerArray3, ta$integerList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$longArray, ta$longList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$longArray2, ta$longList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$longArray3, ta$longList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$shortArray, ta$shortList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$shortArray2, ta$shortList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 1.2, 1.3), ta$shortArray3, ta$shortList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$byteArray, ta$byteList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$byteArray2, ta$byteList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$byteArray3, ta$byteList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray, ta$doubleList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray2, ta$doubleList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray3, ta$doubleList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$floatArray, ta$floatList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$floatArray2, ta$floatList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1.1, 2.1, 3.1), ta$floatArray3, ta$floatList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$doubleArray, ta$doubleList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$doubleArray2, ta$doubleList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$doubleArray3, ta$doubleList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$floatArray, ta$floatList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$floatArray2, ta$floatList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$floatArray3, ta$floatList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$longArray, ta$longList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$longArray2, ta$longList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(1L, 2L, 3L), ta$longArray3, ta$longList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray, ta$doubleList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray2, ta$doubleList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray3, ta$doubleList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray, ta$floatList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray2, ta$floatList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray3, ta$floatList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$longArray, ta$longList))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$longArray2, ta$longList2))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(list(c(TRUE, FALSE, TRUE), ta$longArray3, ta$longList3))) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleArray)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleArray2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleArray3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleList)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleList2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleList3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleObjectArray)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleObjectArray2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$doubleObjectArray3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatArray)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatArray2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatArray3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatList)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatList2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatList3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatObjectArray)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatObjectArray2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$floatObjectArray3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longArray)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longArray2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longArray3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longList)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longList2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longList3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longObjectArray)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longObjectArray2)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$longObjectArray3)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { 'numeric' } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); class(unlist(ta$onlyLongObjectArray)) }
+[1] "numeric"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); l<-list(ta, ta); ul <- unlist(l); identical(l, ul) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { TRUE } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); tal <- unlist(ta); identical(ta, tal) }
+[1] TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('1', 'a', '1') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$mixedObjectArray) }
+[1] "1" "a" "1"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$stringArray, ta$stringList)) }
+[1] "a"   "aa"  "aaa" "a"   "b"   "c"   "a"   "b"   "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$stringArray, ta$stringList), recursive=FALSE) }
+[1] "a"   "aa"  "aaa" "a"   "b"   "c"   "a"   "b"   "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$stringArray2, ta$stringList2)) }
+ [1] "a"   "aa"  "aaa" "a"   "b"   "c"   "a"   "b"   "c"   "a"   "b"   "c"
+[13] "a"   "b"   "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$stringArray3, ta$stringList3)) }
+ [1] "a"   "aa"  "aaa" "a"   "b"   "c"   "a"   "b"   "c"   "a"   "b"   "c"
+[13] "a"   "b"   "c"   "a"   "b"   "c"   "a"   "b"   "c"   "a"   "b"   "c"
+[25] "a"   "b"   "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$byteArray, ta$byteList)) }
+[1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$byteArray, ta$byteList), recursive=FALSE) }
+[1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$integerArray, ta$integerList)) }
+[1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$integerArray, ta$integerList), recursive=FALSE) }
+[1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$longArray, ta$longList)) }
+[1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$longArray, ta$longList), recursive=FALSE) }
+[1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$shortArray, ta$shortList)) }
+[1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$shortArray, ta$shortList), recursive=FALSE) }
+[1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$byteArray2, ta$byteList2)) }
+ [1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[13] "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$integerArray2, ta$integerList2)) }
+ [1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[13] "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$longArray2, ta$longList2)) }
+ [1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[13] "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$shortArray2, ta$shortList2)) }
+ [1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[13] "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$byteArray3, ta$byteList3)) }
+ [1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[13] "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[25] "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$integerArray3, ta$integerList3)) }
+ [1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[13] "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[25] "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$longArray3, ta$longList3)) }
+ [1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[13] "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[25] "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$shortArray3, ta$shortList3)) }
+ [1] "a"   "aa"  "aaa" "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[13] "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"   "1"   "2"   "3"
+[25] "1"   "2"   "3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray, ta$doubleList)) }
+[1] "a"   "aa"  "aaa" "1.1" "1.2" "1.3" "1.1" "1.2" "1.3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray, ta$doubleList), recursive=FALSE) }
+[1] "a"   "aa"  "aaa" "1.1" "1.2" "1.3" "1.1" "1.2" "1.3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray2, ta$doubleList2)) }
+ [1] "a"   "aa"  "aaa" "1.1" "1.2" "1.3" "1.1" "1.2" "1.3" "1.1" "1.2" "1.3"
+[13] "1.1" "1.2" "1.3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray3, ta$doubleList3)) }
+ [1] "a"   "aa"  "aaa" "1.1" "1.2" "1.3" "1.1" "1.2" "1.3" "1.1" "1.2" "1.3"
+[13] "1.1" "1.2" "1.3" "1.1" "1.2" "1.3" "1.1" "1.2" "1.3" "1.1" "1.2" "1.3"
+[25] "1.1" "1.2" "1.3"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$floatArray, ta$floatList)) }
+[1] "a"                "aa"               "aaa"              "1.10000002384186"
+[5] "1.20000004768372" "1.29999995231628" "1.10000002384186" "1.20000004768372"
+[9] "1.29999995231628"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$floatArray, ta$floatList), recursive=FALSE) }
+[1] "a"                "aa"               "aaa"              "1.10000002384186"
+[5] "1.20000004768372" "1.29999995231628" "1.10000002384186" "1.20000004768372"
+[9] "1.29999995231628"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$floatArray2, ta$floatList2)) }
+ [1] "a"                "aa"               "aaa"              "1.10000002384186"
+ [5] "1.20000004768372" "1.29999995231628" "1.10000002384186" "1.20000004768372"
+ [9] "1.29999995231628" "1.10000002384186" "1.20000004768372" "1.29999995231628"
+[13] "1.10000002384186" "1.20000004768372" "1.29999995231628"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$floatArray3, ta$floatList3)) }
+ [1] "a"                "aa"               "aaa"              "1.10000002384186"
+ [5] "1.20000004768372" "1.29999995231628" "1.10000002384186" "1.20000004768372"
+ [9] "1.29999995231628" "1.10000002384186" "1.20000004768372" "1.29999995231628"
+[13] "1.10000002384186" "1.20000004768372" "1.29999995231628" "1.10000002384186"
+[17] "1.20000004768372" "1.29999995231628" "1.10000002384186" "1.20000004768372"
+[21] "1.29999995231628" "1.10000002384186" "1.20000004768372" "1.29999995231628"
+[25] "1.10000002384186" "1.20000004768372" "1.29999995231628"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray, ta$booleanList)) }
+[1] "a"     "aa"    "aaa"   "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray, ta$booleanList), recursive=FALSE) }
+[1] "a"     "aa"    "aaa"   "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray2, ta$booleanList2)) }
+ [1] "a"     "aa"    "aaa"   "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"
+[10] "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'aa', 'aaa', TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray3, ta$booleanList3)) }
+ [1] "a"     "aa"    "aaa"   "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"
+[10] "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"
+[19] "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"  "TRUE"  "FALSE" "TRUE"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charArray) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charArray, recursive=FALSE) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charList) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charList, recursive=FALSE) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charObjectArray) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charObjectArray, recursive=FALSE) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringArray) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringArray, recursive=FALSE) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringList) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringList, recursive=FALSE) }
+[1] "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charArray2) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charList2) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charObjectArray2) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringArray2) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringList2) }
+[1] "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charObjectArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c('a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c'))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteArray, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteList) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteList, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteObjectArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteObjectArray, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerArray, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerList) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerList, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerObjectArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerObjectArray, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longArray, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longList) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longList, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longObjectArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longObjectArray, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$onlyIntegerObjectArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$onlyLongObjectArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortArray, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortList) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortList, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortObjectArray) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortObjectArray, recursive=FALSE) }
+[1] 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteArray2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteList2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteObjectArray2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerArray2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerList2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerObjectArray2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longArray2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longList2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longObjectArray2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortArray2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortList2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortObjectArray2) }
+[1] 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteObjectArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerObjectArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longObjectArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortObjectArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$mixedIntegerList) }
+ [1]  1  2  3  4  5  6  7  8  9 10 11 12
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleArray) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleArray, recursive=FALSE) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleList) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleList, recursive=FALSE) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleObjectArray) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleObjectArray, recursive=FALSE) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatArray) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatArray, recursive=FALSE) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatList) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatList, recursive=FALSE) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatObjectArray) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatObjectArray, recursive=FALSE) }
+[1] 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$stringArray, ta$stringList)) }
+[1] "1.1" "1.2" "1.3" "a"   "b"   "c"   "a"   "b"   "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$stringArray, ta$stringList), recursive=FALSE) }
+[1] "1.1" "1.2" "1.3" "a"   "b"   "c"   "a"   "b"   "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$stringArray2, ta$stringList2)) }
+ [1] "1.1" "1.2" "1.3" "a"   "b"   "c"   "a"   "b"   "c"   "a"   "b"   "c"
+[13] "a"   "b"   "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$stringArray3, ta$stringList3)) }
+ [1] "1.1" "1.2" "1.3" "a"   "b"   "c"   "a"   "b"   "c"   "a"   "b"   "c"
+[13] "a"   "b"   "c"   "a"   "b"   "c"   "a"   "b"   "c"   "a"   "b"   "c"
+[25] "a"   "b"   "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$integerArray, ta$integerList)) }
+[1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$integerArray, ta$integerList), recursive=FALSE) }
+[1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$longArray, ta$longList)) }
+[1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$longArray, ta$longList), recursive=FALSE) }
+[1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$shortArray, ta$shortList)) }
+[1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$shortArray, ta$shortList), recursive=FALSE) }
+[1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$integerArray2, ta$integerList2)) }
+ [1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$longArray2, ta$longList2)) }
+ [1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$shortArray2, ta$shortList2)) }
+ [1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$integerArray3, ta$integerList3)) }
+ [1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0
+[20] 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$longArray3, ta$longList3)) }
+ [1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0
+[20] 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$shortArray3, ta$shortList3)) }
+ [1] 1.1 1.2 1.3 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0
+[20] 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleArray2) }
+[1] 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleList2) }
+[1] 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleObjectArray2) }
+[1] 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatArray2) }
+[1] 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatList2) }
+[1] 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatObjectArray2) }
+[1] 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleObjectArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatObjectArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray, ta$booleanList)) }
+[1] 1.1 1.2 1.3 1.0 0.0 1.0 1.0 0.0 1.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray, ta$booleanList), recursive=FALSE) }
+[1] 1.1 1.2 1.3 1.0 0.0 1.0 1.0 0.0 1.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray2, ta$booleanList2)) }
+ [1] 1.1 1.2 1.3 1.0 0.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 1.2, 1.3, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray3, ta$booleanList3)) }
+ [1] 1.1 1.2 1.3 1.0 0.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0 1.0
+[20] 0.0 1.0 1.0 0.0 1.0 1.0 0.0 1.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$byteArray, ta$byteList)) }
+[1] 1.1 2.1 3.1 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$byteArray, ta$byteList), recursive=FALSE) }
+[1] 1.1 2.1 3.1 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$byteArray2, ta$byteList2)) }
+ [1] 1.1 2.1 3.1 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$byteArray3, ta$byteList3)) }
+ [1] 1.1 2.1 3.1 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0 1.0
+[20] 2.0 3.0 1.0 2.0 3.0 1.0 2.0 3.0
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray, ta$doubleList)) }
+[1] 1.1 2.1 3.1 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray, ta$doubleList), recursive=FALSE) }
+[1] 1.1 2.1 3.1 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray2, ta$doubleList2)) }
+ [1] 1.1 2.1 3.1 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray3, ta$doubleList3)) }
+ [1] 1.1 2.1 3.1 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1
+[20] 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$floatArray, ta$floatList)) }
+[1] 1.1 2.1 3.1 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$floatArray, ta$floatList), recursive=FALSE) }
+[1] 1.1 2.1 3.1 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$floatArray2, ta$floatList2)) }
+ [1] 1.1 2.1 3.1 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1.1, 2.1, 3.1, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$floatArray3, ta$floatList3)) }
+ [1] 1.1 2.1 3.1 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1
+[20] 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$stringArray, ta$stringList)) }
+[1] "1" "2" "3" "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$stringArray, ta$stringList), recursive=FALSE) }
+[1] "1" "2" "3" "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$stringArray2, ta$stringList2)) }
+ [1] "1" "2" "3" "a" "b" "c" "a" "b" "c" "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$stringArray3, ta$stringList3)) }
+ [1] "1" "2" "3" "a" "b" "c" "a" "b" "c" "a" "b" "c" "a" "b" "c" "a" "b" "c" "a"
+[20] "b" "c" "a" "b" "c" "a" "b" "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$byteArray, ta$byteList)) }
+[1] 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$byteArray, ta$byteList), recursive=FALSE) }
+[1] 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$integerArray, ta$integerList)) }
+[1] 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$integerArray, ta$integerList), recursive=FALSE) }
+[1] 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$longArray, ta$longList)) }
+[1] 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$longArray, ta$longList), recursive=FALSE) }
+[1] 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$shortArray, ta$shortList)) }
+[1] 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$shortArray, ta$shortList), recursive=FALSE) }
+[1] 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$byteArray2, ta$byteList2)) }
+ [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$integerArray2, ta$integerList2)) }
+ [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$longArray2, ta$longList2)) }
+ [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$shortArray2, ta$shortList2)) }
+ [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$byteArray3, ta$byteList3)) }
+ [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$integerArray3, ta$integerList3)) }
+ [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$longArray3, ta$longList3)) }
+ [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$shortArray3, ta$shortList3)) }
+ [1] 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$doubleArray, ta$doubleList)) }
+[1] 1.0 2.0 3.0 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$doubleArray, ta$doubleList), recursive=FALSE) }
+[1] 1.0 2.0 3.0 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$doubleArray2, ta$doubleList2)) }
+ [1] 1.0 2.0 3.0 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$doubleArray3, ta$doubleList3)) }
+ [1] 1.0 2.0 3.0 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1
+[20] 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$floatArray, ta$floatList)) }
+[1] 1.0 2.0 3.0 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$floatArray, ta$floatList), recursive=FALSE) }
+[1] 1.0 2.0 3.0 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$floatArray2, ta$floatList2)) }
+ [1] 1.0 2.0 3.0 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$floatArray3, ta$floatList3)) }
+ [1] 1.0 2.0 3.0 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1
+[20] 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$booleanArray, ta$booleanList)) }
+[1] 1 2 3 1 0 1 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$booleanArray, ta$booleanList), recursive=FALSE) }
+[1] 1 2 3 1 0 1 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$booleanArray2, ta$booleanList2)) }
+ [1] 1 2 3 1 0 1 1 0 1 1 0 1 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(1L, 2L, 3L, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$booleanArray3, ta$booleanList3)) }
+ [1] 1 2 3 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1 1 0 1
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanArray) }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanArray, recursive=FALSE) }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanList) }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanList, recursive=FALSE) }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanObjectArray) }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanObjectArray, recursive=FALSE) }
+[1]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray, ta$stringList)) }
+[1] "TRUE"  "FALSE" "TRUE"  "a"     "b"     "c"     "a"     "b"     "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray, ta$stringList), recursive=FALSE) }
+[1] "TRUE"  "FALSE" "TRUE"  "a"     "b"     "c"     "a"     "b"     "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray2, ta$stringList2)) }
+ [1] "TRUE"  "FALSE" "TRUE"  "a"     "b"     "c"     "a"     "b"     "c"
+[10] "a"     "b"     "c"     "a"     "b"     "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c', 'a', 'b', 'c') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray3, ta$stringList3)) }
+ [1] "TRUE"  "FALSE" "TRUE"  "a"     "b"     "c"     "a"     "b"     "c"
+[10] "a"     "b"     "c"     "a"     "b"     "c"     "a"     "b"     "c"
+[19] "a"     "b"     "c"     "a"     "b"     "c"     "a"     "b"     "c"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray, ta$byteList)) }
+[1] 1 0 1 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray, ta$byteList), recursive=FALSE) }
+[1] 1 0 1 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray, ta$integerList)) }
+[1] 1 0 1 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray, ta$integerList), recursive=FALSE) }
+[1] 1 0 1 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$longArray, ta$longList)) }
+[1] 1 0 1 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$longArray, ta$longList), recursive=FALSE) }
+[1] 1 0 1 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray, ta$shortList)) }
+[1] 1 0 1 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray, ta$shortList), recursive=FALSE) }
+[1] 1 0 1 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray2, ta$byteList2)) }
+ [1] 1 0 1 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray2, ta$integerList2)) }
+ [1] 1 0 1 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$longArray2, ta$longList2)) }
+ [1] 1 0 1 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray2, ta$shortList2)) }
+ [1] 1 0 1 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray3, ta$byteList3)) }
+ [1] 1 0 1 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray3, ta$integerList3)) }
+ [1] 1 0 1 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$longArray3, ta$longList3)) }
+ [1] 1 0 1 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray3, ta$shortList3)) }
+ [1] 1 0 1 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3 1 2 3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray, ta$doubleList)) }
+[1] 1.0 0.0 1.0 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray, ta$doubleList), recursive=FALSE) }
+[1] 1.0 0.0 1.0 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray2, ta$doubleList2)) }
+ [1] 1.0 0.0 1.0 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3, 1.1, 1.2, 1.3) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray3, ta$doubleList3)) }
+ [1] 1.0 0.0 1.0 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1
+[20] 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray, ta$floatList)) }
+[1] 1.0 0.0 1.0 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray, ta$floatList), recursive=FALSE) }
+[1] 1.0 0.0 1.0 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray2, ta$floatList2)) }
+ [1] 1.0 0.0 1.0 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842, 1.100000023841858, 1.2000000476837158, 1.2999999523162842) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray3, ta$floatList3)) }
+ [1] 1.0 0.0 1.0 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3 1.1
+[20] 1.2 1.3 1.1 1.2 1.3 1.1 1.2 1.3
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanArray2) }
+[1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanList2) }
+[1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanObjectArray2) }
+[1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray, ta$booleanList)) }
+[1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray, ta$booleanList), recursive=FALSE) }
+[1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanList3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanObjectArray3) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE))"
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray2, ta$booleanList2)) }
+ [1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+[13]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { c(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE, TRUE, FALSE, TRUE) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray3, ta$booleanList3)) }
+ [1]  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+[13]  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE  TRUE FALSE  TRUE
+[25]  TRUE FALSE  TRUE
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray2, ta$booleanList2), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$booleanArray3, ta$booleanList3), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$byteArray2, ta$byteList2), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$byteArray3, ta$byteList3), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray2, ta$doubleList2), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$doubleArray3, ta$doubleList3), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$floatArray2, ta$floatList2), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$floatArray3, ta$floatList3), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$integerArray2, ta$integerList2), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$integerArray3, ta$integerList3), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$longArray2, ta$longList2), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$longArray3, ta$longList3), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$shortArray2, ta$shortList2), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$shortArray3, ta$shortList3), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$stringArray2, ta$stringList2), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] "a"','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] "aa"','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] "aaa"','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c('a', 'aa', 'aaa'), ta$stringArray3, ta$stringList3), recursive=FALSE) }
+[[1]]
+[1] "a"
+
+[[2]]
+[1] "aa"
+
+[[3]]
+[1] "aaa"
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$booleanArray2, ta$booleanList2), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$booleanArray3, ta$booleanList3), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$byteArray2, ta$byteList2), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$byteArray3, ta$byteList3), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$doubleArray2, ta$doubleList2), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$doubleArray3, ta$doubleList3), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$floatArray2, ta$floatList2), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$floatArray3, ta$floatList3), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$integerArray2, ta$integerList2), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$integerArray3, ta$integerList3), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$longArray2, ta$longList2), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$longArray3, ta$longList3), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$shortArray2, ta$shortList2), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$shortArray3, ta$shortList3), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$stringArray2, ta$stringList2), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1L, 2L, 3L), ta$stringArray3, ta$stringList3), recursive=FALSE) }
+[[1]]
+[1] 1
+
+[[2]]
+[1] 2
+
+[[3]]
+[1] 3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray2, ta$booleanList2), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$booleanArray3, ta$booleanList3), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$integerArray2, ta$integerList2), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$integerArray3, ta$integerList3), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$longArray2, ta$longList2), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$longArray3, ta$longList3), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$shortArray2, ta$shortList2), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$shortArray3, ta$shortList3), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$stringArray2, ta$stringList2), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 1.2','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 1.3','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 1.2, 1.3), ta$stringArray3, ta$stringList3), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 1.2
+
+[[3]]
+[1] 1.3
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2.1','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3.1','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$byteArray2, ta$byteList2), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 2.1
+
+[[3]]
+[1] 3.1
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2.1','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3.1','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$byteArray3, ta$byteList3), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 2.1
+
+[[3]]
+[1] 3.1
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2.1','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3.1','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray2, ta$doubleList2), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 2.1
+
+[[3]]
+[1] 3.1
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2.1','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3.1','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$doubleArray3, ta$doubleList3), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 2.1
+
+[[3]]
+[1] 3.1
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2.1','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3.1','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$floatArray2, ta$floatList2), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 2.1
+
+[[3]]
+[1] 3.1
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] 1.1','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] 2.1','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] 3.1','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(1.1, 2.1, 3.1), ta$floatArray3, ta$floatList3), recursive=FALSE) }
+[[1]]
+[1] 1.1
+
+[[2]]
+[1] 2.1
+
+[[3]]
+[1] 3.1
+
+[[4]]
+[external object]
+
+[[5]]
+[external object]
+
+[[6]]
+[external object]
+
+[[7]]
+[external object]
+
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray2, ta$booleanList2), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloat }
-[1] 3.402823e+38
+[[2]]
+[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticFloatObject }
-[1] 3.402823e+38
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShort }
-[1] 32767
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldShortObject }
-[1] 32767
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShort }
-[1] 32767
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticShortObject }
-[1] 32767
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLong }
-[1] 9.223372e+18
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldLongObject }
-[1] 9.223372e+18
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$booleanArray3, ta$booleanList3), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLong }
-[1] 9.223372e+18
+[[2]]
+[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticLongObject }
-[1] 9.223372e+18
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldNullObject }
-NULL
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNullObject }
-NULL
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NaN } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNaN }
-[1] NaN
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NaN } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticNaNObject }
-[1] NaN
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBoolean }
-[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldBooleanObject }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray2, ta$byteList2), recursive=FALSE) }
+[[1]]
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBoolean }
-[1] TRUE
+[[2]]
+[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$fieldStaticBooleanObject }
+[[3]]
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[4]]
 [external object]
-[1]  TRUE FALSE  TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[5]]
 [external object]
-[1]  TRUE FALSE  TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[6]]
 [external object]
-[1] "a" "b" "c"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[7]]
 [external object]
-[1] "a" "b" "c"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$byteArray3, ta$byteList3), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[2]]
+[1] FALSE
+
+[[3]]
+[1] TRUE
+
+[[4]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[5]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[6]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[7]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray2, ta$doubleList2), recursive=FALSE) }
+[[1]]
+[1] TRUE
+
+[[2]]
+[1] FALSE
+
+[[3]]
+[1] TRUE
+
+[[4]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[5]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[6]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[7]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$doubleArray3, ta$doubleList3), recursive=FALSE) }
+[[1]]
+[1] TRUE
+
+[[2]]
+[1] FALSE
+
+[[3]]
+[1] TRUE
+
+[[4]]
 [external object]
-[1] 1.1 2.1 3.1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[5]]
 [external object]
-[1] 1.1 2.1 3.1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[6]]
 [external object]
-[1] 1.1 2.1 3.1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFields#
-#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 }
+[[7]]
 [external object]
-[1] 1.1 2.1 3.1
 
-##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) }
-[1] "character"
 
-##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$fieldStaticStringArray); typeof(v) }
-[1] "character"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray2, ta$floatList2), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticDoubleArray); typeof(v) }
-[1] "double"
+[[2]]
+[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticFloatArray); typeof(v) }
-[1] "double"
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticLongArray); typeof(v) }
-[1] "double"
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "double" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectDoubleArray); typeof(v) }
-[1] "double"
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticByteArray); typeof(v) }
-[1] "integer"
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticIntArray); typeof(v) }
-[1] "integer"
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticShortArray); typeof(v) }
-[1] "integer"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "integer" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectIntArray); typeof(v) }
-[1] "integer"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$floatArray3, ta$floatList3), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "logical" } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticBooleanArray); typeof(v) }
-[1] "logical"
+[[2]]
+[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticBooleanArray); is.vector(v) }
+[[3]]
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticByteArray); is.vector(v) }
-[1] TRUE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticCharArray); is.vector(v) }
-[1] TRUE
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticDoubleArray); is.vector(v) }
-[1] TRUE
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticFloatArray); is.vector(v) }
-[1] TRUE
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticIntArray); is.vector(v) }
-[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticLongArray); is.vector(v) }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray2, ta$integerList2), recursive=FALSE) }
+[[1]]
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticShortArray); is.vector(v) }
-[1] TRUE
+[[2]]
+[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$fieldStaticStringArray); is.vector(v) }
+[[3]]
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); is.list(v) }
-[1] TRUE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$mixedTypesArray); is.list(v) }
-[1] TRUE
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectArray); is.list(v) }
-[1] TRUE
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectDoubleArray); is.vector(v) }
-[1] TRUE
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$objectIntArray); is.vector(v) }
-[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(1) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[1] }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$integerArray3, ta$integerList3), recursive=FALSE) }
 [[1]]
-[1] 1
+[1] TRUE
 
+[[2]]
+[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(3) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[3] }
-[[1]]
-[1] 3
+[[3]]
+[1] TRUE
 
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testFromArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { list(NULL) } else { t <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[2] }
-[[1]]
-NULL
+[[5]]
+[external object]
 
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { tc <- .fastr.java.class('java.lang.Character'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t }
-[1] "a"
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'abc' } else { tc <- .fastr.java.class('java.lang.String'); t <- .fastr.interop.new(tc, 'abc'); t }
-[1] "abc"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'truffle.object' } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNullClass'); t <- .fastr.interop.new(tc, NULL); class(t) }
-[1] "truffle.object"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$longArray2, ta$longList2), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Byte'); t <- .fastr.interop.new(tc, .fastr.interop.toByte(1)); t }
-[1] 1
+[[2]]
+[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Integer'); t <- .fastr.interop.new(tc, 1L); t }
-[1] 1
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Long'); t <- .fastr.interop.new(tc, .fastr.interop.toLong(1)); t }
-[1] 1
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { tc <- .fastr.java.class('java.lang.Short'); t <- .fastr.interop.new(tc, .fastr.interop.toShort(1)); t }
-[1] 1
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { tc <- .fastr.java.class('java.lang.Double'); t <- .fastr.interop.new(tc, 1.1); t }
-[1] 1.1
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { tc <- .fastr.java.class('java.lang.Float'); t <- .fastr.interop.new(tc, .fastr.interop.toFloat(1.1)); t }
-[1] 1.1
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('java.lang.Boolean'); t <- .fastr.interop.new(tc, TRUE); t }
-[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testInteroptNew#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('java/lang/Boolean'); t <- new(tc, TRUE); t }
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$longArray3, ta$longList3), recursive=FALSE) }
+[[1]]
 [1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.array(to) }
+[[2]]
 [1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.atomic(to) }
-[1] FALSE
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.call(to) }
-[1] FALSE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.character(to) }
-[1] FALSE
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.complex(to) }
-[1] FALSE
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.data.frame(to) }
-[1] FALSE
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.double(to) }
-[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.environment(to) }
-[1] FALSE
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray2, ta$shortList2), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.expression(to) }
+[[2]]
 [1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.factor(to) }
-[1] FALSE
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.function(to) }
-[1] FALSE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.integer(to) }
-[1] FALSE
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.language(to) }
-[1] FALSE
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.logical(to) }
-[1] FALSE
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.matrix(to) }
-[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.mts(to) }
-[1] FALSE
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$shortArray3, ta$shortList3), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.na(to) }
+[[2]]
 [1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.name(to) }
-[1] FALSE
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.null(to) }
-[1] FALSE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric(to) }
-[1] FALSE
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric.Date(to) }
-[1] FALSE
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric.POSIXt(to) }
-[1] FALSE
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric.difftime(to) }
-[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.numeric_version(to) }
-[1] FALSE
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray2, ta$stringList2), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.object(to) }
+[[2]]
 [1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.ordered(to) }
-[1] FALSE
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.package_version(to) }
-[1] FALSE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.pairlist(to) }
-[1] FALSE
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.primitive(to) }
-[1] FALSE
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.qr(to) }
-[1] FALSE
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.raster(to) }
-[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.raw(to) }
-[1] FALSE
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[1] FALSE','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[1] TRUE','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[5]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[6]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[7]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(list(c(TRUE, FALSE, TRUE), ta$stringArray3, ta$stringList3), recursive=FALSE) }
+[[1]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.recursive(to) }
+[[2]]
 [1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.relistable(to) }
-[1] FALSE
+[[3]]
+[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.stepfun(to) }
-[1] FALSE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.symbol(to) }
-[1] FALSE
+[[5]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.table(to) }
-[1] FALSE
+[[6]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.ts(to) }
-[1] FALSE
+[[7]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.tskernel(to) }
-[1] FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.unsorted(to) }
-[1] FALSE
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.vector(to) }
-[1] FALSE
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in is.finite(to) : ', '<<<NEWLINE>>>', '  default method not implemented for type \'external object\'<<<NEWLINE>>>', sep='') } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.finite(to) }
-Error in is.finite(to) :
-  default method not implemented for type 'external object'
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in is.infinite(to) : ', '<<<NEWLINE>>>', '  default method not implemented for type \'external object\'<<<NEWLINE>>>', sep='') } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.infinite(to) }
-Error in is.infinite(to) :
-  default method not implemented for type 'external object'
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testIsXXXForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in is.nan(to) : ', '<<<NEWLINE>>>', '  default method not implemented for type \'external object\'<<<NEWLINE>>>', sep='') } else { to <- .fastr.interop.new(.fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass')); is.nan(to) }
-Error in is.nan(to) :
-  default method not implemented for type 'external object'
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticStringObject() }
-[1] "a string"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanList3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a string" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStringObject() }
-[1] "a string"
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodChar() }
-[1] "a"
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodCharObject() }
-[1] "a"
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticChar() }
-[1] "a"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { "a" } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticCharObject() }
-[1] "a"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanObjectArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodDouble() }
-[1] 1.797693e+308
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodDoubleObject() }
-[1] 1.797693e+308
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticDouble() }
-[1] 1.797693e+308
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.7976931348623157E308 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticDoubleObject() }
-[1] 1.797693e+308
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodByte() }
-[1] 127
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodByteObject() }
-[1] 127
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticByte() }
-[1] 127
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticByteObject() }
-[1] 127
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodInteger() }
-[1] 2147483647
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodIntegerObject() }
-[1] 2147483647
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteList3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticInteger() }
-[1] 2147483647
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticIntegerObject() }
-[1] 2147483647
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodFloat() }
-[1] 3.402823e+38
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodFloatObject() }
-[1] 3.402823e+38
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticFloat() }
-[1] 3.402823e+38
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteObjectArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticFloatObject() }
-[1] 3.402823e+38
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodShort() }
-[1] 32767
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodShortObject() }
-[1] 32767
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticShort() }
-[1] 32767
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticShortObject() }
-[1] 32767
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodLong() }
-[1] 9.223372e+18
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodLongObject() }
-[1] 9.223372e+18
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticLong() }
-[1] 9.223372e+18
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticLongObject() }
-[1] 9.223372e+18
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodReturnsNull() }
-NULL
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charList3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticReturnsNull() }
-NULL
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodBoolean() }
-[1] TRUE
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodBooleanObject() }
-[1] TRUE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticBoolean() }
-[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodStaticBooleanObject() }
-[1] TRUE
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charObjectArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#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() }
+[[2]]
 [external object]
-[1] "a" "b" "c"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#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() }
+[[3]]
 [external object]
-[1] "a" "b" "c"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#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() }
+[[4]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testMethods#
-#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() }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleArray3, recursive=FALSE) }
+[[1]]
 [external object]
-[1] 1 2 3
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em) }
-NULL
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); names(tc$staticField) }
-NULL
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); names(tc$staticMethod) }
-NULL
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassNoMembers'); t <- .fastr.interop.new(tc); names(t) }
-NULL
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { NULL } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassNoPublicMembers'); t <- .fastr.interop.new(tc); names(t) }
-NULL
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleList3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('field', 'method', 'staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); t <- .fastr.interop.new(tc); sort(names(t)) }
-[1] "field"        "method"       "staticField"  "staticMethod"
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('one', 'two') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClassMap'); t <- .fastr.interop.new(tc); sort(names(t$m())) }
-[1] "one" "two"
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNamesForForeignObject#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { c('staticField', 'staticMethod') } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestNamesClass'); sort(names(tc)) }
-[1] "staticField"  "staticMethod"
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- new(tc); to$fieldInteger }
-[1] 2147483647
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { to <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to$fieldStaticInteger }
-[1] 2147483647
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleObjectArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('java.lang.Boolean'); to <- new(tc, TRUE); to }
-[1] TRUE
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { to <- new('java.lang.Boolean', TRUE); to }
-[1] TRUE
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { to <- new('java/lang/Boolean', TRUE); to }
-[1] TRUE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in .fastr.interop.new(Class, ...) : ', '<<<NEWLINE>>>', '  error during Java object instantiation<<<NEWLINE>>>', sep='') } else { to <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); new(to) }
-Error in .fastr.interop.new(Class, ...) :
-  error during Java object instantiation
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNewWithJavaClass#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in getClass(Class, where = topenv(parent.frame())) : ', '<<<NEWLINE>>>', '  “__bogus_class_name__” is not a defined class<<<NEWLINE>>>', sep='') } else { to <- new('__bogus_class_name__'); }
-Error in getClass(Class, where = topenv(parent.frame())) :
-  “__bogus_class_name__” is not a defined class
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNonPrimitiveParameter#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$equals(t) }
-[1] TRUE
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) {  } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$methodAcceptsOnlyNull(NULL) }
-NULL
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.Long } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull(1) }
-Error: object 'java.lang.Long' not found
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testNullParameters#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isNull('string') }
-Error: object 'java.lang.String' not found
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { boolean } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded(TRUE) }
-Error: object 'boolean' not found
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatList3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testOverloaded#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { java.lang.String } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); t <- .fastr.interop.new(tc); t$isOverloaded('string') }
-Error: object 'java.lang.String' not found
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(c(to, to)); .fastr.java.isArray(a) }
-[1] TRUE
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { tc <- .fastr.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(to); .fastr.java.isArray(a) }
-[1] TRUE
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatObjectArray3, recursive=FALSE) }
+[[1]]
 [external object]
-[1]  TRUE FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[2]]
 [external object]
-[1]  TRUE FALSE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[3]]
 [external object]
-[1] "a" "b"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[4]]
 [external object]
-[1] "a" "b"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a"\n') } else { a <- .fastr.java.toArray('a'); a; }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerArray3, recursive=FALSE) }
+[[1]]
 [external object]
-[1] "a"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] "a"\n') } else { a <- .fastr.java.toArray('a',,T); a; }
+[[2]]
 [external object]
-[1] "a"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[3]]
 [external object]
-[1] 1 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[4]]
 [external object]
-[1] 1 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerList3, recursive=FALSE) }
+[[1]]
 [external object]
-[1] 1 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[2]]
 [external object]
-[1] 1 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[3]]
 [external object]
-[1] 1 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[4]]
 [external object]
-[1] 1 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerObjectArray3, recursive=FALSE) }
+[[1]]
 [external object]
-[1] 1 2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[2]]
 [external object]
-[1] 1.1 1.2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[3]]
 [external object]
-[1] 1.1 1.2
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[4]]
 [external object]
-[1] 1.123 2.123
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longArray3, recursive=FALSE) }
+[[1]]
 [external object]
-[1] 1.1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[2]]
 [external object]
-[1] 1.1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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); }
+[[3]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[4]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longList3, recursive=FALSE) }
+[[1]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[2]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[3]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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; }
+[[4]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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); }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longObjectArray3, recursive=FALSE) }
+[[1]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#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); }
+[[2]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L); a; }
+[[3]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#Ignored.Unimplemented#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L,,F); a; }
+[[4]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] 1\n') } else { a <- .fastr.java.toArray(1L,,T); a; }
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortArray3, recursive=FALSE) }
+[[1]]
 [external object]
-[1] 1
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T); a; }
+[[2]]
 [external object]
-[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToArray#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('[external object]\n[1] TRUE\n') } else { a <- .fastr.java.toArray(T,,T); a; }
+[[3]]
 [external object]
-[1] TRUE
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); class(v); }
-[1] "interopt.byte"
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.byte' } else { v <- .fastr.interop.toByte(1.1); typeof(v); }
-[1] "interopt.byte"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toByte(1.7976931348623157E308); v; }
-[1] -1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortList3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toByte(2147483647); v; }
-[1] -1
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { -128 } else { v <- .fastr.interop.toByte(-128); v; }
-[1] -128
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toByte(-2147483648); v; }
-[1] 0
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toByte(4.9E-324); v; }
-[1] 0
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1.1); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortObjectArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(1L); v; }
-[1] 1
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toByte(as.raw(1)); v; }
-[1] 1
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToByte#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 127 } else { v <- .fastr.interop.toByte(127); v; }
-[1] 127
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar('a'); v; }
-[1] "a"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97.1); v; }
-[1] "a"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringArray3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'a' } else { v <- .fastr.interop.toChar(97L); v; }
-[1] "a"
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'b' } else { v <- .fastr.interop.toChar('abc', 1); v; }
-[1] "b"
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'b' } else { v <- .fastr.interop.toChar('abc', 1.1); v; }
-[1] "b"
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97.1); class(v); }
-[1] "interopt.char"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97.1); typeof(v); }
-[1] "interopt.char"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { cat('[[1]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[2]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[3]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>','[[4]]','<<<NEWLINE>>>','[external object]','<<<NEWLINE>>><<<NEWLINE>>>', sep='') } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringList3, recursive=FALSE) }
+[[1]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97L); class(v); }
-[1] "interopt.char"
+[[2]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.char' } else { v <- .fastr.interop.toChar(97L); typeof(v); }
-[1] "interopt.char"
+[[3]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in .fastr.interop.toChar(97.1, 1) : ', '<<<NEWLINE>>>', ' pos argument not allowed with a numeric value', '<<<NEWLINE>>>') } else { v <- .fastr.interop.toChar(97.1, 1); v; }
-Error in .fastr.interop.toChar(97.1, 1) :
-  pos argument not allowed with a numeric value
+[[4]]
+[external object]
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToChar#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { cat('Error in .fastr.interop.toChar(97L, 1) : ','<<<NEWLINE>>>',' pos argument not allowed with a numeric value', '<<<NEWLINE>>>') } else { v <- .fastr.interop.toChar(97L, 1); v; }
-Error in .fastr.interop.toChar(97L, 1) :
-  pos argument not allowed with a numeric value
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); class(v); }
-[1] "interopt.float"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c'))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1.1); typeof(v); }
-[1] "interopt.float"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c'))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1L); class(v); }
-[1] "interopt.float"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$charObjectArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c'))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.float' } else { v <- .fastr.interop.toFloat(1L); typeof(v); }
-[1] "interopt.float"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c'))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0.0 } else { v <- .fastr.interop.toFloat(4.9E-324); v; }
-[1] 0
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c')) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$stringList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list('a', 'b', 'c', 'a', 'b', 'c'))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(1L); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toFloat(as.raw(1)); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.1 } else { v <- .fastr.interop.toFloat(1.1); v; }
-[1] 1.1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$byteObjectArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1.401298464324817E-45 } else { v <- .fastr.interop.toFloat(1.4E-45); v; }
-[1] 1.401298e-45
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 3.4028235E38 } else { v <- .fastr.interop.toFloat(3.4028235E38); v; }
-[1] 3.402823e+38
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToFloat#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { Inf } else { v <- .fastr.interop.toFloat(1.7976931348623157E308); v; }
-[1] Inf
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$integerObjectArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); class(v); }
-[1] "interopt.long"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1.1); typeof(v); }
-[1] "interopt.long"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1L); class(v); }
-[1] "interopt.long"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$longObjectArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.long' } else { v <- .fastr.interop.toLong(1L); typeof(v); }
-[1] "interopt.long"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { -2147483648 } else { v <- .fastr.interop.toLong(-2147483648); v; }
-[1] -2147483648
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toLong(4.9E-324); v; }
-[1] 0
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$shortObjectArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1, 2, 3, 1, 2, 3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1.1); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(1L); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toLong(as.raw(1)); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$doubleObjectArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2147483647 } else { v <- .fastr.interop.toLong(2147483647); v; }
-[1] 2147483647
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToLong#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 9223372036854775807 } else { v <- .fastr.interop.toLong(1.7976931348623157E308); v; }
-[1] 9.223372e+18
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); class(v); }
-[1] "interopt.short"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$floatObjectArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(1.1, 1.2, 1.3, 1.1, 1.2, 1.3))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1.1); typeof(v); }
-[1] "interopt.short"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1L); class(v); }
-[1] "interopt.short"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanList2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 'interopt.short' } else { v <- .fastr.interop.toShort(1L); typeof(v); }
-[1] "interopt.short"
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testUnlist#
+#if (!any(R.version$engine == "FastR")) { list(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE)) } else { ta <- new('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestArraysClass'); unlist(ta$booleanObjectArray2, recursive=FALSE) }
+Error: unexpected ')' in "if (!any(R.version$engine == "FastR")) { list(TRUE, FALSE, TRUE, TRUE, FALSE, TRUE))"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(1.7976931348623157E308); v; }
-[1] -1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { cat('Error in if (T) print(\'OK\') :  argument is not interpretable as logical', '<<<NEWLINE>>>') } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to) print('OK') }
+Error in if (T) print('OK') :  argument is not interpretable as logical
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { -1 } else { v <- .fastr.interop.toShort(2147483647); v; }
-[1] -1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#
+#if (!any(R.version$engine == "FastR")) { while(1) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$fieldInteger) {print('OK'); break;} }
+[1] "OK"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { -32768 } else { v <- .fastr.interop.toShort(-32768); v; }
-[1] -32768
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#
+#if (!any(R.version$engine == "FastR")) { while(T) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$fieldBoolean) {print('OK'); break;} }
+[1] "OK"
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toShort(-2147483648); v; }
-[1] 0
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { while(c("TRUE","TRUE","FALSE")) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$listStringBoolean) {print('OK'); break;} }
+[1] "OK"
+Warning message:
+In while (c("TRUE", "TRUE", "FALSE")) { :
+  the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 0 } else { v <- .fastr.interop.toShort(4.9E-324); v; }
-[1] 0
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { while(c('A', 'B')) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$listString) {print('OK'); break;} }
+Error in while (c("A", "B")) { : argument is not interpretable as logical
+In addition: Warning message:
+In while (c("A", "B")) { :
+  the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1.1); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { while(c('TRUE', 'TRUE', 'FALSE')) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$fieldStringBooleanArray) {print('OK'); break;} }
+[1] "OK"
+Warning message:
+In while (c("TRUE", "TRUE", "FALSE")) { :
+  the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(1L); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreWarningContext#Output.IgnoreErrorContext#
+#if (!any(R.version$engine == "FastR")) { while(c('a', 'b')) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));if(to$fieldStringArray) {print('OK'); break;} }
+Error in while (c("a", "b")) { : argument is not interpretable as logical
+In addition: Warning message:
+In while (c("a", "b")) { :
+  the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { v <- .fastr.interop.toShort(as.raw(1)); v; }
-[1] 1
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { while(c(T, F)) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$fieldBooleanArray) {print('OK'); break;} }
+[1] "OK"
+Warning message:
+In while (c(T, F)) { :
+  the condition has length > 1 and only the first element will be used
 
-##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testToShort#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 32767 } else { v <- .fastr.interop.toShort(32767); v; }
-[1] 32767
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { while(c(T, F)) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$fieldIntegerArray) {print('OK'); break;} }
+[1] "OK"
+Warning message:
+In while (c(T, F)) { :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { while(c(T, F)) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$listBoolean) {print('OK'); break;} }
+[1] "OK"
+Warning message:
+In while (c(T, F)) { :
+  the condition has length > 1 and only the first element will be used
+
+##com.oracle.truffle.r.test.library.fastr.TestJavaInterop.testWhile#Output.IgnoreWarningContext#
+#if (!any(R.version$engine == "FastR")) { while(c(T, F)) {print('OK'); break;} } else { to <- new.external(new.java.class('com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'));while(to$listInteger) {print('OK'); break;} }
+[1] "OK"
+Warning message:
+In while (c(T, F)) { :
+  the condition has length > 1 and only the first element will be used
 
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 1 } else { { f<-function(x) .fastr.refcountinfo(x); f(c(1,2)) } }
+#if (!any(R.version$engine == "FastR")) { 1 } else { { f<-function(x) .fastr.refcountinfo(x); f(c(1,2)) } }
 [1] 1
 
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { { f<-function(x) { y<-x; .fastr.refcountinfo(y) }; f(c(1,2)) } }
+#if (!any(R.version$engine == "FastR")) { 2 } else { { f<-function(x) { y<-x; .fastr.refcountinfo(y) }; f(c(1,2)) } }
 [1] 2
 
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { 2 } else { { x<-c(1,2); f<-function(x) .fastr.refcountinfo(x); f(x) } }
+#if (!any(R.version$engine == "FastR")) { 2 } else { { x<-c(1,2); f<-function(x) .fastr.refcountinfo(x); f(x) } }
 [1] 2
 
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { FALSE } else { { f<-function(y) { x<-y; xi1<-.fastr.identity(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 }; f(c(1,2)) } }
+#if (!any(R.version$engine == "FastR")) { FALSE } else { { f<-function(y) { x<-y; xi1<-.fastr.identity(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 }; f(c(1,2)) } }
 [1] FALSE
 
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { { f<-function(x) { xi1<-.fastr.identity(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 }; f(c(1,2)) } }
+#if (!any(R.version$engine == "FastR")) { TRUE } else { { f<-function(x) { xi1<-.fastr.identity(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 }; f(c(1,2)) } }
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { x }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
+#if (!any(R.version$engine == "FastR")) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { x }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
 [1] TRUE
 
 ##com.oracle.truffle.r.test.library.fastr.TestStateTrans.testTransitions#
-#if (length(grep("FastR", R.Version()$version.string)) != 1) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { y<-x; y }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
+#if (!any(R.version$engine == "FastR")) { TRUE } else { { x<-rep(1, 100); xi1<-.fastr.identity(x); f<-function(x) { y<-x; y }; f(x); x[1]<-7; xi2<-.fastr.identity(x); xi1 == xi2 } }
 [1] TRUE
 
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); 3 * (unit(1, 'mm')); }
+[1] 3*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); grid:::unit.list(3 * unit(1, 'mm')); }
+[1] 3*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); unit.c(unit(1,'mm'), 42*unit(1,'mm')); }
+[1] 1mm    42*1mm
+
+##com.oracle.truffle.r.test.library.grid.TestGridPackage.testUnits#
+#{ library(grid); unit.c(unit(1,'mm'), unit(1,'mm')) }
+[1] 1mm 1mm
+
 ##com.oracle.truffle.r.test.library.methods.TestSubstituteDirect.basicTests#
 #a<-substituteDirect(quote(x+1), NA); a
 Error in substituteDirect(quote(x + 1), NA) :
@@ -138254,6 +148022,27 @@ Error: argument 'files' must be character
 #.Call(tools:::Rmd5, c("abc","xyz"))
 [1] NA NA
 
+##com.oracle.truffle.r.test.library.stats.TestExternal_completecases.testCompleteCases#
+#stats::complete.cases(data.frame(col1=c(1,2,NA), col2=c(1,2,3)))
+[1]  TRUE  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.stats.TestExternal_completecases.testCompleteCases#
+#stats::complete.cases(data.frame(col1=c(1,2,NA), col2=c(1,2,3)), c(1,NA,2))
+[1]  TRUE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.stats.TestExternal_completecases.testCompleteCases#
+#stats::complete.cases(data.frame(col1=c(1,2,NA), col2=c(1,2,3)), data.frame(col1=c(1,NA,3), col2=c(1,2,3)))
+[1]  TRUE FALSE FALSE
+
+##com.oracle.truffle.r.test.library.stats.TestExternal_completecases.testCompleteCases#
+#stats::complete.cases(data.frame(col1=c(1,NA), col2=c(2,3)), matrix(c(1,NA,2,NA), nrow=2))
+[1]  TRUE FALSE
+
+##com.oracle.truffle.r.test.library.stats.TestExternal_completecases.testCompleteCasesArgsValidation#Output.IgnoreErrorContext#
+#stats::complete.cases(data.frame(col1=c(1,2,NA), col2=c(1,2,3)), list(NA,2,2))
+Error in stats::complete.cases(data.frame(col1 = c(1, 2, NA), col2 = c(1,  :
+  not all arguments have the same length
+
 ##com.oracle.truffle.r.test.library.stats.TestExternal_covcor.testCovcor#
 #.Call(stats:::C_cov, 1:5, 1:5, 4, FALSE)
 [1] 2.5
@@ -144784,6 +154573,26 @@ x + x ~ y + log(y)
 #update.formula(x ~ y, ~ . + x2)
 x ~ y + x2
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testBrowser#
+#browser()<<<NEWLINE>>>where<<<NEWLINE>>>c<<<NEWLINE>>>
+Called from: top level
+
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testBrowser#
+#do.call('browser', list())<<<NEWLINE>>>c<<<NEWLINE>>>
+Called from: do.call("browser", list())
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testBrowser#
+#foo <- function() { stop('error msg') }; tryCatch(foo(), error=browser)<<<NEWLINE>>>print(msg)<<<NEWLINE>>>c<<<NEWLINE>>>
+Called from: tryCatchOne(expr, names, parentenv, handlers[[1L]])
+[1] "error msg"
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testBrowser#
+#options(error=browser); prod('a')<<<NEWLINE>>>where<<<NEWLINE>>>c<<<NEWLINE>>>
+Error in prod("a") : invalid 'type' (character) of argument
+Called from: top level
+
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testConditionalBreakpoint#
 #fun <- function(x) { cat('x='); cat(x); cat('\n') }; trace(fun, quote(if (x > 10) browser())); fun(10)<<<NEWLINE>>>; fun(11)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
 [1] "fun"
@@ -144998,6 +154807,72 @@ debug at #1: cat(x)
 
 exiting from: fun(3)
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSetBreakpoint#Output.IgnoreDebugCallString#Output.IgnoreDebugPath#
+#source('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r'); setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F); fun(10)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debug.r#4
+Called from: fun(10)
+debug: print("Hello")
+[1] "Hello"
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: for (i in seq(3)) print(i)
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 1
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 2
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 3
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#6: bar("World")
+[1] "World"
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#7: print(x)
+[1] 10
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSetBreakpoint#Output.IgnoreDebugCallString#Output.IgnoreDebugPath#
+#source('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r'); setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F); fun(10)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F, clear=T); fun(10)<<<NEWLINE>>>setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F); invisible(fun(10))<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
+debug.r#4
+Called from: fun(10)
+debug: print("Hello")
+[1] "Hello"
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: for (i in seq(3)) print(i)
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 1
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 2
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 3
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#6: bar("World")
+[1] "World"
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#7: print(x)
+[1] 10
+[1] "Hello"
+[1] 1
+[1] 2
+[1] 3
+[1] "World"
+[1] 10
+debug.r#4
+Called from: fun(10)
+debug: print("Hello")
+[1] "Hello"
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: for (i in seq(3)) print(i)
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 1
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 2
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#5: print(i)
+[1] 3
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#6: bar("World")
+[1] "World"
+debug at tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r#7: print(x)
+[1] 10
+
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSetBreakpoint#
+#source('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r'); setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F); setBreakpoint('tmptest/com.oracle.truffle.r.test.library.utils.rsrc/debug.r', 4, verbose=F, clear=T); fun(10)<<<NEWLINE>>>
+[1] "Hello"
+[1] 1
+[1] 2
+[1] 3
+[1] "World"
+[1] 10
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSimple#
 #f <- function(x) {<<<NEWLINE>>>  t <- x + 1<<<NEWLINE>>>  print(t)<<<NEWLINE>>>  t}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>t<<<NEWLINE>>>n<<<NEWLINE>>>n
 debugging in: f(5)
@@ -145015,6 +154890,39 @@ debug at #4: t
 exiting from: f(5)
 [1] 6
 
+##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testSimple#
+#f <- function(x) {<<<NEWLINE>>>  t <- x + 1<<<NEWLINE>>>  print(t)<<<NEWLINE>>>  t}<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>t<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>undebug(f)<<<NEWLINE>>>f(3)<<<NEWLINE>>>debug(f)<<<NEWLINE>>>f(5)<<<NEWLINE>>>x<<<NEWLINE>>>n<<<NEWLINE>>>n<<<NEWLINE>>>t<<<NEWLINE>>>n<<<NEWLINE>>>n
+debugging in: f(5)
+debug at #1: {
+    t <- x + 1
+    print(t)
+    t
+}
+[1] 5
+debug at #2: t <- x + 1
+debug at #3: print(t)
+[1] 6
+[1] 6
+debug at #4: t
+exiting from: f(5)
+[1] 6
+[1] 4
+[1] 4
+debugging in: f(5)
+debug at #1: {
+    t <- x + 1
+    print(t)
+    t
+}
+[1] 5
+debug at #2: t <- x + 1
+debug at #3: print(t)
+[1] 6
+[1] 6
+debug at #4: t
+exiting from: f(5)
+[1] 6
+
 ##com.oracle.truffle.r.test.library.utils.TestInteractiveDebug.testStepInto#
 #bar <- function(x) { cat(x); cat('\n') }; foo <- function(x) { cat('foo entry\n'); bar(x); cat('foo exit\n') }; debug(foo); foo(3)<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>s<<<NEWLINE>>>n<<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>><<<NEWLINE>>>
 debugging in: foo(3)
@@ -145622,6 +155530,18 @@ see '?methods' for accessing help and source code
 "","double","bool","raw"
 "1",1231231234.5,TRUE,2a
 
+##com.oracle.truffle.r.test.parser.TestParser.testDotIdentifiers#
+#{ .. <- 42; cat(..); }
+42
+##com.oracle.truffle.r.test.parser.TestParser.testDotIdentifiers#
+#{ .... <- 42; cat(....); }
+42
+##com.oracle.truffle.r.test.parser.TestParser.testDotIdentifiers#
+#{ ...... <- 42; cat(......); }
+42
+##com.oracle.truffle.r.test.parser.TestParser.testDotIdentifiers#
+#{ ....x <- 42; cat(....x); }
+42
 ##com.oracle.truffle.r.test.parser.TestParser.testDoubleLiterals#
 #0x0p0
 [1] 0
@@ -145976,6 +155896,12 @@ non-integer value 12345678909876543212L qualified with L; using numeric value
 #'\ ' == ' '
 [1] TRUE
 
+##com.oracle.truffle.r.test.rffi.TestUserRNG.testUserRNG#
+#{ dyn.load("tmptest/userrng/liburand.so"); RNGkind("user"); print(RNGkind()); set.seed(4567); runif(10) }
+[1] "user-supplied" "Inversion"
+ [1] 0.45336386 0.38848030 0.94576608 0.11726267 0.21542351 0.08672997
+ [7] 0.35201276 0.16919220 0.93579263 0.26084486
+
 ##com.oracle.truffle.r.test.rng.TestRRNG.testDirectReadingSeed#
 #invisible(runif(1)); length(.Random.seed)
 [1] 626
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/RTestSuite.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/RTestSuite.java
index f9067c10c5ad2f4de22420b281041415245b60d7..3fa91322e291db86e95b767da9a89077dc628952 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/RTestSuite.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/RTestSuite.java
@@ -9,7 +9,7 @@ import java.security.Permission;
 import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.oracle.truffle.r.engine.shell.RscriptCommand;
+import com.oracle.truffle.r.launcher.RscriptCommand;
 
 /**
  * This class runs FastR on every R file it can find in given directories (it will search
@@ -48,7 +48,7 @@ public final class RTestSuite {
                             try {
                                 expected = String.join("\n", Files.readAllLines(Paths.get(file.toString().replaceFirst("\\.[Rr]", ".out"))));
                                 try {
-                                    RscriptCommand.doMain(new String[]{file.toString()}, null, true, System.in, new PrintStream(baos));
+                                    RscriptCommand.doMain(new String[]{file.toString()}, null, System.in, new PrintStream(baos), System.err);
                                     // Unreachable code from here, because main will try to exit
                                     // which will cause a SecurityException
                                 } catch (SecurityException e) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
index 9d31793e24abbdffa899fb287f84ec254eac9c4a..650fb03db0860ee18a8e074044891c0b9b4e0fd1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestR5.java
@@ -79,7 +79,9 @@ public class TestR5 extends TestBase {
         assertSuppress("{ clazz <- setRefClass('Foo15R5', fields = c('a'), methods = list(initialize = function() { a <<- 123 })); obj <- clazz$new(); obj$a }");
         assertSuppress("{ setRefClass('A6R5', fields = c('a'), methods = list(initialize = function() { a <<- 'hello' })); clazz <- setRefClass('B6R5', fields = c('a'), contains = 'A6R5'); obj <- clazz$new(); obj$a }");
 
-        assertEval(Ignored.Unknown,
+        // FIXME FastR memory statistics missing completely (NA)
+        // Assuming that they should be provided so ImplementationError.
+        assertEval(Ignored.ImplementationError,
                         "{ clazz <- setRefClass('Foo18R5', fields = c('a'), methods = list(initialize = function() a <<- 456, finalize = function() { print(sprintf('finalizer: %d', a)) } )); (function () { x <- clazz$new(); print('fun') })(); gc() }");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
index a69b6a84e1360650ad23ec0f8c6f9a05431139e5..b630e01446c155639e57b5e5b8018fdbe1b01c9b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/S4/TestS4.java
@@ -165,11 +165,21 @@ public class TestS4 extends TestRBase {
         assertEval(".Internal(bindingIsActive(as.name('someSymbol4'), .GlobalEnv))");
         assertEval("someSymbol5 <- 0; lockBinding('someSymbol5', .GlobalEnv); makeActiveBinding('someSymbol5', function(x) { x }, .GlobalEnv)");
         assertEval("makeActiveBinding('someSymbol6', function(x) { x }, .GlobalEnv); lockBinding('someSymbol6', .GlobalEnv); makeActiveBinding('someSymbol6', function(x) { print('hello') }, .GlobalEnv)");
-        assertEval(Ignored.Unknown,
+        // FIXME
+        // Expected output: [1] "get0"
+        // [1] "set0"
+        // [1] "get1"
+        // [1] "set1"
+        // FastR output: [1] "get0"
+        // [1] "get0"
+        // [1] "set0"
+        // [1] "get1"
+        // [1] "get1"
+        // [1] "set1"
+        assertEval(Ignored.ImplementationError,
                         "makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get0') else print('set0') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1; makeActiveBinding('someSymbol7', function(x) { if(missing(x)) print('get1') else print('set1') }, .GlobalEnv); someSymbol7; someSymbol7 <- 1");
         assertEval("makeActiveBinding('someSymbol8', function(x) { print('hello') }, .GlobalEnv); someSymbol9 <- 'world'; print(someSymbol8); print(someSymbol9)");
         assertEval("makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get0') else print('set0'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1; makeActiveBinding('someSymbol10', function(x) { if(missing(x)) print('get1') else print('set1'); NULL }, .GlobalEnv); someSymbol10; someSymbol10 <- 1");
         assertEval("makeActiveBinding('var_a', function(x) { if(missing(x)) { print('get'); return(123) } else { print('set'); return(x) } }, .GlobalEnv); inherits(var_a, 'numeric')");
     }
-
 }
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 e52b7226f056a3623ab659264c67f766e4ef41a5..5e5b5104e24c3488e46b0cda06d6849aa26ff80e 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
@@ -12,8 +12,10 @@ package com.oracle.truffle.r.test;
 
 import static org.junit.Assert.fail;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
+import java.io.StringReader;
 import java.net.URL;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
@@ -29,6 +31,7 @@ import java.util.Map.Entry;
 import java.util.SortedMap;
 import java.util.TreeMap;
 import java.util.TreeSet;
+import java.util.function.Predicate;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -40,10 +43,11 @@ import org.junit.runner.Description;
 import org.junit.runner.Result;
 
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.ResourceHandlerFactory;
 import com.oracle.truffle.r.runtime.Utils;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.ChildContextInfo;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.test.generate.FastRSession;
@@ -64,6 +68,13 @@ import com.oracle.truffle.r.test.generate.TestOutputManager;
 public class TestBase {
 
     public static final boolean ProcessFailedTests = Boolean.getBoolean("ProcessFailedTests");
+
+    static {
+        if (ProcessFailedTests) {
+            System.out.println("Re-trying failed unit tests (ProcessFailedTests=true)");
+        }
+    }
+
     /**
      * When {@link #ProcessFailedTests} is set to true this flag further limits the tests executed
      * to those with {@link Ignored#Unknown} flag.
@@ -91,7 +102,8 @@ public class TestBase {
         IgnoreWhitespace, // removes all whitespace from the whole output
         IgnoreCase, // ignores upper/lower case differences
         IgnoreDebugPath, // ignores <path> in debug output like "debug at <path> #..."
-        IgnoreDebugDepth; // ignores call depth printed by the debugger ("Browse[<call depth>]")
+        IgnoreDebugDepth, // ignores call depth printed by the debugger ("Browse[<call depth>]")
+        IgnoreDebugCallString; // ignores the caller string like "debugging in:" or "Called from:"
 
         @Override
         public String getName() {
@@ -139,8 +151,7 @@ public class TestBase {
     }
 
     /**
-     * Instantiated by the mx {@code JUnit} wrapper. The arguments are passed in the constructor and
-     * must be a comma-separated list of strings, i.e.:
+     * Instantiated by the mx {@code JUnit} wrapper. The arguments are passed as system properties
      * <ul>
      * <li>{@code expected=dir}: path to dir containing expected output file to be
      * read/generated/updated</li>
@@ -158,70 +169,52 @@ public class TestBase {
 
         private static File diffsOutputFile;
 
-        private static final String GEN_EXPECTED = "gen-expected";
-        private static final String GEN_EXPECTED_QUIET = "gen-expected-quiet";
-        private static final String CHECK_EXPECTED = "check-expected";
-        private static final String EXPECTED = "expected=";
-        private static final String GEN_FASTR = "gen-fastr=";
-        private static final String GEN_DIFFS = "gen-diff=";
-        private static final String KEEP_TRAILING_WHITESPACE = "keep-trailing-whitespace";
-        private static final String TRACE_TESTS = "trace-tests";
-        private static final String TEST_METHODS = "test-methods=";
-        /**
-         * The dir where 'mx' puts the output from building this project.
-         */
-        private static final String TEST_PROJECT_OUTPUT_DIR = "test-project-output-dir=";
+        private static final String PROP_BASE = "fastr.test.";
 
-        private final String arg;
+        private enum Props {
+            GEN_EXPECTED("gen.expected"),
+            GEN_EXPECTED_QUIET("gen.expected.quiet"),
+            CHECK_EXPECTED("check.expected"),
+            TRACE_TESTS("trace.tests"),
+            KEEP_TRAILING_WHITESPACE("keep.trailing.whitespace");
 
-        /**
-         * Constructor with customization arguments.
-         */
-        public RunListener(String arg) {
-            this.arg = arg;
+            private final String propSuffix;
+
+            Props(String propSuffix) {
+                this.propSuffix = propSuffix;
+            }
+        }
+
+        private static String getProperty(String baseName) {
+            String propName = PROP_BASE + baseName;
+            String val = System.getProperty(propName);
+            return val;
+        }
+
+        public static boolean getBooleanProperty(String baseName) {
+            String val = getProperty(baseName);
+            return val != null && (val.length() == 0 || val.equals("true"));
         }
 
         @Override
         public void testRunStarted(Description description) {
             try {
-                File expectedOutputFile = null;
                 File fastROutputFile = null;
                 boolean checkExpected = false;
-                boolean genExpected = false;
-                boolean genExpectedQuiet = false;
-                if (arg != null) {
-                    String[] args = arg.split(",");
-                    for (String directive : args) {
-                        if (directive.startsWith(EXPECTED)) {
-                            expectedOutputFile = new File(new File(directive.replace(EXPECTED, "")), TestOutputManager.TEST_EXPECTED_OUTPUT_FILE);
-                        } else if (directive.startsWith(GEN_FASTR)) {
-                            fastROutputFile = new File(new File(directive.replace(GEN_FASTR, "")), TestOutputManager.TEST_FASTR_OUTPUT_FILE);
-                        } else if (directive.startsWith(GEN_DIFFS)) {
-                            diffsOutputFile = new File(new File(directive.replace(GEN_DIFFS, "")), TestOutputManager.TEST_DIFF_OUTPUT_FILE);
-                        } else if (directive.equals(GEN_EXPECTED)) {
-                            genExpected = true;
-                        } else if (directive.equals(GEN_EXPECTED_QUIET)) {
-                            genExpectedQuiet = true;
-                        } else if (directive.equals(CHECK_EXPECTED)) {
-                            checkExpected = true;
-                        } else if (directive.equals(KEEP_TRAILING_WHITESPACE)) {
-                            keepTrailingWhiteSpace = true;
-                        } else if (directive.equals(TRACE_TESTS)) {
-                            traceTests = true;
-                        } else if (directive.startsWith(TEST_PROJECT_OUTPUT_DIR)) {
-                            testProjectOutputDir = Paths.get(directive.replace(TEST_PROJECT_OUTPUT_DIR, ""));
-                        } else if (directive.equals(TEST_METHODS)) {
-                            testMethodsPattern = directive.replace(TEST_METHODS, "");
-                        } else {
-                            throw new RuntimeException("RunListener arg: " + arg + " invalid");
-                        }
-                    }
-                }
-                if (genExpected) {
-                    System.setProperty("GenerateExpectedOutput", "true");
+                String genExpected = getProperty(Props.GEN_EXPECTED.propSuffix);
+                boolean genExpectedQuiet = getBooleanProperty(Props.GEN_EXPECTED_QUIET.propSuffix);
+                checkExpected = getBooleanProperty(Props.CHECK_EXPECTED.propSuffix);
+                if (genExpected != null) {
+                    File expectedOutputFile = new File(new File(genExpected), TestOutputManager.TEST_EXPECTED_OUTPUT_FILE);
+                    expectedOutputManager = new ExpectedTestOutputManager(expectedOutputFile, true, checkExpected, genExpectedQuiet);
+                } else {
+                    // read from jar
+                    URL expectedTestOutputURL = ResourceHandlerFactory.getHandler().getResource(TestBase.class, TestOutputManager.TEST_EXPECTED_OUTPUT_FILE);
+                    expectedOutputManager = new ExpectedTestOutputManager(expectedTestOutputURL, false, checkExpected, genExpectedQuiet);
+                    System.console();
                 }
-                expectedOutputManager = new ExpectedTestOutputManager(expectedOutputFile, genExpected, checkExpected, genExpectedQuiet);
                 fastROutputManager = new FastRTestOutputManager(fastROutputFile);
+                traceTests = getBooleanProperty(Props.TRACE_TESTS.propSuffix);
                 addOutputHook();
             } catch (Throwable ex) {
                 throw new AssertionError("R initialization failure", ex);
@@ -231,6 +224,7 @@ public class TestBase {
         @Override
         public void testRunFinished(Result result) {
             try {
+                deleteDir(Paths.get(TEST_OUTPUT));
                 if (expectedOutputManager.generate) {
                     boolean updated = expectedOutputManager.writeTestOutputFile();
                     if (updated) {
@@ -343,7 +337,20 @@ public class TestBase {
             }
         }
 
-        void createRSession() {
+        protected ExpectedTestOutputManager(URL urlOutput, boolean generate, boolean checkOnly, boolean genExpectedQuiet) throws IOException {
+            super(urlOutput);
+            this.checkOnly = checkOnly;
+            this.generate = generate;
+            if (genExpectedQuiet) {
+                localDiagnosticHandler.setQuiet();
+            }
+            oldExpectedOutputFileContent = readTestOutputFile();
+            if (generate) {
+                createRSession();
+            }
+        }
+
+        private void createRSession() {
             if (!haveRSession) {
                 setRSession(new GnuROneShotRSession());
                 haveRSession = true;
@@ -361,6 +368,9 @@ public class TestBase {
         FastRTestOutputManager(File outputFile) {
             super(outputFile);
             setRSessionName("FastR");
+            // no point in printing errors to file when running tests (that contain errors on
+            // purpose)
+            FastROptions.setValue("PrintErrorStacktracesToFile", false);
             fastRSession = FastRSession.create();
         }
     }
@@ -429,8 +439,6 @@ public class TestBase {
      */
     private static boolean traceTests;
 
-    private static Path testProjectOutputDir;
-
     protected static final String ERROR = "Error";
     protected static final String WARNING = "Warning message";
 
@@ -484,12 +492,16 @@ public class TestBase {
         return evalAndCompare(getAssertEvalFastR(gnuROutput, input), trait1);
     }
 
+    protected boolean assertEvalFastR(TestTrait trait1, TestTrait trait2, String input, String gnuROutput) {
+        return evalAndCompare(getAssertEvalFastR(gnuROutput, input), trait1, trait2);
+    }
+
     protected boolean assertEvalFastR(String input, String gnuROutput) {
         return evalAndCompare(getAssertEvalFastR(gnuROutput, input));
     }
 
     private static String[] getAssertEvalFastR(String gnuROutput, String input) {
-        return new String[]{"if (length(grep(\"FastR\", R.Version()$version.string)) != 1) { " + gnuROutput + " } else { " + input + " }"};
+        return new String[]{"if (!any(R.version$engine == \"FastR\")) { " + gnuROutput + " } else { " + input + " }"};
     }
 
     /*
@@ -517,11 +529,7 @@ public class TestBase {
         return cwd;
     }
 
-    public static void setTestProjectOutputDir(String path) {
-        testProjectOutputDir = Paths.get(path);
-    }
-
-    private static final String TEST_OUTPUT = "tmptest";
+    protected static final String TEST_OUTPUT = "tmptest";
 
     /**
      * Return a path that is relative to the 'cwd/testoutput' when running tests.
@@ -544,24 +552,6 @@ public class TestBase {
         return relativize(dir);
     }
 
-    private static final String TEST_PROJECT = "com.oracle.truffle.r.test";
-    private static final String TEST_NATIVE_PROJECT = "com.oracle.truffle.r.test.native";
-
-    /**
-     * Returns a path to {@code baseName}, assumed to be nested in {@link #testProjectOutputDir}.
-     * The path is return relativized to the cwd.
-     */
-    public static Path getProjectFile(Path baseName) {
-        Path baseNamePath = Paths.get(TEST_PROJECT.replace('.', '/'), baseName.toString());
-        Path result = relativize(testProjectOutputDir.resolve(baseNamePath));
-        return result;
-    }
-
-    public static Path getNativeProjectFile(Path baseName) {
-        Path path = Paths.get(TEST_NATIVE_PROJECT, baseName.toString());
-        return path;
-    }
-
     private static void microTestFailed() {
         if (!ProcessFailedTests || ShowFailedTestsResults) {
             System.err.printf("%nMicro-test failure: %s%n", getTestContext());
@@ -621,29 +611,33 @@ public class TestBase {
         }
 
         String preprocessOutput(String out) {
+            String s = out;
             if (output.contains(Output.IgnoreWhitespace)) {
-                return out.replaceAll("\\s+", "");
+                return s.replaceAll("\\s+", "");
             }
             if (output.contains(Output.IgnoreCase)) {
-                return out.toLowerCase();
+                return s.toLowerCase();
             }
             if (output.contains(Output.ContainsReferences)) {
-                return convertReferencesInOutput(out);
+                return convertReferencesInOutput(s);
             }
             if (output.contains(Output.IgnoreDebugPath)) {
-                return convertDebugOutput(out);
+                s = convertDebugOutput(s);
             }
             if (output.contains(Output.IgnoreDebugDepth)) {
-                return removeDebugCallDepth(out);
+                s = removeDebugCallDepth(s);
             }
-            return out;
+            if (output.contains(Output.IgnoreDebugCallString)) {
+                s = removeDebugCallString(s);
+            }
+            return s;
         }
     }
 
     private boolean evalAndCompare(String[] inputs, TestTrait... traitsList) {
         WhiteList[] whiteLists = TestTrait.collect(traitsList, WhiteList.class);
         TestTraitsSet traits = new TestTraitsSet(traitsList);
-        ContextInfo contextInfo = traits.context.contains(Context.NonShared) ? fastROutputManager.fastRSession.createContextInfo(ContextKind.SHARE_NOTHING) : null;
+        ChildContextInfo contextInfo = traits.context.contains(Context.NonShared) ? fastROutputManager.fastRSession.createContextInfo(ContextKind.SHARE_NOTHING) : null;
         int index = 1;
         boolean allOk = true;
         boolean skipFastREval = traits.isIgnored || generatingExpected();
@@ -677,6 +671,54 @@ public class TestBase {
                 } else {
                     failedInputCount++;
                     microTestFailed();
+                    if (!ProcessFailedTests || ShowFailedTestsResults) {
+                        // Show hint where first diff occurs - use preprocessed text
+                        int len = Math.min(checkResult.expected.length(), checkResult.result.length());
+                        int line = 0;
+                        int col = 0;
+                        for (int i = 0; i < len; i++) {
+                            char c = checkResult.expected.charAt(i);
+                            if (c != checkResult.result.charAt(i)) {
+                                StringBuilder sb = new StringBuilder(64);
+                                sb.append("index=").append(i).append('[').append(line + 1).append(':').append(col + 1).append("] \"");
+                                int dLen = Math.min(i + 20, len);
+                                for (int j = i; j < dLen; j++) {
+                                    char ch = checkResult.expected.charAt(j);
+                                    switch (ch) {
+                                        case '\n':
+                                            sb.append("\\n");
+                                            break;
+                                        case '\r':
+                                            sb.append("\\r");
+                                            break;
+                                        case '\t':
+                                            sb.append("\\t");
+                                            break;
+                                        case '\b':
+                                            sb.append("\\b");
+                                            break;
+                                        case '\f':
+                                            sb.append("\\f");
+                                            break;
+                                        default:
+                                            sb.append(ch);
+                                    }
+                                }
+                                if (dLen < len) {
+                                    sb.append("...");
+                                }
+                                sb.append('"');
+                                System.err.printf("%16s %s%n", "Prepr.text diff:", sb);
+                                break;
+                            }
+                            col++;
+                            if (c == '\n') {
+                                line++;
+                                col = 0;
+                            }
+                        }
+                    }
+
                     if (inputs.length > 1) {
                         System.out.print('E');
                     }
@@ -779,6 +821,10 @@ public class TestBase {
         return removeAllOccurrencesBetween(out, prefix, prefix.length(), "]", 0);
     }
 
+    private static String removeDebugCallString(String out) {
+        return removeLines(out, line -> line.startsWith("debugging in:") || line.startsWith("Called from:"));
+    }
+
     private static String removeAllOccurrencesBetween(String out, String prefix, int prefixOffset, String suffix, int suffixOffset) {
         StringBuilder sb = new StringBuilder(out);
 
@@ -792,6 +838,28 @@ public class TestBase {
         return sb.toString();
     }
 
+    /**
+     * Removes the lines from the test output string matching the provided predicate.
+     */
+    private static String removeLines(String out, Predicate<String> pred) {
+        StringBuilder sb = new StringBuilder();
+
+        BufferedReader r = new BufferedReader(new StringReader(out));
+        String line;
+        try {
+            while ((line = r.readLine()) != null) {
+                if (!pred.test(line)) {
+                    sb.append(line);
+                    sb.append(System.lineSeparator());
+                }
+            }
+        } catch (IOException e) {
+            // won't happen
+        }
+
+        return sb.toString();
+    }
+
     private boolean searchWhiteLists(WhiteList[] whiteLists, String input, String expected, String result, TestTraitsSet testTraits) {
         if (whiteLists == null) {
             return false;
@@ -911,7 +979,7 @@ public class TestBase {
      * Evaluate {@code input} in FastR, returning all (virtual) console output that was produced. If
      * {@code nonShared} then this must evaluate in a new, non-shared, {@link RContext}.
      */
-    protected String fastREval(String input, ContextInfo contextInfo, boolean longTimeout) {
+    protected String fastREval(String input, ChildContextInfo contextInfo, boolean longTimeout) {
         microTestInfo.expression = input;
         String result;
         try {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestRBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestRBase.java
index 6d4317791a4276e61b257c0661251ce5059fe22a..960eff3d5d53a688ad1626bf0f1d7f9a8b5794a8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestRBase.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestRBase.java
@@ -22,17 +22,17 @@
  */
 package com.oracle.truffle.r.test;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
 import java.io.IOException;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Map.Entry;
 
-import org.junit.Assert;
 import org.junit.Test;
 
+import com.oracle.truffle.r.runtime.ResourceHandlerFactory;
+
 /**
  * Base class for all Java test suites (in the sense of JUnit Java files) that want to run R tests
  * stored in the file system as R sources. It is expected that R test source files will be stored in
@@ -60,54 +60,45 @@ public class TestRBase extends TestBase {
         if (testDirName == null) {
             return;
         }
-        Path testDirPath = TestBase.getProjectFile(Paths.get(testDirName, "R"));
-        if (!Files.exists(testDirPath) || !Files.isDirectory(testDirPath)) {
-            return;
-        }
-        File testDir = testDirPath.toFile();
-        File[] files = testDir.listFiles((dir, name) -> name.endsWith(".R"));
-        if (files == null) {
-            return;
-        }
-        for (int i = 0; i < files.length; i++) {
-            explicitTestContext = testDirName + "/R/" + files[i].getName();
-            try {
-                BufferedReader bf = new BufferedReader(new FileReader(files[i]));
-                TestTrait testTrait = null;
-                String l = bf.readLine();
-                if (l != null) {
-                    l = l.trim();
-                    if (l.startsWith("#")) {
-                        // check the first line for configuration options
-                        if (l.contains("IgnoreErrorContext")) {
-                            testTrait = Output.IgnoreErrorContext;
-                        } else if (l.contains("IgnoreWarningContext")) {
-                            testTrait = Output.IgnoreWarningContext;
-                        } else if (l.contains("Ignored")) {
-                            for (Ignored ignoredType : Ignored.values()) {
-                                if (l.contains("Ignored." + ignoredType.name())) {
-                                    testTrait = ignoredType;
-                                    break;
-                                }
-                            }
-                            if (testTrait == null) {
-                                testTrait = Ignored.Unknown; // Retain old way for compatibility
-                            }
+        Map<String, String> rFiles = ResourceHandlerFactory.getHandler().getRFiles(this.getClass(), testDirName);
+        for (Entry<String, String> entry : rFiles.entrySet()) {
+            String entryName = entry.getKey();
+            String entryValue = entry.getValue();
+            explicitTestContext = entryName;
+            String[] lines = entryValue.split("\n");
+            String l = lines[0].trim();
+            TestTrait testTrait = null;
+            if (l.startsWith("#")) {
+                // check the first line for configuration options
+                if (l.contains("IgnoreErrorContext")) {
+                    testTrait = Output.IgnoreErrorContext;
+                } else if (l.contains("IgnoreWarningContext")) {
+                    testTrait = Output.IgnoreWarningContext;
+                } else if (l.contains("Ignored")) {
+                    for (Ignored ignoredType : Ignored.values()) {
+                        if (l.contains("Ignored." + ignoredType.name())) {
+                            testTrait = ignoredType;
+                            break;
                         }
                     }
+                    if (testTrait == null) {
+                        testTrait = Ignored.Unknown; // Retain old way for compatibility
+                    }
                 }
-                bf.close();
-                String testFilePath = testDirPath.resolve(files[i].getName()).toString();
+            }
+            try {
+                Path dir = TestBase.createTestDir(getTestDir());
+                Path p = dir.resolve(Paths.get(entryName).getFileName());
+                Files.write(p, entryValue.getBytes());
                 if (testTrait == null) {
-                    assertEval(TestBase.template("{ source(\"%0\") }", new String[]{testFilePath}));
+                    assertEval(TestBase.template("{ source(\"%0\") }", new String[]{p.toString()}));
                 } else {
-                    assertEval(testTrait, TestBase.template("{ source(\"%0\") }", new String[]{testFilePath}));
+                    assertEval(testTrait, TestBase.template("{ source(\"%0\") }", new String[]{p.toString()}));
                 }
-            } catch (IOException x) {
-                Assert.fail("error reading: " + files[i].getPath() + ": " + x);
-            } finally {
-                explicitTestContext = null;
+            } catch (IOException ex) {
+                assert false;
             }
+            explicitTestContext = null;
         }
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encoding.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encoding.java
index 2fd0304038b7ca57b8c5b2797348b8fdc49f3451..96e43c8408c884fbe645d7b73977e3196f6c0bc5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encoding.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Encoding.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.
  */
@@ -24,18 +24,27 @@ public class TestBuiltin_Encoding extends TestBase {
 
     @Test
     public void testEncoding2() {
-        assertEval(Ignored.Unknown,
+        // FIXME GnuR outputs "unknown" for each vector member while FastR just one:
+        // FastR output: [1] "unknown"
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(c('\\n', '\\n', '## These cannot be run by examples() but should be OK when pasted\\n', '## into an interactive R session with the tcltk package loaded\\n', '\\n', 'tt <- tktoplevel()\\n', 'tkpack(txt.w <- tktext(tt))\\n', 'tkinsert(txt.w, \\\'0.0\\\', \\\'plot(1:10)\\\')\\n', '\\n', '# callback function\\n', 'eval.txt <- function()\\n', '   eval(parse(text = tclvalue(tkget(txt.w, \\\'0.0\\\', \\\'end\\\'))))\\n', 'tkpack(but.w <- tkbutton(tt, text = \\\'Submit\\\', command = eval.txt))\\n', '\\n', '## Try pressing the button, edit the text and when finished:\\n', '\\n', 'tkdestroy(tt)\\n', '\\n', '\\n')); .Internal(Encoding(argv[[1]]))");
     }
 
     @Test
     public void testEncoding3() {
-        assertEval(Ignored.Unknown, "argv <- list('detaching ‘package:nlme’, ‘package:splines’'); .Internal(Encoding(argv[[1]]))");
+        // FIXME character '‘' causes the string to become "UTF-8" so we should
+        // probably adhere to this too thus marking ImplementationError for now
+        // Expected output: [1] "UTF-8"
+        // FastR output: [1] "unknown"
+        assertEval(Ignored.ImplementationError, "argv <- list('detaching ‘package:nlme’, ‘package:splines’'); .Internal(Encoding(argv[[1]]))");
     }
 
     @Test
     public void testEncoding4() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(character(0), class = 'check_code_usage_in_package')); .Internal(Encoding(argv[[1]]))");
+        // FastR result seems better thus ReferenceError for now
+        // Expected output: character(0)
+        // FastR output: [1] "unknown"
+        assertEval(Ignored.ReferenceError, "argv <- list(structure(character(0), class = 'check_code_usage_in_package')); .Internal(Encoding(argv[[1]]))");
     }
 
     @Test
@@ -50,7 +59,9 @@ public class TestBuiltin_Encoding extends TestBase {
 
     @Test
     public void testEncoding7() {
-        assertEval(Ignored.Unknown,
+        // FIXME GnuR outputs "unknown" for each vector member while FastR just one:
+        // FastR output: [1] "unknown"
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(c('* Edit the help file skeletons in man, possibly combining help files for multiple functions.', '* Edit the exports in NAMESPACE, and add necessary imports.', '* Put any C/C++/Fortran code in src.', '* If you have compiled code, add a useDynLib() directive to NAMESPACE.', '* Run R CMD build to build the package tarball.', '* Run R CMD check to check the package tarball.', '', 'Read Writing R Extensions for more information.')); .Internal(Encoding(argv[[1]]))");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
index b13bdb9886e1b09b9c39a647adc4201f454448ee..ea840a2bb0074a1745fff06298b73d4da4ce7ea1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java
@@ -19,18 +19,19 @@ public class TestBuiltin_Syssetlocale extends TestBase {
 
     @Test
     public void testSyssetlocale1() {
-        assertEval("argv <- list(3L, 'C'); .Internal(Sys.setlocale(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(3L, 'C'); Sys.setlocale(argv[[1]], argv[[2]])");
     }
 
     @Test
     public void testSyssetlocale3() {
         assertEval("argv <- structure(list(category = 'LC_TIME', locale = 'C'), .Names = c('category',     'locale'));do.call('Sys.setlocale', argv)");
+        assertEval("{ Sys.setenv(LC_CTYPE=\"en_US.UTF-8\"); Sys.getlocale(\"LC_CTYPE\"); }");
     }
 
     @Test
     public void testSyssetlocaleInvalidArgs() {
-        assertEval(".Internal(Sys.setlocale(4, c('more', 'elements')))");
-        assertEval(".Internal(Sys.setlocale(4, 42))");
-        assertEval(Output.IgnoreErrorMessage, ".Internal(Sys.setlocale('3L', 'C'))");
+        assertEval("Sys.setlocale(4, c('more', 'elements'))");
+        assertEval("Sys.setlocale(4, 42)");
+        assertEval("Sys.setlocale('3L', 'C')");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
index c341da371c863d86f83700e7f625222080c9d22e..c71d8d2f225dc049e5f5b105c71e03ff14076360 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicated.java
@@ -99,10 +99,7 @@ public class TestBuiltin_anyDuplicated extends TestBase {
 
     @Test
     public void testanyDuplicated18() {
-        // FIXME RInternalError: java.lang.ArrayIndexOutOfBoundsException: 0
-        assertEval(Ignored.ImplementationError,
-                        "argv <- structure(list(x = structure(c(3, 2, 7, 2, 6, 2, 7, 2),     .Dim = c(4L, 2L), .Dimnames = list(c('A', 'B', 'C', 'D'),         c('M', 'F'))), MARGIN = 0), .Names = c('x', 'MARGIN'));" +
-                                        "do.call('anyDuplicated', argv)");
+        assertEval("argv <- structure(list(x = structure(c(3, 2, 7, 2, 6, 2, 7, 2),     .Dim = c(4L, 2L), .Dimnames = list(c('A', 'B', 'C', 'D'),         c('M', 'F'))), MARGIN = 0), .Names = c('x', 'MARGIN'));do.call('anyDuplicated', argv)");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicatedmatrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicatedmatrix.java
index 431b920e047a30de4e9b6c8d9852d7ece22d202f..5b96ccfd74992d64d2247cc9b4cb749c8c56840d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicatedmatrix.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_anyDuplicatedmatrix.java
@@ -20,9 +20,7 @@ public class TestBuiltin_anyDuplicatedmatrix extends TestBase {
 
     @Test
     public void testanyDuplicatedmatrix1() {
-        // FIXME RInternalError: java.lang.ArrayIndexOutOfBoundsException: 0
-        assertEval(Ignored.ImplementationError,
-                        "argv <- structure(list(x = structure(c(3, 2, 7, 2, 6, 2, 7, 2),     .Dim = c(4L, 2L), .Dimnames = list(c('A', 'B', 'C', 'D'),         c('M', 'F'))), MARGIN = 0), .Names = c('x', 'MARGIN'));" +
-                                        "do.call('anyDuplicated.matrix', argv)");
+        assertEval("argv <- structure(list(x = structure(c(3, 2, 7, 2, 6, 2, 7, 2),     .Dim = c(4L, 2L), .Dimnames = list(c('A', 'B', 'C', 'D'),         c('M', 'F'))), MARGIN = 0), .Names = c('x', 'MARGIN'));" +
+                        "do.call('anyDuplicated.matrix', argv)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
index 6974bfef2a476fabd8c526c36d7333b646685999..efd65af29d6c03dd1d8d1dba1837c9b9973d12aa 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aperm.java
@@ -19,8 +19,8 @@ public class TestBuiltin_aperm extends TestBase {
 
     @Test
     public void testaperm1() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
+        // 3 spaces (GnuR) instead of two (FastR) between 1st and 2nd columns of FALSEs
+        assertEval(Output.IgnoreWhitespace,
                         "argv <- list(structure(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Dim = c(5L, 14L), .Dimnames = list(c('#ifdef', '\\\\Sexpr', 'build', 'install', 'render'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
@@ -36,23 +36,17 @@ public class TestBuiltin_aperm extends TestBase {
 
     @Test
     public void testaperm4() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L), .Dim = c(1L, 8L), .Dimnames = list('strata(enum)', c('rx', 'size', 'number', 'strata(enum)', 'cluster(id)', 'rx:strata(enum)', 'size:strata(enum)', 'number:strata(enum)'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(0L, 0L, 0L, 1L, 0L, 1L, 1L, 1L), .Dim = c(1L, 8L), .Dimnames = list('strata(enum)', c('rx', 'size', 'number', 'strata(enum)', 'cluster(id)', 'rx:strata(enum)', 'size:strata(enum)', 'number:strata(enum)'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testaperm5() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(9.2319289524956, -0.470372045488369, 186.857050189827), .Dim = c(1L, 3L), .Dimnames = list('118', c('age', 'sex', 'meal.cal'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(9.2319289524956, -0.470372045488369, 186.857050189827), .Dim = c(1L, 3L), .Dimnames = list('118', c('age', 'sex', 'meal.cal'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testaperm6() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(414L, 439L, 382L, 388L, 383L, 364L, 364L, 363L, 349L, 371L, 102L, 388L, 388L, 363L, 367L, 365L, 382L, 362L, 373L, 385L, 376L, 360L, 306L, 160L, 316L, 316L, 315L, 357L, 360L, 347L, 353L, 308L, 327L, 329L, 343L, 251L, 318L, 304L, 316L, 335L, 365L, 336L, 350L, 356L, 339L, 301L, 330L, 300L, 300L, 312L, 334L, 270L, 347L, 293L, 303L, 337L, 287L, 293L, 293L, 318L, 359L, 351L, 322L, 343L, 269L, 286L, 286L, 273L, 297L, 273L, 273L, 273L, 294L, 303L, 281L, 273L, 255L, 269L, 270L, 270L, 276L, 264L, 245L, 261L, 270L, 273L, 306L, 274L, 279L, 278L, 278L, 284L, 276L, 265L, 294L, 277L, 259L, 287L, 263L, 240L, 217L, 271L, 252L, 331L, 255L, 271L, 254L, 185L, 213L, 210L, 203L, 288L, 269L, 269L, 91L, 91L, 192L, 199L, 195L, 198L, 207L, 200L, 197L, 243L, 203L, 197L, 227L, 227L, 219L, 8L, NA, NA, 246L, NA, 292L, NA, 294L, NA, 19L, 373L, NA, 211L, 82L, NA, 334L, 18L, NA, 280L, NA, NA, NA, NA, 146L, NA, NA, NA, 267L, 206L, 175L, NA, NA, NA, NA, 118L, NA, NA, NA, NA, 274L, NA, NA, 187L, NA, 6L, NA, NA, 146L, 304L, NA, 52L, 67L, NA, 265L, NA, 91L, NA, NA, NA, 318L, 57L, 226L, 65L, NA, 264L, NA, NA, NA, 236L, NA, 207L, NA, NA, NA, NA, NA, NA, 23L, NA, NA, NA, NA, NA, NA, 113L, 99L, NA, NA, 14L, NA, NA, NA, NA, NA, NA, NA, 4L, NA, 167L, NA, NA, NA, NA, NA, NA, NA, NA, NA, 165L, NA, NA, NA, NA, NA, NA, NA, NA, 11L, NA, NA, 168L, NA, NA, 120L, NA, 104L, NA, 373L, 26L, NA, NA, 253L, NA, NA, NA, NA, NA, NA, NA, NA, 260L, 114L, NA, 370L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 280L, NA, NA, NA, NA, 240L, NA, NA, NA, NA, 361L, NA, NA, NA, NA, NA, NA, NA, 188L, NA, NA, 65L, 248L, NA, NA, NA, 121L, NA, NA, NA, NA, 121L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 306L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 159L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 22L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 152L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 265L, 337L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 255L, 250L, NA, NA, NA, 203L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 213L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 169L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 241L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 269L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 284L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 249L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 307L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 322L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 350L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), .Dim = c(128L, 8L), .Dimnames = list(    NULL, c('futime', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7'))), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(414L, 439L, 382L, 388L, 383L, 364L, 364L, 363L, 349L, 371L, 102L, 388L, 388L, 363L, 367L, 365L, 382L, 362L, 373L, 385L, 376L, 360L, 306L, 160L, 316L, 316L, 315L, 357L, 360L, 347L, 353L, 308L, 327L, 329L, 343L, 251L, 318L, 304L, 316L, 335L, 365L, 336L, 350L, 356L, 339L, 301L, 330L, 300L, 300L, 312L, 334L, 270L, 347L, 293L, 303L, 337L, 287L, 293L, 293L, 318L, 359L, 351L, 322L, 343L, 269L, 286L, 286L, 273L, 297L, 273L, 273L, 273L, 294L, 303L, 281L, 273L, 255L, 269L, 270L, 270L, 276L, 264L, 245L, 261L, 270L, 273L, 306L, 274L, 279L, 278L, 278L, 284L, 276L, 265L, 294L, 277L, 259L, 287L, 263L, 240L, 217L, 271L, 252L, 331L, 255L, 271L, 254L, 185L, 213L, 210L, 203L, 288L, 269L, 269L, 91L, 91L, 192L, 199L, 195L, 198L, 207L, 200L, 197L, 243L, 203L, 197L, 227L, 227L, 219L, 8L, NA, NA, 246L, NA, 292L, NA, 294L, NA, 19L, 373L, NA, 211L, 82L, NA, 334L, 18L, NA, 280L, NA, NA, NA, NA, 146L, NA, NA, NA, 267L, 206L, 175L, NA, NA, NA, NA, 118L, NA, NA, NA, NA, 274L, NA, NA, 187L, NA, 6L, NA, NA, 146L, 304L, NA, 52L, 67L, NA, 265L, NA, 91L, NA, NA, NA, 318L, 57L, 226L, 65L, NA, 264L, NA, NA, NA, 236L, NA, 207L, NA, NA, NA, NA, NA, NA, 23L, NA, NA, NA, NA, NA, NA, 113L, 99L, NA, NA, 14L, NA, NA, NA, NA, NA, NA, NA, 4L, NA, 167L, NA, NA, NA, NA, NA, NA, NA, NA, NA, 165L, NA, NA, NA, NA, NA, NA, NA, NA, 11L, NA, NA, 168L, NA, NA, 120L, NA, 104L, NA, 373L, 26L, NA, NA, 253L, NA, NA, NA, NA, NA, NA, NA, NA, 260L, 114L, NA, 370L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 280L, NA, NA, NA, NA, 240L, NA, NA, NA, NA, 361L, NA, NA, NA, NA, NA, NA, NA, 188L, NA, NA, 65L, 248L, NA, NA, NA, 121L, NA, NA, NA, NA, 121L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 306L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 159L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 22L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 152L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 265L, 337L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 255L, 250L, NA, NA, NA, 203L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 213L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 169L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 241L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 269L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 284L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 249L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 307L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 322L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 350L, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), .Dim = c(128L, 8L), .Dimnames = list(    NULL, c('futime', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7'))), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -62,9 +56,7 @@ public class TestBuiltin_aperm extends TestBase {
 
     @Test
     public void testaperm8() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 1539.44739946315, 1548.66655077773, 1557.88570209231, 1566.45228027983, 1575.01885846735, 1583.14083472285, 1591.26281097836, 1599.26100149451, 1607.25919201066, 1611.39689466313, 1615.5345973156, 1612.61129444623, 1609.68799157686, 1603.44643859537, 1597.20488561388, 1588.73002343463, 1580.25516125537, 1570.86127478964, 1561.46738832392, 1549.89535441445, 1538.32332050498, 1524.62526591843, 1510.92721133189, 1499.65830819836, 1488.38940506483, 1479.31388700637, 1470.23836894792, 1460.03887936132, 1449.83938977473, 1441.27547309544, 1432.71155641615, 1432.51830671501, 1432.32505701387, 1433.15763708544, 1433.99021715701, 1434.96142536256, 1435.9326335681, 1435.47421580154, 1435.01579803498, 1433.4368629411, 1431.85792784722, 1430.85617066215, 1429.85441347709, 1432.59097206397, 1435.32753065085, 1440.49425642708, 1445.66098220331, 1448.76676550395, 1451.87254880459, 1452.9163236715, 1453.96009853841, 1454.6961768366, 1455.43225513478, 1452.22362902495, 1449.01500291512, 1442.43484036078, 1435.85467780644, 1426.50159512644, 1417.14851244644, 1409.58997614642, 1402.0314398464, 1397.59624058751, 1393.16104132862, 1386.64426440334, 1380.12748747807, 1371.71107833433, 1363.2946691906, 1354.59002807904, 1345.88538696748, 1336.94914699242, 1328.01290701735, 1318.64960669271, 49.7622186359663, -84.1535032467218, -121.764781099341, 37.2870304782966, 82.528433600382, -44.2319392670254, 25.3010406627996, -34.7698782399993, 48.5709781995188, 110.301655093951, -1.96962838525201, -3.7990131710535, -51.4783734777507, 135.066608935635, 114.916035379091, -28.990712676497, -11.7078691876363, 7.04762066618673, -38.9035366827579, 16.5957688400649, -38.4931502947952, 52.0732838386475, 26.6377575984557, 329.153973076816, -13.1797869657194, 872.199160524634, 371.882552045056, -254.299568603192, -95.2920977069916, 8.63342236039193, 16.852295225008, -29.0271834604991, 13.5051131963112, 4.54091267164154, 25.5747517733375, 386.850855912621, 259.276984531009, -199.961168270532, -153.894877042003, 94.302447817031, -20.3106357794875, 21.0527247936745, -6.29056183593116, 13.9001511905426, -29.4973604406664, -31.7957066699985, -224.096013272965, -30.9544842287708, 22.3370692945275, 432.596723859509, 47.1608224545594, -304.956866078466, 50.1150369329559, 24.6852664308792, -14.4511512739648, -4.94371710626865, -19.024507596255, -56.8030453693573, -314.583543516094, 165.222305128756, 316.17817825271, 23.9168069434991, 11.9598796643579, -128.904953645213, 0.419804589665318, -6.80218287850425, 29.2691824505584, 53.9010951754703, 40.9447832426993, -26.2505972353374, -41.4479380870087, -214.837325417531, 2134, 1863, 1877, 1877, 1492, 1249, 1280, 1131, 1209, 1492, 1621, 1846, 2103, 2137, 2153, 1833, 1403, 1288, 1186, 1133, 1053, 1347, 1545, 2066, 2020, 2750, 2283, 1479, 1189, 1160, 1113, 970, 999, 1208, 1467, 2059, 2240, 1634, 1722, 1801, 1246, 1162, 1087, 1013, 959, 1179, 1229, 1655, 2019, 2284, 1942, 1423, 1340, 1187, 1098, 1004, 970, 1140, 1110, 1812, 2263, 1820, 1846, 1531, 1215, 1075, 1056, 975, 940, 1081, 1294, 1341), .Dim = c(72L, 4L), .Dimnames = list(NULL, c('STL.seasonal', 'STL.trend', 'STL.remainder', 'data')), .Tsp = c(1974, 1979.91666666667, 12), class = c('mts', 'ts', 'matrix')), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 544.790381900886, 398.486952468991, 440.879079007027, 273.26068924187, -165.547292067734, -289.908895455829, -336.563851641157, -433.491123254512, -446.830170210184, -229.698549757081, 7.43503106965538, 237.187718724823, 1539.44739946315, 1548.66655077773, 1557.88570209231, 1566.45228027983, 1575.01885846735, 1583.14083472285, 1591.26281097836, 1599.26100149451, 1607.25919201066, 1611.39689466313, 1615.5345973156, 1612.61129444623, 1609.68799157686, 1603.44643859537, 1597.20488561388, 1588.73002343463, 1580.25516125537, 1570.86127478964, 1561.46738832392, 1549.89535441445, 1538.32332050498, 1524.62526591843, 1510.92721133189, 1499.65830819836, 1488.38940506483, 1479.31388700637, 1470.23836894792, 1460.03887936132, 1449.83938977473, 1441.27547309544, 1432.71155641615, 1432.51830671501, 1432.32505701387, 1433.15763708544, 1433.99021715701, 1434.96142536256, 1435.9326335681, 1435.47421580154, 1435.01579803498, 1433.4368629411, 1431.85792784722, 1430.85617066215, 1429.85441347709, 1432.59097206397, 1435.32753065085, 1440.49425642708, 1445.66098220331, 1448.76676550395, 1451.87254880459, 1452.9163236715, 1453.96009853841, 1454.6961768366, 1455.43225513478, 1452.22362902495, 1449.01500291512, 1442.43484036078, 1435.85467780644, 1426.50159512644, 1417.14851244644, 1409.58997614642, 1402.0314398464, 1397.59624058751, 1393.16104132862, 1386.64426440334, 1380.12748747807, 1371.71107833433, 1363.2946691906, 1354.59002807904, 1345.88538696748, 1336.94914699242, 1328.01290701735, 1318.64960669271, 49.7622186359663, -84.1535032467218, -121.764781099341, 37.2870304782966, 82.528433600382, -44.2319392670254, 25.3010406627996, -34.7698782399993, 48.5709781995188, 110.301655093951, -1.96962838525201, -3.7990131710535, -51.4783734777507, 135.066608935635, 114.916035379091, -28.990712676497, -11.7078691876363, 7.04762066618673, -38.9035366827579, 16.5957688400649, -38.4931502947952, 52.0732838386475, 26.6377575984557, 329.153973076816, -13.1797869657194, 872.199160524634, 371.882552045056, -254.299568603192, -95.2920977069916, 8.63342236039193, 16.852295225008, -29.0271834604991, 13.5051131963112, 4.54091267164154, 25.5747517733375, 386.850855912621, 259.276984531009, -199.961168270532, -153.894877042003, 94.302447817031, -20.3106357794875, 21.0527247936745, -6.29056183593116, 13.9001511905426, -29.4973604406664, -31.7957066699985, -224.096013272965, -30.9544842287708, 22.3370692945275, 432.596723859509, 47.1608224545594, -304.956866078466, 50.1150369329559, 24.6852664308792, -14.4511512739648, -4.94371710626865, -19.024507596255, -56.8030453693573, -314.583543516094, 165.222305128756, 316.17817825271, 23.9168069434991, 11.9598796643579, -128.904953645213, 0.419804589665318, -6.80218287850425, 29.2691824505584, 53.9010951754703, 40.9447832426993, -26.2505972353374, -41.4479380870087, -214.837325417531, 2134, 1863, 1877, 1877, 1492, 1249, 1280, 1131, 1209, 1492, 1621, 1846, 2103, 2137, 2153, 1833, 1403, 1288, 1186, 1133, 1053, 1347, 1545, 2066, 2020, 2750, 2283, 1479, 1189, 1160, 1113, 970, 999, 1208, 1467, 2059, 2240, 1634, 1722, 1801, 1246, 1162, 1087, 1013, 959, 1179, 1229, 1655, 2019, 2284, 1942, 1423, 1340, 1187, 1098, 1004, 970, 1140, 1110, 1812, 2263, 1820, 1846, 1531, 1215, 1075, 1056, 975, 940, 1081, 1294, 1341), .Dim = c(72L, 4L), .Dimnames = list(NULL, c('STL.seasonal', 'STL.trend', 'STL.remainder', 'data')), .Tsp = c(1974, 1979.91666666667, 12), class = c('mts', 'ts', 'matrix')), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -74,9 +66,7 @@ public class TestBuiltin_aperm extends TestBase {
 
     @Test
     public void testaperm10() {
-        // FIXME Attrs not transposed (as described in aperm docs)
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), .Dim = c(4L, 4L, 2L), .Dimnames = structure(list(Hair = c('Black', 'Brown', 'Red', 'Blond'), Eye = c('Brown', 'Blue', 'Hazel', 'Green'), Sex = c('Male', 'Female')), .Names = c('Hair', 'Eye', 'Sex')), class = 'table'), c(3L, 1L, 2L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(32, 53, 10, 3, 11, 50, 10, 30, 10, 25, 7, 5, 3, 15, 7, 8, 36, 66, 16, 4, 9, 34, 7, 64, 5, 29, 7, 5, 2, 14, 7, 8), .Dim = c(4L, 4L, 2L), .Dimnames = structure(list(Hair = c('Black', 'Brown', 'Red', 'Blond'), Eye = c('Brown', 'Blue', 'Hazel', 'Green'), Sex = c('Male', 'Female')), .Names = c('Hair', 'Eye', 'Sex')), class = 'table'), c(3L, 1L, 2L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -91,9 +81,7 @@ public class TestBuiltin_aperm extends TestBase {
 
     @Test
     public void testaperm13() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c('    Null deviance:', 'Residual deviance:', '3.118557', '0.012672', ' on', ' on', '8', '7', ' degrees of freedom\\n', ' degrees of freedom\\n'), .Dim = c(2L, 5L), .Dimnames = list(c('null.deviance', 'deviance'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c('    Null deviance:', 'Residual deviance:', '3.118557', '0.012672', ' on', ' on', '8', '7', ' degrees of freedom\\n', ' degrees of freedom\\n'), .Dim = c(2L, 5L), .Dimnames = list(c('null.deviance', 'deviance'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -103,8 +91,8 @@ public class TestBuiltin_aperm extends TestBase {
 
     @Test
     public void testaperm15() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
+        // 3 spaces (GnuR) instead of two (FastR) between 1st and 2nd columns of FALSEs
+        assertEval(Output.IgnoreWhitespace,
                         "argv <- list(structure(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Dim = c(5L, 20L), .Dimnames = list(c('#ifdef', '\\\\Sexpr', 'build', 'install', 'render'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
@@ -125,30 +113,22 @@ public class TestBuiltin_aperm extends TestBase {
 
     @Test
     public void testaperm19() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 4000, 8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000, 96000, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 12000, 24000, 36000, 48000, 60000, 72000, 84000, 96000, 108000, 120000, 132000, 144000, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 16000, 32000, 48000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 20000, 40000, 60000, 80000, 1e+05, 120000, 140000, 160000, 180000, 2e+05, 220000, 240000, 24, 48, 72, 96, 120, 144, 168, 192, 216, 240, 264, 288, 24000, 48000, 72000, 96000, 120000, 144000, 168000, 192000, 216000, 240000, 264000, 288000, 28, 56, 84, 112, 140, 168, 196, 224, 252, 280, 308, 336, 28000, 56000, 84000, 112000, 140000, 168000, 196000, 224000, 252000, 280000, 308000, 336000, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 36, 72, 108, 144, 180, 216, 252, 288, 324, 360, 396, 432, 36000, 72000, 108000, 144000, 180000, 216000, 252000, 288000, 324000, 360000, 396000, 432000, 40, 80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 40000, 80000, 120000, 160000, 2e+05, 240000, 280000, 320000, 360000, 4e+05, 440000, 480000, 44, 88, 132, 176, 220, 264, 308, 352, 396, 440, 484, 528, 44000, 88000, 132000, 176000, 220000, 264000, 308000, 352000, 396000, 440000, 484000, 528000, 48, 96, 144, 192, 240, 288, 336, 384, 432, 480, 528, 576, 48000, 96000, 144000, 192000, 240000, 288000, 336000, 384000, 432000, 480000, 528000, 576000, 52, 104, 156, 208, 260, 312, 364, 416, 468, 520, 572, 624, 52000, 104000, 156000, 208000, 260000, 312000, 364000, 416000, 468000, 520000, 572000, 624000, 56, 112, 168, 224, 280, 336, 392, 448, 504, 560, 616, 672, 56000, 112000, 168000, 224000, 280000, 336000, 392000, 448000, 504000, 560000, 616000, 672000, 60, 120, 180, 240, 300, 360, 420, 480, 540, 600, 660, 720, 60000, 120000, 180000, 240000, 3e+05, 360000, 420000, 480000, 540000, 6e+05, 660000, 720000, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 64000, 128000, 192000, 256000, 320000, 384000, 448000, 512000, 576000, 640000, 704000, 768000, 68, 136, 204, 272, 340, 408, 476, 544, 612, 680, 748, 816, 68000, 136000, 204000, 272000, 340000, 408000, 476000, 544000, 612000, 680000, 748000, 816000, 72, 144, 216, 288, 360, 432, 504, 576, 648, 720, 792, 864, 72000, 144000, 216000, 288000, 360000, 432000, 504000, 576000, 648000, 720000, 792000, 864000, 76, 152, 228, 304, 380, 456, 532, 608, 684, 760, 836, 912, 76000, 152000, 228000, 304000, 380000, 456000, 532000, 608000, 684000, 760000, 836000, 912000, 80, 160, 240, 320, 400, 480, 560, 640, 720, 800, 880, 960, 80000, 160000, 240000, 320000, 4e+05, 480000, 560000, 640000, 720000, 8e+05, 880000, 960000, 84, 168, 252, 336, 420, 504, 588, 672, 756, 840, 924, 1008, 84000, 168000, 252000, 336000, 420000, 504000, 588000, 672000, 756000, 840000, 924000, 1008000, 88, 176, 264, 352, 440, 528, 616, 704, 792, 880, 968, 1056, 88000, 176000, 264000, 352000, 440000, 528000, 616000, 704000, 792000, 880000, 968000, 1056000, 92, 184, 276, 368, 460, 552, 644, 736, 828, 920, 1012, 1104, 92000, 184000, 276000, 368000, 460000, 552000, 644000, 736000, 828000, 920000, 1012000, 1104000, 96, 192, 288, 384, 480, 576, 672, 768, 864, 960, 1056, 1152, 96000, 192000, 288000, 384000, 480000, 576000, 672000, 768000, 864000, 960000, 1056000, 1152000), .Dim = c(3L, 4L, 2L, 3L, 4L, 2L), .Dimnames = list(c('A', 'B', 'C'), c('D', 'E', 'F', 'G'), c('frequentist', 'bayesian'), NULL, NULL, c('happy', 'sad'))), c(4L, 1L, 5L, 2L, 6L, 3L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 4000, 8000, 12000, 16000, 20000, 24000, 28000, 32000, 36000, 40000, 44000, 48000, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 72000, 80000, 88000, 96000, 12, 24, 36, 48, 60, 72, 84, 96, 108, 120, 132, 144, 12000, 24000, 36000, 48000, 60000, 72000, 84000, 96000, 108000, 120000, 132000, 144000, 16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192, 16000, 32000, 48000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 20, 40, 60, 80, 100, 120, 140, 160, 180, 200, 220, 240, 20000, 40000, 60000, 80000, 1e+05, 120000, 140000, 160000, 180000, 2e+05, 220000, 240000, 24, 48, 72, 96, 120, 144, 168, 192, 216, 240, 264, 288, 24000, 48000, 72000, 96000, 120000, 144000, 168000, 192000, 216000, 240000, 264000, 288000, 28, 56, 84, 112, 140, 168, 196, 224, 252, 280, 308, 336, 28000, 56000, 84000, 112000, 140000, 168000, 196000, 224000, 252000, 280000, 308000, 336000, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 36, 72, 108, 144, 180, 216, 252, 288, 324, 360, 396, 432, 36000, 72000, 108000, 144000, 180000, 216000, 252000, 288000, 324000, 360000, 396000, 432000, 40, 80, 120, 160, 200, 240, 280, 320, 360, 400, 440, 480, 40000, 80000, 120000, 160000, 2e+05, 240000, 280000, 320000, 360000, 4e+05, 440000, 480000, 44, 88, 132, 176, 220, 264, 308, 352, 396, 440, 484, 528, 44000, 88000, 132000, 176000, 220000, 264000, 308000, 352000, 396000, 440000, 484000, 528000, 48, 96, 144, 192, 240, 288, 336, 384, 432, 480, 528, 576, 48000, 96000, 144000, 192000, 240000, 288000, 336000, 384000, 432000, 480000, 528000, 576000, 52, 104, 156, 208, 260, 312, 364, 416, 468, 520, 572, 624, 52000, 104000, 156000, 208000, 260000, 312000, 364000, 416000, 468000, 520000, 572000, 624000, 56, 112, 168, 224, 280, 336, 392, 448, 504, 560, 616, 672, 56000, 112000, 168000, 224000, 280000, 336000, 392000, 448000, 504000, 560000, 616000, 672000, 60, 120, 180, 240, 300, 360, 420, 480, 540, 600, 660, 720, 60000, 120000, 180000, 240000, 3e+05, 360000, 420000, 480000, 540000, 6e+05, 660000, 720000, 64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 64000, 128000, 192000, 256000, 320000, 384000, 448000, 512000, 576000, 640000, 704000, 768000, 68, 136, 204, 272, 340, 408, 476, 544, 612, 680, 748, 816, 68000, 136000, 204000, 272000, 340000, 408000, 476000, 544000, 612000, 680000, 748000, 816000, 72, 144, 216, 288, 360, 432, 504, 576, 648, 720, 792, 864, 72000, 144000, 216000, 288000, 360000, 432000, 504000, 576000, 648000, 720000, 792000, 864000, 76, 152, 228, 304, 380, 456, 532, 608, 684, 760, 836, 912, 76000, 152000, 228000, 304000, 380000, 456000, 532000, 608000, 684000, 760000, 836000, 912000, 80, 160, 240, 320, 400, 480, 560, 640, 720, 800, 880, 960, 80000, 160000, 240000, 320000, 4e+05, 480000, 560000, 640000, 720000, 8e+05, 880000, 960000, 84, 168, 252, 336, 420, 504, 588, 672, 756, 840, 924, 1008, 84000, 168000, 252000, 336000, 420000, 504000, 588000, 672000, 756000, 840000, 924000, 1008000, 88, 176, 264, 352, 440, 528, 616, 704, 792, 880, 968, 1056, 88000, 176000, 264000, 352000, 440000, 528000, 616000, 704000, 792000, 880000, 968000, 1056000, 92, 184, 276, 368, 460, 552, 644, 736, 828, 920, 1012, 1104, 92000, 184000, 276000, 368000, 460000, 552000, 644000, 736000, 828000, 920000, 1012000, 1104000, 96, 192, 288, 384, 480, 576, 672, 768, 864, 960, 1056, 1152, 96000, 192000, 288000, 384000, 480000, 576000, 672000, 768000, 864000, 960000, 1056000, 1152000), .Dim = c(3L, 4L, 2L, 3L, 4L, 2L), .Dimnames = list(c('A', 'B', 'C'), c('D', 'E', 'F', 'G'), c('frequentist', 'bayesian'), NULL, NULL, c('happy', 'sad'))), c(4L, 1L, 5L, 2L, 6L, 3L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testaperm20() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(1:24, .Dim = c(4L, 6L), .Dimnames = structure(list(happy = c('a', 'b', 'c', 'd'), sad = c('A', 'B', 'C', 'D', 'E', 'F')), .Names = c('happy', 'sad'))), c(2, 1), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(1:24, .Dim = c(4L, 6L), .Dimnames = structure(list(happy = c('a', 'b', 'c', 'd'), sad = c('A', 'B', 'C', 'D', 'E', 'F')), .Names = c('happy', 'sad'))), c(2, 1), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testaperm21() {
-        // FIXME .Dimnames not applied
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(1:120, .Dim = 2:5, .Dimnames = list(NULL, c('a', 'b', 'c'), NULL, c('V5', 'V6', 'V7', 'V8', 'V9'))), 1:4, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(1:120, .Dim = 2:5, .Dimnames = list(NULL, c('a', 'b', 'c'), NULL, c('V5', 'V6', 'V7', 'V8', 'V9'))), 1:4, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testaperm22() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c('    Null deviance:', 'Residual deviance:', '67.5316', ' 4.5512', ' on', ' on', '9', '7', ' degrees of freedom\\n', ' degrees of freedom\\n'), .Dim = c(2L, 5L), .Dimnames = list(c('null.deviance', 'deviance'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c('    Null deviance:', 'Residual deviance:', '67.5316', ' 4.5512', ' on', ' on', '9', '7', ' degrees of freedom\\n', ' degrees of freedom\\n'), .Dim = c(2L, 5L), .Dimnames = list(c('null.deviance', 'deviance'), NULL)), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -158,24 +138,18 @@ public class TestBuiltin_aperm extends TestBase {
 
     @Test
     public void testaperm24() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 2, 3, 4, 5), .Dim = c(8L, 2L), .Dimnames = list(c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), c('x1', 'x2'))), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 2, 1, 2, 3, 4, 5), .Dim = c(8L, 2L), .Dimnames = list(c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'), c('x1', 'x2'))), c(2L, 1L), TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testaperm25() {
-        // FIXME .Dimnames not applied
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(0, 1.23517986278748, 1.95771376416406, 2.47035972557496, 2.86799882564536, 3.19289362695154, 3.46758826742286, 3.70553958836244, 3.91542752832811, 4.10317868843284, 4.27302027203108, 4.42807348973901, 4.57070862330685, 4.70276813021034, 4.82571258980942, 4.94071945114991, 5.04875179140451, 5.15060739111559, 5.2469545231864, 5.33835855122032, 5.42530203158692, 5.50820013481856, 5.58741263619316, 5.66325335252649, 5.73599765129073, 5.80588848609433, 5.87314129249217, 5.93794799299782, 6.00048029898585, 6.0608924525969, 6.11932351888589, 6.17589931393739, 6.23073403619514, 6.28393165419199, 6.33558709306823, 6.38578725390307, 6.43461189335533, 6.48213438597388, 6.52842238747091, 6.5735384140078, 6.61754034994095, 6.6604818943744, 6.70241295516147, 6.74337999760604, 6.78342635397348, 6.82259249898064, 6.86091629565604, 6.89843321531397, 6.93517653484573, 6.97117751407821, 7.00646555556857, 7.04106834888181, 7.07501200112497, 7.10832115527965, 7.14101909767645, 7.1731278557853, 7.20466828735046, 7.23566016177333, 7.26612223453848, 7.29607231538438, 7.3255273308395, 7.35450338167337, 7.38301579575098, 7.41107917672487, 7.43870744895221, 7.46591389898262, 7.49271121392624, 7.51911151697947, 7.54512640035722, 7.57076695585571, 7.59604380324749, 7.62096711669055, 7.64554664931599, 7.66979175614282, 7.69371141545478, 7.71731424876136, 7.74060853945395, 7.76360225025839, 7.78630303957574, 7.80871827679528, 7.83085505665623, 7.85272021272842, 7.87432033007586, 7.89566175716188, 7.91675061704988, 7.93759281794895, 7.95819406314991, 7.97855986039352, 7.99869553070936, 8.01860621676096, 8.03829689072971, 8.05777236176812, 8.07703728304995, 8.09609615844352, 8.11495334883177, 8.13361307810145, 8.15207943882202, 8.17035639763321, 8.1884478003592, 8.20635737686569, 5.76558893216369, 5.5342688729893, 5.69366159038267, 6.17674775070929, 6.08762735966107, 6.68653280779044, 6.70253591217234, 6.32938323618963, 6.81735284786279, 6.64835766778347, 6.91213030655848, 7.1496842781073, 7.25682341590407, 7.46164094256645, 7.37149913131863, 7.56470707593246, 7.71334191900841, 7.71375128844693, 7.82793409372511, 7.90749319121623, 7.96255733207686, 8.11381187364273, 8.21211505208663, 8.18427543602736, 8.29133399017863, 8.31295002652197, 8.345677476918, 8.39053879616249, 8.40857122007675, 8.48086068897741, 8.7064475146364, 8.66563269607315, 8.79435721712053, 8.7996087849725, 8.82443395257555, 8.91314507957224, 8.8999544270272, 8.96760168103462, 8.93548690078514, 9.01332239000153, 9.07083338712431, 9.15422051683385, 9.20109302097792, 9.2062218972166, 9.31170984199071, 9.30909253379462, 9.35447695163181, 9.45333740615033, 9.41458248768079, 9.46983861007334, 9.51652628670815, 9.5301888386762, 9.59497468213833, 9.61268143770055, 9.64141492393412, 9.68857453461133, 9.77580537125637, 9.79816256416163, 9.79128849346381, 9.80699184934282, 9.91833626833319, 9.95487179604373, 9.88086373278725, 9.93505313047982, 9.97034080826287, 9.97752630228797, 10.1165750634827, 10.0977558023188, 10.1414502841663, 10.129071787117, 10.166774063688, 10.1792762662323, 10.2172491181904, 10.2670710204409, 10.2742314938915, 10.287876622612, 10.3447249333494, 10.4075370351282, 10.3465199067119, 10.4404223214255, 10.422301774768, 10.4739543513507, 10.5314461891317, 10.4813429169605, 10.5097541699286, 10.5389544549716, 10.5752633644781, 10.6133054015308, 10.6776080133421, 10.6266190058322, 10.6657950921482, 10.7067723709738, 10.7424707425861, 10.7418659657784, 10.7335163259687, 10.780101845273, 10.8334343829096, 10.8616735406708, 10.8535694508523, 10.8900668188725), .Dim = c(100L, 2L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100'), c('log(x)', 'log(z)'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c(0, 1.23517986278748, 1.95771376416406, 2.47035972557496, 2.86799882564536, 3.19289362695154, 3.46758826742286, 3.70553958836244, 3.91542752832811, 4.10317868843284, 4.27302027203108, 4.42807348973901, 4.57070862330685, 4.70276813021034, 4.82571258980942, 4.94071945114991, 5.04875179140451, 5.15060739111559, 5.2469545231864, 5.33835855122032, 5.42530203158692, 5.50820013481856, 5.58741263619316, 5.66325335252649, 5.73599765129073, 5.80588848609433, 5.87314129249217, 5.93794799299782, 6.00048029898585, 6.0608924525969, 6.11932351888589, 6.17589931393739, 6.23073403619514, 6.28393165419199, 6.33558709306823, 6.38578725390307, 6.43461189335533, 6.48213438597388, 6.52842238747091, 6.5735384140078, 6.61754034994095, 6.6604818943744, 6.70241295516147, 6.74337999760604, 6.78342635397348, 6.82259249898064, 6.86091629565604, 6.89843321531397, 6.93517653484573, 6.97117751407821, 7.00646555556857, 7.04106834888181, 7.07501200112497, 7.10832115527965, 7.14101909767645, 7.1731278557853, 7.20466828735046, 7.23566016177333, 7.26612223453848, 7.29607231538438, 7.3255273308395, 7.35450338167337, 7.38301579575098, 7.41107917672487, 7.43870744895221, 7.46591389898262, 7.49271121392624, 7.51911151697947, 7.54512640035722, 7.57076695585571, 7.59604380324749, 7.62096711669055, 7.64554664931599, 7.66979175614282, 7.69371141545478, 7.71731424876136, 7.74060853945395, 7.76360225025839, 7.78630303957574, 7.80871827679528, 7.83085505665623, 7.85272021272842, 7.87432033007586, 7.89566175716188, 7.91675061704988, 7.93759281794895, 7.95819406314991, 7.97855986039352, 7.99869553070936, 8.01860621676096, 8.03829689072971, 8.05777236176812, 8.07703728304995, 8.09609615844352, 8.11495334883177, 8.13361307810145, 8.15207943882202, 8.17035639763321, 8.1884478003592, 8.20635737686569, 5.76558893216369, 5.5342688729893, 5.69366159038267, 6.17674775070929, 6.08762735966107, 6.68653280779044, 6.70253591217234, 6.32938323618963, 6.81735284786279, 6.64835766778347, 6.91213030655848, 7.1496842781073, 7.25682341590407, 7.46164094256645, 7.37149913131863, 7.56470707593246, 7.71334191900841, 7.71375128844693, 7.82793409372511, 7.90749319121623, 7.96255733207686, 8.11381187364273, 8.21211505208663, 8.18427543602736, 8.29133399017863, 8.31295002652197, 8.345677476918, 8.39053879616249, 8.40857122007675, 8.48086068897741, 8.7064475146364, 8.66563269607315, 8.79435721712053, 8.7996087849725, 8.82443395257555, 8.91314507957224, 8.8999544270272, 8.96760168103462, 8.93548690078514, 9.01332239000153, 9.07083338712431, 9.15422051683385, 9.20109302097792, 9.2062218972166, 9.31170984199071, 9.30909253379462, 9.35447695163181, 9.45333740615033, 9.41458248768079, 9.46983861007334, 9.51652628670815, 9.5301888386762, 9.59497468213833, 9.61268143770055, 9.64141492393412, 9.68857453461133, 9.77580537125637, 9.79816256416163, 9.79128849346381, 9.80699184934282, 9.91833626833319, 9.95487179604373, 9.88086373278725, 9.93505313047982, 9.97034080826287, 9.97752630228797, 10.1165750634827, 10.0977558023188, 10.1414502841663, 10.129071787117, 10.166774063688, 10.1792762662323, 10.2172491181904, 10.2670710204409, 10.2742314938915, 10.287876622612, 10.3447249333494, 10.4075370351282, 10.3465199067119, 10.4404223214255, 10.422301774768, 10.4739543513507, 10.5314461891317, 10.4813429169605, 10.5097541699286, 10.5389544549716, 10.5752633644781, 10.6133054015308, 10.6776080133421, 10.6266190058322, 10.6657950921482, 10.7067723709738, 10.7424707425861, 10.7418659657784, 10.7335163259687, 10.780101845273, 10.8334343829096, 10.8616735406708, 10.8535694508523, 10.8900668188725), .Dim = c(100L, 2L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100'), c('log(x)', 'log(z)'))), 1:2, TRUE); .Internal(aperm(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testaperm27() {
-        // FIXME .Dimnames not transposed
-        assertEval(Ignored.ImplementationError,
-                        "argv <- structure(list(a = structure(c(0.124248979591837, 0.266432653061224,     0.404342857142857, 0.0992163265306122, 0.0851836734693878,     0.0937632653061225, 0.0163551020408163, 0.182897959183673,     0.303289795918367, 0.010330612244898, 0.0557795918367347,     0.0490938775510204, 0.0992163265306122, 0.0851836734693878,     0.0937632653061225, 0.143689795918367, 0.098469387755102,     0.104004081632653, 0.0116979591836735, 0.0826530612244898,     0.0713795918367347, 0.00929795918367347, 0.0412040816326531,     0.0476285714285714, 0.0163551020408163, 0.182897959183673,     0.303289795918367, 0.0116979591836735, 0.0826530612244898,     0.0713795918367347, 0.0301591836734694, 0.220816326530612,     0.304587755102041, 0.00606938775510204, 0.0731020408163265,     0.0488244897959184, 0.010330612244898, 0.0557795918367347,     0.0490938775510204, 0.00929795918367347, 0.0412040816326531,     0.0476285714285714, 0.00606938775510204, 0.0731020408163265,     0.0488244897959184, 0.0111061224489796, 0.0391061224489796,     0.0754326530612245), .Dim = c(3L, 4L, 4L), .Dimnames = structure(list(Species = c('setosa',     'versicolor', 'virginica'), c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width'), c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width')), .Names = c('Species', '',     ''))), perm = c(2, 3, 1)), .Names = c('a', 'perm'));" +
-                                        "do.call('aperm', argv)");
+        assertEval("argv <- structure(list(a = structure(c(0.124248979591837, 0.266432653061224,     0.404342857142857, 0.0992163265306122, 0.0851836734693878,     0.0937632653061225, 0.0163551020408163, 0.182897959183673,     0.303289795918367, 0.010330612244898, 0.0557795918367347,     0.0490938775510204, 0.0992163265306122, 0.0851836734693878,     0.0937632653061225, 0.143689795918367, 0.098469387755102,     0.104004081632653, 0.0116979591836735, 0.0826530612244898,     0.0713795918367347, 0.00929795918367347, 0.0412040816326531,     0.0476285714285714, 0.0163551020408163, 0.182897959183673,     0.303289795918367, 0.0116979591836735, 0.0826530612244898,     0.0713795918367347, 0.0301591836734694, 0.220816326530612,     0.304587755102041, 0.00606938775510204, 0.0731020408163265,     0.0488244897959184, 0.010330612244898, 0.0557795918367347,     0.0490938775510204, 0.00929795918367347, 0.0412040816326531,     0.0476285714285714, 0.00606938775510204, 0.0731020408163265,     0.0488244897959184, 0.0111061224489796, 0.0391061224489796,     0.0754326530612245), .Dim = c(3L, 4L, 4L), .Dimnames = structure(list(Species = c('setosa',     'versicolor', 'virginica'), c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width'), c('Sepal.Length', 'Sepal.Width',     'Petal.Length', 'Petal.Width')), .Names = c('Species', '',     ''))), perm = c(2, 3, 1)), .Names = c('a', 'perm'));" +
+                        "do.call('aperm', argv)");
     }
 
     @Test
@@ -228,4 +202,12 @@ public class TestBuiltin_aperm extends TestBase {
         // Complex Vector
         assertEval("{ aperm(array(c(3+2i, 5+0i, 1+3i, 5-3i), c(2,2,2))) }");
     }
+
+    @Test
+    public void testApermAttrs() {
+        // Dimnames are expected to be permuted too; check that refcount is proper for permuted
+        // dimnames
+        assertEval("{ a<-array(1:24, c(2,3,4), dimnames=list(x=c('x1','x2'),y=c('y1','y2','y3'),z=c('z1','z2','z3','z4'))); b<-aperm(a,c(3,1,2)); a; b; dimnames(b)$x[1]<-'c'; dimnames(a)$x; }");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
index 4a2724063a9a53d83ee45fe2fad6b41b2f315e38..087193a3effdc48cc31bfb550285d66966399b88 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_array.java
@@ -64,7 +64,8 @@ public class TestBuiltin_array extends TestBase {
 
     @Test
     public void testarray10() {
-        assertEval(Ignored.Unknown,
+        // FIXME Column with "\\Sexpr" header shifted one char right in FastR
+        assertEval(Output.IgnoreWhitespace,
                         "argv <- list(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), c(5L, 16L), list(c('#ifdef', '\\\\Sexpr', 'build', 'install', 'render'), NULL)); .Internal(array(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
index 1649f2aae78282d9b7d635e7ca98f41e5d11fd5d..5715ff9d612ed6730d6b6feeabf9dddfb7d58810 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascall.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -61,5 +61,7 @@ public class TestBuiltin_ascall extends TestBase {
         assertEval("{ f <- function(x) x ; l <- list(f, 42) ; cl <- as.call(l); typeof(cl[[2]]) }");
 
         assertEval("{ as.call(42) }");
+
+        assertEval("typeof(as.call(list(substitute(graphics::par))))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
index c14ea94779518649d14ea38c2f50ae62e5c8802c..52ee6cfe6c6133a370e38ce9d78af85dfd1eb644 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascharacter.java
@@ -267,5 +267,6 @@ public class TestBuiltin_ascharacter extends TestBase {
 
         assertEval("{ f1<-function() 7; f2<-function(x) { sys.call() }; as.character(f2(f1())) }");
         assertEval("{ f1<-function(x) 7; f2<-function(y) { sys.call() }; as.character(f2(f1(42))) }");
+        assertEval("{ as.character.cls <- function(x) 42; as.character(structure(c(1,2), class='cls')); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java
index b7a010a802caba243ba8657deaad7826c0e023cc..766320bdadf0ce374ea4d015db943c5862bb93f0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ascomplex.java
@@ -101,5 +101,6 @@ public class TestBuiltin_ascomplex extends TestBase {
         assertEval("{ as.complex(list(42)) }");
         assertEval(Output.IgnoreErrorContext, "{ as.complex(list(NULL)) }");
         assertEval(Output.IgnoreWarningContext, "{ as.complex(list(\"foo\")) }");
+        assertEval("{ as.complex.cls <- function(x) 42; as.complex(structure(c(1,2), class='cls')); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdataframetable.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdataframetable.java
index b6135db975cfaa31c33ae96c7a9aa8461531c95f..a36c934765502ab1c136381850cd5e8465e5d14f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdataframetable.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdataframetable.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.
  */
@@ -20,7 +20,7 @@ public class TestBuiltin_asdataframetable extends TestBase {
 
     @Test
     public void testasdataframetable1() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(x = structure(integer(0), .Dim = 0L, .Dimnames = structure(list(NULL),     .Names = ''), class = 'table')), .Names = 'x');" +
+        assertEval("argv <- structure(list(x = structure(integer(0), .Dim = 0L, .Dimnames = structure(list(NULL),     .Names = ''), class = 'table')), .Names = 'x');" +
                         "do.call('as.data.frame.table', argv)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdifftime.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdifftime.java
index a39cfdb313564626ebc3c07980bd738a3e2c475a..6a24ff3af08e423d50743a0e677886b945ba4c5c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdifftime.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdifftime.java
@@ -20,13 +20,11 @@ public class TestBuiltin_asdifftime extends TestBase {
 
     @Test
     public void testasdifftime1() {
-        // FIXME RInternalError: should not reach here
-        assertEval(Ignored.ImplementationError, "argv <- structure(list(tim = c('0:3:20', '11:23:15')), .Names = 'tim');do.call('as.difftime', argv)");
+        assertEval("argv <- structure(list(tim = c('0:3:20', '11:23:15')), .Names = 'tim');do.call('as.difftime', argv)");
     }
 
     @Test
     public void testasdifftime2() {
-        // FIXME RInternalError: should not reach here
-        assertEval(Ignored.ImplementationError, "argv <- structure(list(tim = c('3:20', '23:15', '2:'), format = '%H:%M'),     .Names = c('tim', 'format'));do.call('as.difftime', argv)");
+        assertEval("argv <- structure(list(tim = c('3:20', '23:15', '2:'), format = '%H:%M'),     .Names = c('tim', 'format'));do.call('as.difftime', argv)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
index 26624d73a5a4740709d366033340ca864aa05215..a8bf3d2060252563251c2749fa5f0f48b47e721e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asdouble.java
@@ -29,8 +29,7 @@ public class TestBuiltin_asdouble extends TestBase {
 
     @Test
     public void testasdouble3() {
-        // FIXME FastR outputs 4 (does not handle specially difftime class)
-        assertEval(Ignored.ImplementationError, "argv <- list(structure(4, tzone = 'GMT', units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(structure(4, tzone = 'GMT', units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -95,8 +94,7 @@ public class TestBuiltin_asdouble extends TestBase {
 
     @Test
     public void testasdouble16() {
-        // FIXME FastR outputs 28 i.e. does not handle specially difftime class
-        assertEval(Ignored.ImplementationError, "argv <- list(structure(28, units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(structure(28, units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -111,8 +109,7 @@ public class TestBuiltin_asdouble extends TestBase {
 
     @Test
     public void testasdouble19() {
-        // FIXME FastR outputs 180.9583 (does not handle specially difftime class)
-        assertEval(Ignored.ImplementationError, "argv <- list(structure(180.958333333333, units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(structure(180.958333333333, units = 'days', class = 'difftime'), units = 'secs');as.double(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -188,5 +185,6 @@ public class TestBuiltin_asdouble extends TestBase {
         assertEval("{ x<-c(a=1.1, b=2.2); dim(x)<-c(1,2); attr(x, \"foo\")<-\"foo\"; y<-as.double(x); attributes(y) }");
         assertEval("{ x<-c(a=1L, b=2L); dim(x)<-c(1,2); attr(x, \"foo\")<-\"foo\"; y<-as.double(x); attributes(y) }");
         assertEval("{ as.double(NULL) }");
+        assertEval("{ as.double.cls <- function(x) 42; as.double(structure(c(1,2), class='cls')); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java
index 6efaa38af0fc646336bef5e74fa19a7281053daa..19aeddb65d4d96a5da38c47f76af20880fac9004 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asinteger.java
@@ -24,13 +24,15 @@ public class TestBuiltin_asinteger extends TestBase {
 
     @Test
     public void testasinteger2() {
-        assertEval(Ignored.Unknown,
+        // FIXME according to docs a leading whitespace should be accepted
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(c('   33', '   34', '   35', '   36', '   37', '   38', '   18', '   19', '   20', '   21', '   22', '   23', '   36', '   37', '   38', '   39'));as.integer(argv[[1]]);");
     }
 
     @Test
     public void testasinteger3() {
-        assertEval(Ignored.Unknown,
+        // FIXME combination of Inf and a number causes AssertionError
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(c(-Inf, -8.5, -2.83333333333333, -1.41666666666667, -0.85, -0.566666666666666, -0.404761904761905, -0.303571428571428, -0.236111111111111, -0.188888888888889));as.integer(argv[[1]]);");
     }
 
@@ -66,7 +68,8 @@ public class TestBuiltin_asinteger extends TestBase {
 
     @Test
     public void testasinteger11() {
-        assertEval(Ignored.Unknown, "argv <- list(c('3', '14159265358979'));as.integer(argv[[1]]);");
+        // FIXME combination of a large number and a number causes AssertionError
+        assertEval(Ignored.ImplementationError, "argv <- list(c('3', '14159265358979'));as.integer(argv[[1]]);");
     }
 
     @Test
@@ -143,5 +146,6 @@ public class TestBuiltin_asinteger extends TestBase {
         assertEval("{ as.integer(\"\") }");
         assertEval("{ as.integer(as.character(NA)) }");
         assertEval("{ as.integer(\"1\", as.character(NA)) }");
+        assertEval("{ as.integer.cls <- function(x) 42; as.integer(structure(c(1,2), class='cls')); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslogical.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslogical.java
index 06aac364437447adef9c6966430184850fa5982c..528771ad78568fef103adc9c2696fee3364f85b8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslogical.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_aslogical.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -99,5 +99,6 @@ public class TestBuiltin_aslogical extends TestBase {
         assertEval("{ as.logical(10+2i) }");
         assertEval("{ as.logical(c(3+3i, 4+4i)) }");
         assertEval("{ as.logical(NULL) }");
+        assertEval("{ as.logical.cls <- function(x) 42; as.logical(structure(c(1,2), class='cls')); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java
index d8c0187dacfb3f77352b69a7d78d97ffad8bf785..6432d859efb3eee089ad3ef48c779d2190d1837d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asraw.java
@@ -58,6 +58,7 @@ public class TestBuiltin_asraw extends TestBase {
         assertEval("{ as.raw(c(1L, 2L, 3L)) }");
         assertEval("{ as.raw(list(1,2,3)) }");
         assertEval("{ as.raw(list(\"1\", 2L, 3.4)) }");
+        assertEval("{ as.raw.cls <- function(x) 42; as.raw(structure(c(1,2), class='cls')); }");
 
         assertEval(Output.IgnoreWarningContext, "{ as.raw(1+1i) }");
         assertEval(Output.IgnoreWarningContext, "{ as.raw(-1) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_astype_dispatch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_astype_dispatch.java
new file mode 100644
index 0000000000000000000000000000000000000000..f78d2b5e32b07b24aae23cbe12e9521c5cf21609
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_astype_dispatch.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+/**
+ * Tests internal dispatch of 'as.{type}' functions.
+ */
+public class TestBuiltin_astype_dispatch extends TestBase {
+
+    private static final String[] AS_FUNC_NAMES = new String[]{"as.character", "as.integer", "as.double", "as.complex", "as.logical", "as.raw"};
+
+    @Test
+    public void testAsFunctionInternalDispatch() {
+        assertEval(template("{ %0.myclass <- function(x) 42L; %0(structure(TRUE, class='myclass')); }", AS_FUNC_NAMES));
+    }
+
+    @Test
+    public void testExtraArgumentsArePassedToOverload() {
+        assertEval("as.integer.myclass <- function(x, extra, ...) list(x=x, extra=extra, varargs=list(...)); as.integer(structure(TRUE, class='myclass'), my=TRUE, extra=42L, args='hello');");
+    }
+
+    @Test
+    public void testWithBuiltinFunction() {
+        // taken from grDevices package
+        assertEval("as.numeric(diff(structure(c(-154401120, 1503191520), class = c('POSIXct', 'POSIXt'), tzone = 'GMT')), units='secs')");
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
index 11385e6c408a423f8c3936b2a3948c79b57a19c4..9e95aa28f713d7e0016d5fbabcecdb1590c9771a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_asvector.java
@@ -89,7 +89,10 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector15() {
-        assertEval(Ignored.Unknown, "argv <- list(quote(sqrt(abs(`Standardized residuals`))), 'expression'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        // FIXME
+        // Expected output: expression(sqrt(abs(`Standardized residuals`)))
+        // FastR output: expression(sqrt, abs(`Standardized residuals`))
+        assertEval(Ignored.ImplementationError, "argv <- list(quote(sqrt(abs(`Standardized residuals`))), 'expression'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -109,7 +112,10 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector19() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL, 'double'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        // docs do not explicitly handle this so it might be ReferenceError too
+        // Expected output: numeric(0)
+        // FastR output: NULL
+        assertEval(Ignored.ImplementationError, "argv <- list(NULL, 'double'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -119,7 +125,10 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector21() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL, 'integer'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        // docs do not explicitly handle this so it might be ReferenceError too
+        // Expected output: numeric(0)
+        // FastR output: NULL
+        assertEval(Ignored.ImplementationError, "argv <- list(NULL, 'integer'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -204,7 +213,7 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector38() {
-        assertEval(Ignored.Unknown, "argv <- list(integer(0), 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(integer(0), 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -219,7 +228,13 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector41() {
-        assertEval(Ignored.Unknown,
+        // FIXME
+        // Expected output: [1] character(0)
+        // <0 rows> (or 0-length row.names)
+        // FastR output: $`character(0)`
+        // factor(0)
+        // Levels:
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(list(`character(0)` = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'character(0)', row.names = character(0), class = 'data.frame'), 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
@@ -235,7 +250,8 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector44() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL, 'logical'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        // RInternalError: not implemented: NULL to logical
+        assertEval(Ignored.ImplementationError, "argv <- list(NULL, 'logical'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -275,12 +291,12 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector53() {
-        assertEval(Ignored.Unknown, "argv <- list('1.3', 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list('1.3', 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testasvector54() {
-        assertEval(Ignored.Unknown, "argv <- list(1L, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(1L, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -295,7 +311,7 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector57() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(FALSE, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -370,7 +386,7 @@ public class TestBuiltin_asvector extends TestBase {
 
     @Test
     public void testasvector75() {
-        assertEval(Ignored.Unknown, "argv <- list(3.14159265358979, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(3.14159265358979, 'pairlist'); .Internal(as.vector(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -425,6 +441,9 @@ public class TestBuiltin_asvector extends TestBase {
         assertEval(Output.ImprovedErrorContext, "{ as.vector(42, NULL) }");
         assertEval(Output.ImprovedErrorContext, "{ as.vector(42, c(\"character\", \"character\")) }");
         assertEval(Output.ImprovedErrorContext, "{ as.vector(42, character())  }");
+
+        assertEval("as.vector(NULL, mode='pairlist')");
+        assertEval("{ as.vector.cls <- function(x, mode) 42; as.vector(structure(c(1,2), class='cls')); }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
index 43a54a0dd24e553d6a21740c39257d2370da0542..58c752e272f9bd28a8aed8782715f98f2db29eea 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_atan2.java
@@ -19,12 +19,17 @@ public class TestBuiltin_atan2 extends TestBase {
 
     @Test
     public void testatan21() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(0.142857142857143, .Names = 'Var2'), structure(1.75510204081633, .Names = 'Var1')); .Internal(atan2(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(0.142857142857143, .Names = 'Var2'), structure(1.75510204081633, .Names = 'Var1')); .Internal(atan2(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(0.142857142857143, .Names = 'Var2'), 1.75510204081633); .Internal(atan2(argv[[1]], argv[[2]]))");
+        assertEval(".Internal(atan2(structure(c(1,2), .Names = c('a','b')), 1));");
+        assertEval(".Internal(atan2(structure(1:2, .Names = c('a','b')), 1));");
+        assertEval(".Internal(atan2(structure(1:6, dim = c(2,3)), 1));");
+        assertEval("x <- 1:4; class(x) <- 'asdfasdf'; attr(x, 'f') <- 'fff'; names(x) <- c('a','b','c','d'); y <- 1:2; class(y) <- 'fds'; attr(y, 'a') <- 'Asdf'; names(y) <- c('v','y'); .Internal(atan2(x,1)); .Internal(atan2(x,x)); .Internal(atan2(x,y)); .Internal(atan2(y,x)); .Internal(atan2(y,1))");
     }
 
     @Test
     public void testatan22() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(-0.224489795918367, .Names = 'Var2'), structure(-0.816326530612245, .Names = 'Var1')); .Internal(atan2(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(-0.224489795918367, .Names = 'Var2'), structure(-0.816326530612245, .Names = 'Var1')); .Internal(atan2(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -34,7 +39,8 @@ public class TestBuiltin_atan2 extends TestBase {
 
     @Test
     public void testatan24() {
-        assertEval(Ignored.Unknown, "argv <- list(0+1i, 0+0i); .Internal(atan2(argv[[1]], argv[[2]]))");
+        // FIXME atan2 not implemented for complex values
+        assertEval(Ignored.Unimplemented, "argv <- list(0+1i, 0+0i); .Internal(atan2(argv[[1]], argv[[2]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
index e69737300cb5c637d2e54237b978b172d2824241..d6e982828c0faeb2ce09a508e084eaf79c3f3985 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attrassign.java
@@ -44,7 +44,7 @@ public class TestBuiltin_attrassign extends TestBase {
 
     @Test
     public void testattrassign6() {
-        assertEval(Ignored.Unknown,
+        assertEval(Output.IgnoreWhitespace,
                         "argv <- list(structure(c('o', 'p', 'v', 'i', 'r', 'w', 'b', 'm', 'f', 's'), date = structure(1224086400, class = c('POSIXct', 'POSIXt'), tzone = '')), 'date', value = structure(1224086400, class = c('POSIXct', 'POSIXt'), tzone = ''));`attr<-`(argv[[1]],argv[[2]],argv[[3]]);");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributesassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributesassign.java
index e9fa6045044912f1acb5f1d95b0029f28b8c5993..1b6a07daec94d0ce39da1d6c7278d3da07a44deb 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributesassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_attributesassign.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.
  */
@@ -19,12 +19,13 @@ public class TestBuiltin_attributesassign extends TestBase {
 
     @Test
     public void testattributesassign1() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL, NULL);`attributes<-`(argv[[1]],argv[[2]]);");
+        // FIXME According to docs NULL object is allowed (coerced to empty list)
+        assertEval(Ignored.ImplementationError, "argv <- list(NULL, NULL);`attributes<-`(argv[[1]],argv[[2]]);");
     }
 
     @Test
     public void testattributesassign2() {
-        assertEval(Ignored.Unknown,
+        assertEval(Output.IgnoreWhitespace,
                         "argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame'), structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = 'data.frame'));`attributes<-`(argv[[1]],argv[[2]]);");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bcVersion.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bcVersion.java
index 10fee8130267ab99503bc46203c6a29e5402ac3b..a3953145225a1095d7734e6c9ccb5df39199c2bd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bcVersion.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_bcVersion.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.
  */
@@ -19,6 +19,7 @@ public class TestBuiltin_bcVersion extends TestBase {
 
     @Test
     public void testbcVersion1() {
-        assertEval(Ignored.Unknown, " .Internal(bcVersion())");
+        // FIXME RInternalError: not implemented: .Internal bcVersion
+        assertEval(Ignored.Unimplemented, " .Internal(bcVersion())");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_c.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_c.java
index 99bfa6460b0b1ecef9cc6496604026b2028ba8f1..5b22103fc953e6e333c6a485183a380fdcde63d7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_c.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_c.java
@@ -89,7 +89,7 @@ public class TestBuiltin_c extends TestBase {
         // FIXME FastR does not honor setting options(digits=ndecimaldigits)
         // First test is a simplified problem on which the second test would fail too (besides that
         // it should work fine)
-        assertEval(Ignored.OutputFormatting, "options(digits=4);c(0.12345678912345,0.123)");
+        assertEval("options(digits=4);c(0.12345678912345,0.123)");
         assertEval(Ignored.OutputFormatting,
                         "argv <- list(`Grand mean` = structure(103.87323943662, class = 'mtable'), structure(list(N = structure(c(78.7365206866197, 98.5088731171753, 113.842206450509, 123.008873117175), .Dim = 4L, .Dimnames = structure(list(N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = 'N'), class = 'mtable'), `V:N` = structure(c(79.5323303457107, 86.1989970123773, 69.7732394366197, 98.0323303457106, 108.032330345711, 89.1989970123773, 114.198997012377, 116.698997012377, 110.365663679044, 124.365663679044, 126.365663679044, 118.032330345711), .Dim = 3:4, .Dimnames = structure(list(V = c('Golden.rain', 'Marvellous', 'Victory'), N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = c('V', 'N')), class = 'mtable')), .Names = c('N', 'V:N')));c(argv[[1]],argv[[2]]);");
     }
@@ -543,6 +543,8 @@ public class TestBuiltin_c extends TestBase {
 
         // names vector created by combine cannot be temporary
         assertEval("{ x<-c(a=42); y<-c(b=7); z<-c(x,y); w<-names(z); w[[1]]<-\"c\"; z }");
+
+        assertEval("typeof(c(substitute(graphics::par), list(as.symbol('a'))))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
index 82d71854d968bd8b5b0084273e5fe17026599329..4f598802c30f2be8ad7db72b85954c3181e5b4c3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cbind.java
@@ -181,5 +181,8 @@ public class TestBuiltin_cbind extends TestBase {
         assertEval("dput(cbind(c(NULL, NULL), integer(0)))");
         assertEval("dput(cbind(integer(0)))");
         assertEval("dput(cbind(integer(0), NULL, NULL))");
+        // FIXME FastR wrongly adds dimnames to the result
+        assertEval(Ignored.ImplementationError, "dput(cbind(substitute(graphics::par), list(as.symbol('a'))))");
+        assertEval("typeof(cbind(substitute(graphics::par), list(as.symbol('a'))))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ceiling.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ceiling.java
index a9b34b32a401376b65596567f2a082dddabb4930..873db5bf320d576af2520e8837c3903669fc97f4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ceiling.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ceiling.java
@@ -62,7 +62,8 @@ public class TestBuiltin_ceiling extends TestBase {
         assertEval("{ ceiling(c(0.2,-3.4,NA,0/0,1/0)) }");
         assertEval("{ typeof(ceiling(42L)); }");
         assertEval("{ typeof(ceiling(TRUE)); }");
-        assertEval("{ trunc(1+1i); }");
-        assertEval("{ trunc(\"aaa\"); }");
+        // not implemented for complex in GNU R
+        assertEvalFastR("{ ceiling(1.1+1.9i); }", "2+2i");
+        assertEval("{ ceiling(\"aaa\"); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_chol.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_chol.java
index e7ca722d15a7ba8960953433ee78b49699227bda..93f784559e835cd42fec4cd0bca9a37f44affdc1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_chol.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_chol.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -29,6 +29,10 @@ public class TestBuiltin_chol extends TestBase {
         assertEval("{ chol(1) }");
         assertEval("{ round( chol(10), digits=5) }");
         assertEval("{ m <- matrix(c(5,1,1,3),2) ; round( chol(m), digits=5 ) }");
-        assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ m <- matrix(c(5,-5,-5,3),2,2) ; chol(m) }");
+        // Error messages differ
+        // Expected output: Error in chol.default(m) :
+        // the leading minor of order 2 is not positive definite
+        // FastR output: Error in chol.default(m) : error code 2 from Lapack routine 'dpotrf'
+        assertEval(Output.IgnoreErrorMessage, "{ m <- matrix(c(5,-5,-5,3),2,2) ; chol(m) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cnoquote.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cnoquote.java
index b8b3bab3bf4b875ffd8dae162e2e33729b78d5fe..4f40040655e0ca9443feea40759add75ec9b524e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cnoquote.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cnoquote.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.
  */
@@ -20,7 +20,9 @@ public class TestBuiltin_cnoquote extends TestBase {
 
     @Test
     public void testcnoquote1() {
-        assertEval(Ignored.Unknown,
+        // FIXME ArrayIndexOutOfBoundsException: 0
+        // com.oracle.truffle.r.runtime.data.RDoubleVector.getDataAt(RDoubleVector.java:127)
+        assertEval(Ignored.ImplementationError,
                         "argv <- structure(list(structure(c('.', '.', '|', '.', '.', '|',     '.', '.'), .Dim = c(2L, 4L), .Dimnames = list(NULL, c('',     '', '', '')), class = 'noquote')), .Names = '');" +
                                         "do.call('c.noquote', argv)");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colSums.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colSums.java
index 9bd8089dc09d5ce4ebd46847a95652bdd6fa4f1a..62fb86be0abaa079ceb1156f11fa2f980080412d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colSums.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_colSums.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -49,7 +49,10 @@ public class TestBuiltin_colSums extends TestBase {
 
     @Test
     public void testcolSums7() {
-        assertEval(Ignored.Unknown,
+        // FIXME results slightly differ for low-exponent values - ImplementationError for now
+        // Expected output: [1] 0.000000e+00 0.000000e+00 1.013412e-12 6.002665e-11
+        // FastR output: [1] 0.000000e+00 0.000000e+00 1.818989e-12 5.820766e-11
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(c(-7.5, -6.5, -5.5, -4.5, -3.5, -2.5, -1.5, -0.5, 0.5, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5, 7.5, -421.875, -274.625, -166.375, -91.125, -42.875, -15.625, -3.375, -0.125, 0.125, 3.375, 15.625, 42.875, 91.125, 166.375, 274.625, 421.875, -9187.5, -2866.5, -445.499999999999, -4.5, -283.5, -562.5, -541.5, -220.5, 220.5, 541.5, 562.5, 283.5, 4.49999999999999, 445.5, 2866.5, 9187.5, -139741.875, -4844.38499999995, -10122.255, -28872.045, -28539.315, -15800.625, -4325.535, -178.605, 178.605, 4325.535, 15800.625, 28539.315, 28872.045, 10122.255, 4844.38500000001, 139741.875), .Dim = c(16L, 4L)), 16, 4, FALSE); .Internal(colSums(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_comment.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_comment.java
index 40e1843d9760879ddaabffc88a0f43760e0030d1..71ef49ad4a35ab98e2f396b7c672334b6343d93b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_comment.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_comment.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.
  */
@@ -19,22 +19,27 @@ public class TestBuiltin_comment extends TestBase {
 
     @Test
     public void testcomment1() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL); .Internal(comment(argv[[1]]))");
+        // FIXME RInternalError: not implemented: .Internal comment
+        assertEval(Ignored.Unimplemented, "argv <- list(NULL); .Internal(comment(argv[[1]]))");
     }
 
     @Test
     public void testcomment2() {
-        assertEval(Ignored.Unknown,
+        // FIXME RInternalError: not implemented: .Internal comment
+        assertEval(Ignored.Unimplemented,
                         "argv <- list(structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0'))); .Internal(comment(argv[[1]]))");
     }
 
     @Test
     public void testcomment3() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(comment(argv[[1]]))");
+        // FIXME RInternalError: not implemented: .Internal comment
+        assertEval(Ignored.Unimplemented, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L))); .Internal(comment(argv[[1]]))");
     }
 
     @Test
     public void testcomment4() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1:12, .Dim = 3:4, comment = c('This is my very important data from experiment #0234', 'Jun 5, 1998'))); .Internal(comment(argv[[1]]))");
+        // FIXME RInternalError: not implemented: .Internal comment
+        assertEval(Ignored.Unimplemented,
+                        "argv <- list(structure(1:12, .Dim = 3:4, comment = c('This is my very important data from experiment #0234', 'Jun 5, 1998'))); .Internal(comment(argv[[1]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_commentassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_commentassign.java
index d6da6d0b4aae3dff1db2450f998923f0d3a05b4d..1d4f6dcc68f0b88de0bcf6e199106b3c1c1d233b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_commentassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_commentassign.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.
  */
@@ -19,17 +19,20 @@ public class TestBuiltin_commentassign extends TestBase {
 
     @Test
     public void testcommentassign1() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR output: Error: there is no .Internal function 'comment<-'
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(1:12, .Dim = 3:4, comment = c('This is my very important data from experiment #0234', 'Jun 5, 1998')), c('This is my very important data from experiment #0234', 'Jun 5, 1998')); .Internal(`comment<-`(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcommentassign2() {
-        assertEval(Ignored.Unknown, "argv <- list(character(0), NULL); .Internal(`comment<-`(argv[[1]], argv[[2]]))");
+        // FIXME FastR output: Error: there is no .Internal function 'comment<-'
+        assertEval(Ignored.ImplementationError, "argv <- list(character(0), NULL); .Internal(`comment<-`(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testcommentassign3() {
-        assertEval(Ignored.Unknown, "argv <- list(logical(0), NULL); .Internal(`comment<-`(argv[[1]], argv[[2]]))");
+        // FIXME FastR output: Error: there is no .Internal function 'comment<-'
+        assertEval(Ignored.ImplementationError, "argv <- list(logical(0), NULL); .Internal(`comment<-`(argv[[1]], argv[[2]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cos.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cos.java
index fbfc4d441f65b05d66db2b41f1c9fec1717e0ad4..2f7a62b088e1defdf2ca598d43111327466fe74d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cos.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_cos.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -34,7 +34,10 @@ public class TestBuiltin_cos extends TestBase {
 
     @Test
     public void testcos4() {
-        assertEval(Ignored.Unknown, "argv <- list(Inf);cos(argv[[1]]);");
+        // FIXME Missing warning about NaN in FastR:
+        // Warning message:
+        // In cos(argv[[1]]) : NaNs produced
+        assertEval(Output.MissingWarning, "argv <- list(Inf);cos(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
index 07cbdc0b4b73033d48b57d03fa4e3739162269c3..ece53d8cd2e0bf1e6903bf60544c520ee9e74e29 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_crossprod.java
@@ -56,9 +56,7 @@ public class TestBuiltin_crossprod extends TestBase {
 
     @Test
     public void testcrossprod8() {
-        // FIXME FastR ignores .Dimnames (docs say to keep them)
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(-0.0972759604917099, -0.0972759604917099, -0.197781705719934, -0.197781705719934, -0.258476920906799, -0.258476920906799, -0.31681058743414, -0.31681058743414, -0.36711291168933, -0.36711291168933, -0.386611727075222, -0.386611727075222, -0.339690730499459, -0.33969073049946, -0.392353467475584, -0.392353467475584, -0.277328754578855, -0.277328754578855, -0.062581948827679, -0.062581948827679, 0.204605005658209, 0.204605005658209, 0.32860008733551, 0.32860008733551, 0.504748197638673, 0.504748197638673, 0.0398546163039329, 0.039854616303933, -0.269613788250837, -0.269613788250837, -0.312096598983548, -0.312096598983548, 0.0190548270250438, 0.0190548270250438, 0.270521530002251, 0.270521530002251), .Dim = c(12L, 3L)), structure(c(-2.82631170793264, -2.82631170793264, -3.89457420977924, -3.89457420977924, -3.62818861156626, -3.62818861156626, -2.72530862462141, -2.72530862462141, -1.437640468988, -1.437640468988, -0.811701520293695, -0.811701520293695, 14291.543903102, 14291.543903102, 13346.8386233407, 13346.8386233407, 8863.44390274002, 8863.44390274002, 4080.15117667984, 4080.15117667984, 979.818149952962, 979.818149952962, 296.593928028368, 296.593928028368), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('Vm', 'K')))); .Internal(crossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(-0.0972759604917099, -0.0972759604917099, -0.197781705719934, -0.197781705719934, -0.258476920906799, -0.258476920906799, -0.31681058743414, -0.31681058743414, -0.36711291168933, -0.36711291168933, -0.386611727075222, -0.386611727075222, -0.339690730499459, -0.33969073049946, -0.392353467475584, -0.392353467475584, -0.277328754578855, -0.277328754578855, -0.062581948827679, -0.062581948827679, 0.204605005658209, 0.204605005658209, 0.32860008733551, 0.32860008733551, 0.504748197638673, 0.504748197638673, 0.0398546163039329, 0.039854616303933, -0.269613788250837, -0.269613788250837, -0.312096598983548, -0.312096598983548, 0.0190548270250438, 0.0190548270250438, 0.270521530002251, 0.270521530002251), .Dim = c(12L, 3L)), structure(c(-2.82631170793264, -2.82631170793264, -3.89457420977924, -3.89457420977924, -3.62818861156626, -3.62818861156626, -2.72530862462141, -2.72530862462141, -1.437640468988, -1.437640468988, -0.811701520293695, -0.811701520293695, 14291.543903102, 14291.543903102, 13346.8386233407, 13346.8386233407, 8863.44390274002, 8863.44390274002, 4080.15117667984, 4080.15117667984, 979.818149952962, 979.818149952962, 296.593928028368, 296.593928028368), .Dim = c(12L, 2L), .Dimnames = list(NULL, c('Vm', 'K')))); .Internal(crossprod(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -76,4 +74,9 @@ public class TestBuiltin_crossprod extends TestBase {
 
         assertEval(Output.ImprovedErrorContext, "{ crossprod('asdf', matrix(1:6, ncol=2)) }");
     }
+
+    @Test
+    public void testCrossprodDimnames() {
+        assertEval("{ crossprod(structure(1:9, .Dim=c(3L,3L), .Dimnames=list(c('a', 'b', 'c'), c('A', 'B', 'C'))), structure(1:9, .Dim=c(3L,3L), .Dimnames=list(c('d', 'e', 'f'), c('D', 'E', 'F')))) }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
index 3dcdec562dc272a329ddc5016aba3bd67cd42e27..f5cfc992142cb9d56faa411f1b19e61ba2bd8048 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_deriv.java
@@ -197,5 +197,4 @@ public class TestBuiltin_deriv extends TestBase {
         assertEval("(df <- deriv(1, \"x\"));df(0)");
         assertEval("x<-1;(df <- deriv(x, \"x\"));df(0)");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_digamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_digamma.java
index 143dd8f317cca17573338c33f40569b878bf633f..1a657cc4bf329d4324038894b286c1140b85ce62 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_digamma.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_digamma.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -19,14 +19,12 @@ public class TestBuiltin_digamma extends TestBase {
 
     @Test
     public void testdigamma1() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(3.80516394437114, 12.8051639443711, 15.8051639443711, 6.80516394437114, 6.80516394437114, 14.8051639443711, 21.8051639443711, 23.8051639443711, 7.80516394437114, 7.80516394437114, 16.8051639443711, 8.80516394437114, 15.8051639443711, 7.80516394437114, 33.8051639443711, 54.8051639443711, 58.8051639443711, 15.8051639443711, 17.8051639443711, 17.8051639443711, 18.8051639443711, 41.8051639443711, 44.8051639443711, 47.8051639443711, 9.80516394437114, 24.8051639443711, 24.8051639443711, 29.8051639443711, 35.8051639443711, 37.8051639443711, 39.8051639443711, 4.80516394437114, 6.80516394437114, 12.8051639443711, 25.8051639443711, 46.8051639443711, 6.80516394437114, 7.80516394437114, 7.80516394437114, 10.8051639443711, 14.8051639443711, 24.8051639443711, 26.8051639443711, 33.8051639443711, 54.8051639443711, 55.8051639443711, 6.80516394437114, 6.80516394437114, 12.8051639443711, 18.8051639443711, 20.8051639443711, 9.80516394437114, 14.8051639443711, 15.8051639443711, 21.8051639443711, 48.8051639443711, 49.8051639443711, 61.8051639443711, 82.8051639443711, 3.80516394437114, 1.80516394437114, 3.80516394437114, 4.80516394437114, 6.80516394437114, 11.8051639443711, 15.8051639443711, 22.8051639443711, 37.8051639443711, 41.8051639443711, 7.80516394437114, 18.8051639443711, 68.8051639443711, 1.80516394437114, 1.80516394437114, 3.80516394437114, 8.80516394437114, 12.8051639443711, 13.8051639443711, 1.80516394437114, 1.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 12.8051639443711, 18.8051639443711, 4.80516394437114, 5.80516394437114, 23.8051639443711, 31.8051639443711, 37.8051639443711, 9.80516394437114, 1.80516394437114, 2.80516394437114, 6.80516394437114, 8.80516394437114, 17.8051639443711, 28.8051639443711, 1.80516394437114, 31.8051639443711, 11.8051639443711, 15.8051639443711, 28.8051639443711, 42.8051639443711, 70.8051639443711, 26.8051639443711, 11.8051639443711, 12.8051639443711, 21.8051639443711, 34.8051639443711, 6.80516394437114, 8.80516394437114, 1.80516394437114, 2.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 8.80516394437114, 12.8051639443711, 16.8051639443711, 6.80516394437114, 15.8051639443711, 7.80516394437114, 7.80516394437114, 8.80516394437114, 29.8051639443711, 1.80516394437114, 6.80516394437114, 15.8051639443711, 3.80516394437114, 3.80516394437114, 4.80516394437114, 9.80516394437114, 11.8051639443711, 13.8051639443711, 2.80516394437114, 2.80516394437114, 10.8051639443711, 23.8051639443711, 4.80516394437114, 4.80516394437114, 6.80516394437114, 16.8051639443711, 19.8051639443711, 23.8051639443711, 38.8051639443711), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146')));digamma(argv[[1]]);");
+        assertEval("argv <- list(structure(c(3.80516394437114, 12.8051639443711, 15.8051639443711, 6.80516394437114, 6.80516394437114, 14.8051639443711, 21.8051639443711, 23.8051639443711, 7.80516394437114, 7.80516394437114, 16.8051639443711, 8.80516394437114, 15.8051639443711, 7.80516394437114, 33.8051639443711, 54.8051639443711, 58.8051639443711, 15.8051639443711, 17.8051639443711, 17.8051639443711, 18.8051639443711, 41.8051639443711, 44.8051639443711, 47.8051639443711, 9.80516394437114, 24.8051639443711, 24.8051639443711, 29.8051639443711, 35.8051639443711, 37.8051639443711, 39.8051639443711, 4.80516394437114, 6.80516394437114, 12.8051639443711, 25.8051639443711, 46.8051639443711, 6.80516394437114, 7.80516394437114, 7.80516394437114, 10.8051639443711, 14.8051639443711, 24.8051639443711, 26.8051639443711, 33.8051639443711, 54.8051639443711, 55.8051639443711, 6.80516394437114, 6.80516394437114, 12.8051639443711, 18.8051639443711, 20.8051639443711, 9.80516394437114, 14.8051639443711, 15.8051639443711, 21.8051639443711, 48.8051639443711, 49.8051639443711, 61.8051639443711, 82.8051639443711, 3.80516394437114, 1.80516394437114, 3.80516394437114, 4.80516394437114, 6.80516394437114, 11.8051639443711, 15.8051639443711, 22.8051639443711, 37.8051639443711, 41.8051639443711, 7.80516394437114, 18.8051639443711, 68.8051639443711, 1.80516394437114, 1.80516394437114, 3.80516394437114, 8.80516394437114, 12.8051639443711, 13.8051639443711, 1.80516394437114, 1.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 12.8051639443711, 18.8051639443711, 4.80516394437114, 5.80516394437114, 23.8051639443711, 31.8051639443711, 37.8051639443711, 9.80516394437114, 1.80516394437114, 2.80516394437114, 6.80516394437114, 8.80516394437114, 17.8051639443711, 28.8051639443711, 1.80516394437114, 31.8051639443711, 11.8051639443711, 15.8051639443711, 28.8051639443711, 42.8051639443711, 70.8051639443711, 26.8051639443711, 11.8051639443711, 12.8051639443711, 21.8051639443711, 34.8051639443711, 6.80516394437114, 8.80516394437114, 1.80516394437114, 2.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 6.80516394437114, 8.80516394437114, 12.8051639443711, 16.8051639443711, 6.80516394437114, 15.8051639443711, 7.80516394437114, 7.80516394437114, 8.80516394437114, 29.8051639443711, 1.80516394437114, 6.80516394437114, 15.8051639443711, 3.80516394437114, 3.80516394437114, 4.80516394437114, 9.80516394437114, 11.8051639443711, 13.8051639443711, 2.80516394437114, 2.80516394437114, 10.8051639443711, 23.8051639443711, 4.80516394437114, 4.80516394437114, 6.80516394437114, 16.8051639443711, 19.8051639443711, 23.8051639443711, 38.8051639443711), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140', '141', '142', '143', '144', '145', '146')));digamma(argv[[1]]);");
     }
 
     @Test
     public void testdigamma2() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(9.16602330897621, 9.16602330897621, 1.16602330897621, 1.16602330897621, 3.16602330897621, 3.16602330897621, 6.16602330897621, 6.16602330897621, 6.16602330897621, 6.16602330897621, 2.16602330897621, 2.16602330897621, 8.16602330897621, 8.16602330897621, 1.16602330897621, 1.16602330897621, 7.16602330897621, 7.16602330897621, 19.1660233089762, 19.1660233089762, 2.16602330897621, 2.16602330897621), .Names = c('1', '1.1', '2', '2.1', '3', '3.1', '4', '4.1', '5', '5.1', '6', '6.1', '7', '7.1', '8', '8.1', '9', '9.1', '10', '10.1', '11', '11.1')));digamma(argv[[1]]);");
+        assertEval("argv <- list(structure(c(9.16602330897621, 9.16602330897621, 1.16602330897621, 1.16602330897621, 3.16602330897621, 3.16602330897621, 6.16602330897621, 6.16602330897621, 6.16602330897621, 6.16602330897621, 2.16602330897621, 2.16602330897621, 8.16602330897621, 8.16602330897621, 1.16602330897621, 1.16602330897621, 7.16602330897621, 7.16602330897621, 19.1660233089762, 19.1660233089762, 2.16602330897621, 2.16602330897621), .Names = c('1', '1.1', '2', '2.1', '3', '3.1', '4', '4.1', '5', '5.1', '6', '6.1', '7', '7.1', '8', '8.1', '9', '9.1', '10', '10.1', '11', '11.1')));digamma(argv[[1]]);");
     }
 
     @Test
@@ -36,7 +34,7 @@ public class TestBuiltin_digamma extends TestBase {
 
     @Test
     public void testdigamma4() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));digamma(argv[[1]]);");
+        assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));digamma(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimnamesassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimnamesassign.java
index f592d11f570e6158b74a8d0baa19023e79463866..38c358a69d3f396ccfdde6201cc6ac9a0ebdf000 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimnamesassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimnamesassign.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.
  */
@@ -96,4 +96,10 @@ public class TestBuiltin_dimnamesassign extends TestBase {
     public void testDimnamesAssign() {
         assertEval("{ x<-data.frame(c(1,2),c(3,4)); dimnames(x) <- list(c(\"A\", \"B\"), c(\"C\", \"D\")); x }");
     }
+
+    @Test
+    public void testDimnamesElementAssign() {
+        assertEval("{ x<-matrix(12,3,4); dimnames(x)[[2]]<-c('a','b','c','d'); x }");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dir.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dir.java
index ae7e5d9c4f8d6c185e88c9d1e4ae948a9bffa03b..c5b3d2c970c6cd4399f282a9a4cbf6346b6e20b3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dir.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dir.java
@@ -20,6 +20,6 @@ public class TestBuiltin_dir extends TestBase {
 
     @Test
     public void testdir1() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(path = '.', pattern = 'myTst_.*tar[.]gz$'),     .Names = c('path', 'pattern'));do.call('dir', argv)");
+        assertEval("argv <- structure(list(path = '.', pattern = 'myTst_.*tar[.]gz$'),     .Names = c('path', 'pattern'));do.call('dir', argv)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_docall.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_docall.java
index c0003b48744895d87218edb6e67044f4c97b3992..0f496903658c8919cac514ad4ff868f32aaf52e6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_docall.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_docall.java
@@ -43,5 +43,10 @@ public class TestBuiltin_docall extends TestBase {
         assertEval("{ e <- new.env(); assign('foo', function() 42, e); foo <- function(x) 1; do.call('foo', list(), envir=e); }");
         assertEval("{ e <- new.env(); assign('foo', 42, e); foo <- function(x) 1; do.call('foo', list(), envir=e); }");
         assertEval("{ do.call('+', list(data.frame(1), data.frame(2)), envir = new.env()); do.call('assign', list('a',2,new.env()), envir = new.env()); }");
+
+        assertEval("{ boo <- function(c) ls(parent.frame(2)); foo <- function(a,b) boo(a); bar <- function(x,z) do.call('foo', list(1,2)); bar() }");
+        assertEval("{ boo <- function(c) ls(parent.frame(2)); foo <- function(a,b) boo(a); bar <- function(x,z) do.call('foo', list(parse(text='goo()'),2)); bar() }");
+        assertEval("{ boo <- function(c) ls(parent.frame(3)); foo <- function(a,b) boo(a); bar <- function(x,z) do.call('foo', list(parse(text='goo()'),2)); baz <- function(bazX) bar(bazX,1); baz(); }");
+        assertEval("{ f1 <- function(a) ls(parent.frame(2)); f2 <- function(b) f1(b); f3 <- function(c) f2(c); f4 <- function(d) do.call('f3', list(d)); f4(42); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dqr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dqr.java
new file mode 100644
index 0000000000000000000000000000000000000000..20fbc5bba758da0032fc387b4528b797258e17af
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dqr.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+// Checkstyle: stop line length check
+public class TestBuiltin_dqr extends TestBase {
+
+    @Test
+    public void testdqrdc2() {
+        assertEval(Ignored.OutputFormatting, ".Fortran(.F_dqrdc2, 1, 1L, 1L, 1L, 1, 1L, 1, 1L, 1)");
+    }
+
+    @Test
+    public void testdqrcf() {
+        assertEval(Ignored.OutputFormatting, ".Fortran(.F_dqrcf, 1, 1L, 1L, 1, 1, 1L, 1, 1L)");
+    }
+
+    @Test
+    public void testdqrqty() {
+        assertEval(".Fortran(.F_dqrqty, 1, 1L, 1L, 1, 1, 1L, qty=1)");
+    }
+
+    @Test
+    public void testdqrqy() {
+        assertEval(".Fortran(.F_dqrqy, 1, 1L, 1L, 1, 1, 1L, 1)");
+    }
+
+    @Test
+    public void testdqrrsd() {
+        assertEval(".Fortran(.F_dqrrsd, 1, 1L, 1L, 1, 1, 1L, 1)");
+    }
+
+    @Test
+    public void testdqrxb() {
+        assertEval(".Fortran(.F_dqrxb, 1, 1L, 1L, 1, 1, 1L, 1)");
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_encodeString.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_encodeString.java
index d9bb1b69a6380ac4daec11cab65114df7443527d..6f0d875ceb61aedff8536e61195001ab6d670712 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_encodeString.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_encodeString.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -39,7 +39,8 @@ public class TestBuiltin_encodeString extends TestBase {
 
     @Test
     public void testencodeString7() {
-        assertEval(Ignored.Unknown, "argv <- list('ab\\bc\\ndef', 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
+        // FIXME No \b and \n encoding done in FastR
+        assertEval(Ignored.ImplementationError, "argv <- list('ab\\bc\\ndef', 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
@@ -49,30 +50,30 @@ public class TestBuiltin_encodeString extends TestBase {
 
     @Test
     public void testencodeString9() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure('integer(0)', .Names = 'c0', row.names = character(0)), 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
+        assertEval("argv <- list(structure('integer(0)', .Names = 'c0', row.names = character(0)), 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
     public void testencodeString10() {
-        assertEval(Ignored.Unknown,
+        // FIXME No \ to \\ encoding done
+        assertEval(Ignored.ImplementationError,
                         "argv <- list('\\\'class\\\' is a reserved slot name and cannot be redefined', 0L, '\\\'', 0L, FALSE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
     public void testencodeString11() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(character(0), .Dim = c(0L, 0L)), 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
+        assertEval("argv <- list(structure(character(0), .Dim = c(0L, 0L)), 0L, '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
     public void testencodeString12() {
-        assertEval(Ignored.Unknown, "argv <- list(character(0), logical(0), '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
+        // docs mention that width arg is integer so logical(0) is correctly refused by FastR
+        assertEval(Ignored.ReferenceError, "argv <- list(character(0), logical(0), '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
     public void testencodeString13() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure('integer(0)', .Names = 'c0', row.names = character(0)), structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
+        assertEval("argv <- list(structure('integer(0)', .Names = 'c0', row.names = character(0)), structure(list(c0 = structure(integer(0), .Label = character(0), class = 'factor')), .Names = 'c0', row.names = character(0), class = structure('integer(0)', .Names = 'c0')), '', 0L, TRUE); .Internal(encodeString(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java
index d1b9210eb8a4806f224ceb5c0a09bc3912f25a14..90624c90873ac5ec3374d09205b4ed43b13e6315 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_eval.java
@@ -59,11 +59,13 @@ public class TestBuiltin_eval extends TestBase {
         assertEval("a <- 1; lang <- quote(list(a)); eval(lang, NULL, NULL)");
         assertEval("a <- 1; lang <- quote(list(a)); eval(lang, new.env(), new.env())");
         assertEval(Output.IgnoreErrorMessage, "y <- 2; x <- 2 ; eval(quote(x+y), c(-1, -2))");
+
+        // note: 'with' is a oneliner builtin calling into eval
+        assertEval("{ df <- list(a=c(1,2,3), b=c(3,4,5)); df$c <- with(df, a^2); df; }");
     }
 
     @Test
     public void testReturnInEvalExpr() {
         assertEval("f1 <- function(x) { eval(quote(if(x>2){return()}else 1)); 10 };f1(5);f1(0)");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java
index 3745256f0428282c4d0cd11142617b333cfdd409..6ea1535f07318381a9899a42ac45ecbf91db6918 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_extract_replace.java
@@ -48,4 +48,9 @@ public class TestBuiltin_extract_replace extends TestBase {
         assertEval("e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1[[1]]==e1[[1]]");
         assertEval(Ignored.OutputFormatting, "e1 <- expression(x^2); l1 <- quote(y^2); l1[1] <- e1; l1");
     }
+
+    @Test
+    public void replaceWithPositionNames() {
+        assertEval("{ foo <- function(x, idx) { x[idx] <- F; x }; foo(c(T,T,T,T), structure(c('a'), .Names = c('a'))); r <- foo(c(T,T,T,T), structure(c('a', 'b'), .Names = c('a', 'b'))); r }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_floor.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_floor.java
index 39355fc4872fbb9ec404f8c1c343e6f0902ccf57..3ecc9803b79a8e09070eefaa7cfd2e6c7e9bbb52 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_floor.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_floor.java
@@ -67,7 +67,8 @@ public class TestBuiltin_floor extends TestBase {
         assertEval("{ floor(c(0.2,-3.4,NA,0/0,1/0)) }");
         assertEval("{ typeof(floor(42L)); }");
         assertEval("{ typeof(floor(TRUE)); }");
-        assertEval("{ trunc(1+1i); }");
-        assertEval("{ trunc(\"aaa\"); }");
+        // not implemented for complex in GNU R
+        assertEvalFastR("{ floor(1.1+1.9i); }", "1+1i");
+        assertEval("{ floor(\"aaa\"); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java
index c426128a20ebfc0bddddf0ba0f309337c5c31fcf..80326152032cc3ce626d8515c6e1cd03b8773f53 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_format.java
@@ -294,5 +294,10 @@ public class TestBuiltin_format extends TestBase {
         assertEval("{ format(c(7.42,42.7)) }");
         assertEval("{ format(c(7.42,42.7,NA)) }");
         assertEval("{ .Internal(format(.GlobalEnv,FALSE,NA,0,0,3,TRUE,NA,'.')) }");
+        assertEval("{ format(1.1, scientific=TRUE) }");
+        assertEval("{ format(1.1, scientific=FALSE) }");
+        assertEval("{ format(1.1, scientific=c(TRUE, FALSE)) }");
+        assertEval("{ format(1.1, scientific=-10) }");
+        assertEval("{ format(1.1, scientific=c(-10, 1)) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java
index 23276863358730e81aaf2c0afdfbdc7958683694..3a9706a4c6cf7f6519f2983651e2cee5cb02e1f6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatC.java
@@ -19,9 +19,7 @@ public class TestBuiltin_formatC extends TestBase {
 
     @Test
     public void testformatC1() {
-        // FIXME FastR: the third arg "1" is output into 6 characters instead of 10
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(c(3.14159265358979, 3.1415926535898, 1), 'double', 10, 4L, 'g', '', c(12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
+        assertEval("argv <- list(c(3.14159265358979, 3.1415926535898, 1), 'double', 10, 4L, 'g', '', c(12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
     @Test
@@ -32,16 +30,12 @@ public class TestBuiltin_formatC extends TestBase {
 
     @Test
     public void testformatC3() {
-        // FIXME Similar problem to testformatC1
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(1.5, 13.3414265412268, 1e-15, 8, 1, 500, 28), .Dim = c(7L, 1L), .Dimnames = list(c('m.ship.expon.', 'objective', 'tolerance', 'iterations', 'converged', 'maxit', 'n'), ' ')), 'double', 8L, 7L, 'g', '', c(15L, 15L, 15L, 15L, 15L, 15L, 15L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
+        assertEval("argv <- list(structure(c(1.5, 13.3414265412268, 1e-15, 8, 1, 500, 28), .Dim = c(7L, 1L), .Dimnames = list(c('m.ship.expon.', 'objective', 'tolerance', 'iterations', 'converged', 'maxit', 'n'), ' ')), 'double', 8L, 7L, 'g', '', c(15L, 15L, 15L, 15L, 15L, 15L, 15L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
     @Test
     public void testformatC4() {
-        // FIXME Similar problem to testformatC2
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(c(1000, 1e+07, 1), 'double', 5, 4L, 'g', '', c(12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
+        assertEval("argv <- list(c(1000, 1e+07, 1), 'double', 5, 4L, 'g', '', c(12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
     @Test
@@ -97,4 +91,11 @@ public class TestBuiltin_formatC extends TestBase {
         assertEval(Ignored.ReferenceError,
                         "argv <- list(structure(c(1962.25, 1962.5, 1962.75, 1963, 1963.25, 1963.5, 1963.75, 1964, 1964.25, 1964.5, 1964.75, 1965, 1965.25, 1965.5, 1965.75, 1966, 1966.25, 1966.5, 1966.75, 1967, 1967.25, 1967.5, 1967.75, 1968, 1968.25, 1968.5, 1968.75, 1969, 1969.25, 1969.5, 1969.75, 1970, 1970.25, 1970.5, 1970.75, 1971, 1971.25, 1971.5, 1971.75), .Tsp = c(1962.25, 1971.75, 4), class = 'ts'), 'double', 1, 4L, 'g', '', c(12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L, 12L)); .Internal(formatC(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
+
+    @Test
+    public void testformatC15() {
+        assertEval(".Internal(formatC(1e-15, \"double\", 1L, 6L, \"g\", \"\", 12))");
+        assertEval("y <- structure(c(2, 14.1776856316985), .Dim = c(2L, 1L), .Dimnames = list(c(\"m.ship.expon.\", \"objective\"), \" \")); formatC(y, digits = 6)");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatinfo.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatinfo.java
index 215aa7c560b6061de71a59f98468c5b7a83fde01..771f3239267c833de99faed7211fac72332a881b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatinfo.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_formatinfo.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.
  */
@@ -19,73 +19,87 @@ public class TestBuiltin_formatinfo extends TestBase {
 
     @Test
     public void testformatinfo1() {
-        assertEval(Ignored.Unknown, "argv <- list(c(0.099999994, 0.2), 7L, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(c(0.099999994, 0.2), 7L, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo2() {
-        assertEval(Ignored.Unknown, "argv <- list(c(0.099999994, 0.2), 6L, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(c(0.099999994, 0.2), 6L, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo3() {
-        assertEval(Ignored.Unknown, "argv <- list(c(Inf, -Inf), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(c(Inf, -Inf), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo4() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(FALSE, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo5() {
-        assertEval(Ignored.Unknown, "argv <- list(3.14159265358979e-10, NULL, 8); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(3.14159265358979e-10, NULL, 8); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo6() {
-        assertEval(Ignored.Unknown, "argv <- list(1e+08, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(1e+08, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo7() {
-        assertEval(Ignored.Unknown, "argv <- list(1e+222, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(1e+222, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo8() {
-        assertEval(Ignored.Unknown, "argv <- list(31.4159265358979, NULL, 8); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(31.4159265358979, NULL, 8); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo9() {
-        assertEval(Ignored.Unknown, "argv <- list(712L, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(712L, NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo10() {
-        assertEval(Ignored.Unknown,
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented,
                         "argv <- list(structure(c(2, 0, 0, 0, 0, 1, 0, 0, 0, 0, 3, 0, 6, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), .Names = c('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y')), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo11() {
-        assertEval(Ignored.Unknown,
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented,
                         "argv <- list(structure(c(-3.14159265358979e-05, 3.14159265358979e-05, -0.000314159265358979, 0.000314159265358979, -0.00314159265358979, 0.00314159265358979, -0.0314159265358979, 0.0314159265358979, -0.314159265358979, 0.314159265358979, -3.14159265358979, 3.14159265358979, -31.4159265358979, 31.4159265358979, -314.159265358979, 314.159265358979, -3141.59265358979, 3141.59265358979, -31415.9265358979, 31415.9265358979, -314159.265358979, 314159.265358979, -1e-05, 1e-05, -1e-04, 1e-04, -0.001, 0.001, -0.01, 0.01, -0.1, 0.1), .Dim = c(2L, 16L)), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo12() {
-        assertEval(Ignored.Unknown, "argv <- list(c(NaN, NA), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- list(c(NaN, NA), NULL, 0L); .Internal(format.info(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testformatinfo14() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(x = complex(real = Inf, imaginary = Inf)),     .Names = 'x');do.call('format.info', argv)");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- structure(list(x = complex(real = Inf, imaginary = Inf)),     .Names = 'x');do.call('format.info', argv)");
     }
 
     @Test
     public void testformatinfo15() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(x = c(complex(real = NaN, imaginary = NaN),     NA)), .Names = 'x');do.call('format.info', argv)");
+        // FIXME RInternalError: not implemented: .Internal format.info
+        assertEval(Ignored.Unimplemented, "argv <- structure(list(x = c(complex(real = NaN, imaginary = NaN),     NA)), .Names = 'x');do.call('format.info', argv)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
index 5f024ba694c048f9f3866a5866703e92d255ba73..b0e512c4b4decec0e2e06a4191e2ea642b9e1cfd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gamma.java
@@ -29,8 +29,7 @@ public class TestBuiltin_gamma extends TestBase {
 
     @Test
     public void testgamma3() {
-        // FIXME RInternalError: not implemented: .Internal beta
-        assertEval(Ignored.Unimplemented, "argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));gamma(argv[[1]]);");
+        assertEval("argv <- list(structure(numeric(0), .Dim = c(0L, 0L)));gamma(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gctorture2.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gctorture2.java
index f9265300f0161e0f3b980d656993184ffd2df545..b2bd1d9da08687eda3ec42aff0d2299d9fb9a324 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gctorture2.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gctorture2.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.
  */
@@ -19,11 +19,13 @@ public class TestBuiltin_gctorture2 extends TestBase {
 
     @Test
     public void testgctorture21() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL, NULL, FALSE); .Internal(gctorture2(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME not implemented: .Internal gctorture2
+        assertEval(Ignored.Unimplemented, "argv <- list(NULL, NULL, FALSE); .Internal(gctorture2(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testgctorture22() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE, FALSE, FALSE); .Internal(gctorture2(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME not implemented: .Internal gctorture2
+        assertEval(Ignored.Unimplemented, "argv <- list(FALSE, FALSE, FALSE); .Internal(gctorture2(argv[[1]], argv[[2]], argv[[3]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_get.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_get.java
index 71ad84e6ef169c30f8eeb6d78d6cec134f20346e..d5064ed832423825d44cac15a7741064b96f12ca 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_get.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_get.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -34,5 +34,8 @@ public class TestBuiltin_get extends TestBase {
         // behavior specific to RS4Object as environment:
         assertEval("setClass('foo', representation(x='numeric')); f <- new('foo'); e <- new.env(); e$x <- 1; attr(f, '.xData') <- e; get('x', envir=f)");
         assertEval("setClass('foo', representation(x='numeric')); f <- new('foo'); e <- new.env(); e$x <- 1; attr(f, '.Data') <- e; get('x', envir=f)");
+
+        assertEval("{x <- 1L; get('x', mode='numeric'); }");
+        assertEval("{x <- 1L; get('x', mode='double'); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_getconst.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_getconst.java
index a8d9de8e23fc52b119de36ff4b62f01e00087d69..4592ad622fd9a31864d8874855b406142d7d568e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_getconst.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_getconst.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.
  */
@@ -19,11 +19,13 @@ public class TestBuiltin_getconst extends TestBase {
 
     @Test
     public void testgetconst1() {
-        assertEval(Ignored.Unknown, "argv <- list(list(list(), NULL), 1); .Internal(getconst(argv[[1]], argv[[2]]))");
+        // FIXME not implemented: .Internal getconst
+        assertEval(Ignored.Unimplemented, "argv <- list(list(list(), NULL), 1); .Internal(getconst(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testgetconst2() {
-        assertEval(Ignored.Unknown, "argv <- list(list(FALSE), 1); .Internal(getconst(argv[[1]], argv[[2]]))");
+        // FIXME not implemented: .Internal getconst
+        assertEval(Ignored.Unimplemented, "argv <- list(list(FALSE), 1); .Internal(getconst(argv[[1]], argv[[2]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gregexpr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gregexpr.java
index 1fc37fe055fe1222de1b19950a1e95e14804934a..1d55ebbc8d048b622032a4ea4790025fdfebdb9e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gregexpr.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gregexpr.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -34,7 +34,8 @@ public class TestBuiltin_gregexpr extends TestBase {
 
     @Test
     public void testgregexpr4() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR ignores useBytes argument value (last argument)
+        assertEval(Ignored.ImplementationError,
                         "argv <- list('éè', '«Latin-1 accented chars»: éè øØ å<Å æ<Æ é éè', FALSE, FALSE, TRUE, TRUE); .Internal(gregexpr(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))");
     }
 
@@ -50,7 +51,8 @@ public class TestBuiltin_gregexpr extends TestBase {
 
     @Test
     public void testgregexpr7() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR ignores useBytes argument value (last argument)
+        assertEval(Ignored.ImplementationError,
                         "argv <- list('éè', '«Latin-1 accented chars»: éè øØ å<Å æ<Æ é éè', TRUE, FALSE, FALSE, TRUE); .Internal(gregexpr(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))");
     }
 
@@ -98,7 +100,10 @@ public class TestBuiltin_gregexpr extends TestBase {
     public void testRegExpr() {
         assertEval("gregexpr(\"e\",c(\"arm\",\"foot\",\"lefroo\", \"bafoobar\"))");
         // NOTE: this is without attributes
-        assertEval(Ignored.Unknown, "gregexpr(\"(a)[^a]\\\\1\", c(\"andrea apart\", \"amadeus\", NA))");
+        // gregexpr help does not comment x == NA and GnuR returns NA
+        // while FastR returns -1
+        // Using ImplementationError for now.
+        assertEval(Ignored.ImplementationError, "gregexpr(\"(a)[^a]\\\\1\", c(\"andrea apart\", \"amadeus\", NA))");
 
         assertEval("{ x<-gregexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=T); as.integer(c(x[[1]], x[[2]])) }");
         assertEval("{ x<-gregexpr(\"foo\", c(\"bar foo foo\", \"foo\"), fixed=F); as.integer(c(x[[1]], x[[2]])) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java
index 83f201d7b1935d729c2a488790cfbd3be5464b24..d5c5148e5700bf77b247ef7607dab95add6a7a71 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_grep.java
@@ -93,9 +93,20 @@ public class TestBuiltin_grep extends TestBase {
         assertEval("{ .Internal(grep(character(), \"7\", F, F, F, F, F, F)) }");
         assertEval("{ .Internal(grep(\"7\", 7, F, F, F, F, F, F)) }");
 
+        // FIXME btw docs do not mention \n handling
+        // ImplementationError for now but might be revised
         // Expected output: integer(0)
         // FastR output: [1] 1
-        assertEval(Ignored.Unknown, "{ grep('^ *$', ' \\n') }");
+        assertEval(Ignored.ImplementationError, "{ grep('^ *$', ' \\n') }");
+
+        assertEval("grep('[(]', ')')");
+        assertEval("grep('[)]', ')')");
+        assertEval("grep('(())', ')')");
+        assertEval("grep('))', ')')");
+        assertEval("grep('))', '))')");
+        assertEval(Output.IgnoreErrorMessage, "grep('([)]', ')')");
+        assertEval(Output.IgnoreErrorMessage, "grep('([(]', ')')");
+        assertEval(Output.IgnoreErrorMessage, "grep('(()', ')')");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
index 6c0ecb1d2d5960deebdb19fb60f2c8c197de3bef..05e8cbecd2e5d7d4cf71e6785fb3ed0811b8eb77 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_gsub.java
@@ -64,7 +64,11 @@ public class TestBuiltin_gsub extends TestBase {
 
     @Test
     public void testgsub10() {
-        assertEval(Ignored.Unknown, "argv <- list('a*', 'x', 'baaac', FALSE, FALSE, FALSE, FALSE); .Internal(gsub(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
+        // FIXME GnuR result appears to be more logical:
+        // Expected output: [1] "xbxcx"
+        // FastR output: [1] "xbxxcx"
+        assertEval(Ignored.ImplementationError,
+                        "argv <- list('a*', 'x', 'baaac', FALSE, FALSE, FALSE, FALSE); .Internal(gsub(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
     @Test
@@ -79,7 +83,10 @@ public class TestBuiltin_gsub extends TestBase {
 
     @Test
     public void testgsub13() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR does not recognize word boundary properly:
+        // Expected output: [1] "|The| |quick| |brown| |èé|"
+        // FastR output: [1] "|The| |quick| |brown| èé"
+        assertEval(Ignored.ImplementationError,
                         "argv <- list('\\\\b', '|', 'The quick brown èé', FALSE, TRUE, FALSE, FALSE); .Internal(gsub(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
 
@@ -165,7 +172,10 @@ public class TestBuiltin_gsub extends TestBase {
 
     @Test
     public void testgsub31() {
-        assertEval(Ignored.Unknown, "argv <- structure(list(pattern = 'a*', replacement = 'x', x = 'baaaac'),     .Names = c('pattern', 'replacement', 'x'));do.call('gsub', argv)");
+        // FIXME GnuR result appears to be more logical:
+        // Expected output: [1] "xbxcx"
+        // FastR output: [1] "xbxxcx"
+        assertEval(Ignored.ImplementationError, "argv <- structure(list(pattern = 'a*', replacement = 'x', x = 'baaaac'),     .Names = c('pattern', 'replacement', 'x'));do.call('gsub', argv)");
     }
 
     @Test
@@ -178,7 +188,8 @@ public class TestBuiltin_gsub extends TestBase {
         assertEval("{ gsub(\"([a-e])\",\"\\\\1\\\\1\", \"prague alley\") }");
         assertEval("{ gsub(\"h\",\"\", c(\"hello\", \"hi\", \"bye\")) }");
         assertEval("{ gsub(\"h\",\"\", c(\"hello\", \"hi\", \"bye\"), fixed=TRUE) }");
-        assertEval(Ignored.Unknown, "{ gsub(\"a\",\"aa\", \"prAgue alley\", ignore.case=TRUE) }");
+        // FIXME not yet implemented: ignoreCase == true
+        assertEval(Ignored.Unimplemented, "{ gsub(\"a\",\"aa\", \"prAgue alley\", ignore.case=TRUE) }");
 
         assertEval("{ .Internal(gsub(7, \"42\", \"7\", F, F, F, F)) }");
         assertEval("{ .Internal(gsub(character(), \"42\", \"7\", F, F, F, F)) }");
@@ -191,6 +202,6 @@ public class TestBuiltin_gsub extends TestBase {
 
         // Expected output: [1] "xaxbx"
         // FastR output: [1] "axxxxxb"
-        assertEval(Ignored.Unknown, "{ gsub(pattern = 'Ä*', replacement = 'x', x = 'aÄÄÄÄÄb', perl = TRUE) }");
+        assertEval(Ignored.ImplementationError, "{ gsub(pattern = 'Ä*', replacement = 'x', x = 'aÄÄÄÄÄb', perl = TRUE) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_iconv.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_iconv.java
index 91ccd99c4a2cc3e073874a733e50c99b7db8f5fe..b06ef8da33a6fdabcc15fc22b44759eca66e6e7d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_iconv.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_iconv.java
@@ -62,18 +62,12 @@ public class TestBuiltin_iconv extends TestBase {
 
     @Test
     public void testiconv8() {
-        // FIXME FastR does not carry extra Rd_tag attr in its output
-        // which is required according to iconv() GnuR docs.
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure('Prediction matrix for soap film smooth', Rd_tag = 'TEXT'), 'UTF-8', 'ASCII', NA_character_, FALSE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))");
+        assertEval("argv <- list(structure('Prediction matrix for soap film smooth', Rd_tag = 'TEXT'), 'UTF-8', 'ASCII', NA_character_, FALSE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))");
     }
 
     @Test
     public void testiconv9() {
-        // FIXME FastR does not carry extra .Names attr in its output
-        // which is required according to iconv() GnuR docs.
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c('Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance'), .Names = c('Q1_MISSING_NONE', 'Q1_MISSING_1', 'Q1_MISSING_2', 'Q1_MISSING_3', 'Q1_MISSING_RANGE', 'Q1_MISSING_LOW', 'Q1_MISSING_HIGH', 'Q1_MISSING_RANGE_1', 'Q1_MISSING_LOW_1', 'Q1_MISSING_HIGH_1')), 'latin1', '', NA_character_, TRUE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))");
+        assertEval("argv <- list(structure(c('Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance', 'Q.1 Opinion of presidents job performance'), .Names = c('Q1_MISSING_NONE', 'Q1_MISSING_1', 'Q1_MISSING_2', 'Q1_MISSING_3', 'Q1_MISSING_RANGE', 'Q1_MISSING_LOW', 'Q1_MISSING_HIGH', 'Q1_MISSING_RANGE_1', 'Q1_MISSING_LOW_1', 'Q1_MISSING_HIGH_1')), 'latin1', '', NA_character_, TRUE, FALSE); .Internal(iconv(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_icuSetCollate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_icuSetCollate.java
index 735fc52f5c82d88aa01765580c59149f90b4394c..eafa476dd22474a0c261b4ba5553469e25fe8f25 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_icuSetCollate.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_icuSetCollate.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.
  */
@@ -19,6 +19,7 @@ public class TestBuiltin_icuSetCollate extends TestBase {
 
     @Test
     public void testicuSetCollate1() {
-        assertEval(Ignored.Unknown, " .Internal(icuSetCollate())");
+        // FIXME RInternalError: not implemented: .Internal icuSetCollate
+        assertEval(Ignored.Unimplemented, " .Internal(icuSetCollate())");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
index 6bbed855deb3945f9858829de9e3eb46294c2859..dda9a52a128486e6d568566eb7f8a0b35ae2b1b4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_inherits.java
@@ -213,5 +213,8 @@ public class TestBuiltin_inherits extends TestBase {
         assertEval("{x <- 10;class(x) <- c(\"a\", \"b\");inherits(x, \"a\", 1) ;}");
 
         assertEval("inherits(NULL, 'NULL')");
+
+        assertEval("inherits(1L, 'numeric')");
+        assertEval("inherits(1L, 'double')");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isarray.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isarray.java
index 70cbafc70bbed98f3596396e5b64181fe9326ea0..000a50537c52fe1c8cd4404e074c2f12df67bb65 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isarray.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isarray.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.
  */
@@ -131,4 +131,9 @@ public class TestBuiltin_isarray extends TestBase {
     public void testisarray23() {
         assertEval("argv <- list(c(0.568, 1.432, -1.08, 1.08));is.array(argv[[1]]);");
     }
+
+    @Test
+    public void testisarrayGenericDispatch() {
+        assertEval("{ is.array.cls <- function(x) 42; is.array(structure(c(1,2), class='cls')); }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java
index 0816c96c8e09e83d1cb86ac897fb05f147cd7887..1dd81fe60904d09a97b1c84ebff1b7e00cdf758c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isfinite.java
@@ -44,7 +44,7 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite6() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1.27861470300044, .Dim = c(1L, 1L), .Dimnames = list('(Intercept)', '(Intercept)')));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(1.27861470300044, .Dim = c(1L, 1L), .Dimnames = list('(Intercept)', '(Intercept)')));is.finite(argv[[1]]);");
     }
 
     @Test
@@ -59,8 +59,7 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite9() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.0147058823529412, 0.0110294117647059, 0.0257352941176471, 0.00735294117647059, 0.0294117647058824, 0.0147058823529412, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.0110294117647059, 0.0147058823529412, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.00735294117647059, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.0147058823529412, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.0183823529411765, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.00367647058823529, 0.00735294117647059, 0.0183823529411765, 0.00735294117647059, 0.00735294117647059, 0.00735294117647059, 0.0147058823529412, 0.0147058823529412, 0.00367647058823529, 0.00367647058823529, 0.0110294117647059, 0.0147058823529412, 0.00735294117647059, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.0183823529411765, 0.0147058823529412, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.0147058823529412, 0.00735294117647059, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.0294117647058824, 0.00367647058823529, 0.0183823529411765, 0.00367647058823529, 0.0110294117647059, 0.0147058823529412, 0.0147058823529412, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00735294117647059, 0.0220588235294118, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529), class = 'table', .Dim = 126L, .Dimnames = structure(list(fe = c('1.6', '1.667', '1.7', '1.733', '1.75', '1.783', '1.8', '1.817', '1.833', '1.85', '1.867', '1.883', '1.917', '1.933', '1.95', '1.967', '1.983', '2', '2.017', '2.033', '2.067', '2.083', '2.1', '2.133', '2.15', '2.167', '2.183', '2.2', '2.217', '2.233', '2.25', '2.267', '2.283', '2.3', '2.317', '2.333', '2.35', '2.367', '2.383', '2.4', '2.417', '2.483', '2.617', '2.633', '2.8', '2.883', '2.9', '3.067', '3.317', '3.333', '3.367', '3.417', '3.45', '3.5', '3.567', '3.6', '3.683', '3.717', '3.733', '3.75', '3.767', '3.817', '3.833', '3.85', '3.883', '3.917', '3.95', '3.966', '3.967', '4', '4.033', '4.05', '4.067', '4.083', '4.1', '4.117', '4.133', '4.15', '4.167', '4.183', '4.2', '4.233', '4.25', '4.267', '4.283', '4.3', '4.317', '4.333', '4.35', '4.366', '4.367', '4.383', '4.4', '4.417', '4.433', '4.45', '4.467', '4.483', '4.5', '4.517', '4.533', '4.55', '4.567', '4.583', '4.6', '4.617', '4.633', '4.65', '4.667', '4.7', '4.716', '4.733', '4.75', '4.767', '4.783', '4.8', '4.817', '4.833', '4.85', '4.883', '4.9', '4.933', '5', '5.033', '5.067', '5.1')), .Names = 'fe')));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.0147058823529412, 0.0110294117647059, 0.0257352941176471, 0.00735294117647059, 0.0294117647058824, 0.0147058823529412, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.0110294117647059, 0.0147058823529412, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.00735294117647059, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00735294117647059, 0.0147058823529412, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.00367647058823529, 0.0183823529411765, 0.00735294117647059, 0.00367647058823529, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.00367647058823529, 0.00735294117647059, 0.0183823529411765, 0.00735294117647059, 0.00735294117647059, 0.00735294117647059, 0.0147058823529412, 0.0147058823529412, 0.00367647058823529, 0.00367647058823529, 0.0110294117647059, 0.0147058823529412, 0.00735294117647059, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.0183823529411765, 0.0147058823529412, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.0147058823529412, 0.00735294117647059, 0.0110294117647059, 0.00735294117647059, 0.00367647058823529, 0.0294117647058824, 0.00367647058823529, 0.0183823529411765, 0.00367647058823529, 0.0110294117647059, 0.0147058823529412, 0.0147058823529412, 0.00367647058823529, 0.0110294117647059, 0.00367647058823529, 0.00735294117647059, 0.0220588235294118, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.0220588235294118, 0.00735294117647059, 0.00735294117647059, 0.00367647058823529, 0.00367647058823529, 0.00735294117647059, 0.0110294117647059, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529, 0.00367647058823529), class = 'table', .Dim = 126L, .Dimnames = structure(list(fe = c('1.6', '1.667', '1.7', '1.733', '1.75', '1.783', '1.8', '1.817', '1.833', '1.85', '1.867', '1.883', '1.917', '1.933', '1.95', '1.967', '1.983', '2', '2.017', '2.033', '2.067', '2.083', '2.1', '2.133', '2.15', '2.167', '2.183', '2.2', '2.217', '2.233', '2.25', '2.267', '2.283', '2.3', '2.317', '2.333', '2.35', '2.367', '2.383', '2.4', '2.417', '2.483', '2.617', '2.633', '2.8', '2.883', '2.9', '3.067', '3.317', '3.333', '3.367', '3.417', '3.45', '3.5', '3.567', '3.6', '3.683', '3.717', '3.733', '3.75', '3.767', '3.817', '3.833', '3.85', '3.883', '3.917', '3.95', '3.966', '3.967', '4', '4.033', '4.05', '4.067', '4.083', '4.1', '4.117', '4.133', '4.15', '4.167', '4.183', '4.2', '4.233', '4.25', '4.267', '4.283', '4.3', '4.317', '4.333', '4.35', '4.366', '4.367', '4.383', '4.4', '4.417', '4.433', '4.45', '4.467', '4.483', '4.5', '4.517', '4.533', '4.55', '4.567', '4.583', '4.6', '4.617', '4.633', '4.65', '4.667', '4.7', '4.716', '4.733', '4.75', '4.767', '4.783', '4.8', '4.817', '4.833', '4.85', '4.883', '4.9', '4.933', '5', '5.033', '5.067', '5.1')), .Names = 'fe')));is.finite(argv[[1]]);");
     }
 
     @Test
@@ -130,8 +129,7 @@ public class TestBuiltin_isfinite extends TestBase {
 
     @Test
     public void testisfinite23() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(-4, 0, 0, 0, 0, 0, 0, -406.725, 41.7955066364795, 0, 0, 0, 0, 0, -1550.79375, 381.717151319926, 49.8228991342168, 0, 0, 0, 0, -1277.325, 224.617432123818, -31.1858918860748, -282.060212912726, 0, 0, 0, -1042.675, 125.261805546114, -29.9849484767744, 164.425554254677, -170.353263600129, 0, 0, -469.696, 26.3795103523805, 4.19691803785862, -3.18974110831568, 0.0462484557378925, 1.46320172717486, 0, -7818, 18.2758880432689, 1.77525956575195, -1.45298766739792, -0.449176219307484, -0.281900648530911, -0.669305080560524), .Dim = c(7L, 7L), .Dimnames = list(c('1947', '1948', '1949', '1950', '1951', '1952', '1953'), c('(Intercept)', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'))));is.finite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(-4, 0, 0, 0, 0, 0, 0, -406.725, 41.7955066364795, 0, 0, 0, 0, 0, -1550.79375, 381.717151319926, 49.8228991342168, 0, 0, 0, 0, -1277.325, 224.617432123818, -31.1858918860748, -282.060212912726, 0, 0, 0, -1042.675, 125.261805546114, -29.9849484767744, 164.425554254677, -170.353263600129, 0, 0, -469.696, 26.3795103523805, 4.19691803785862, -3.18974110831568, 0.0462484557378925, 1.46320172717486, 0, -7818, 18.2758880432689, 1.77525956575195, -1.45298766739792, -0.449176219307484, -0.281900648530911, -0.669305080560524), .Dim = c(7L, 7L), .Dimnames = list(c('1947', '1948', '1949', '1950', '1951', '1952', '1953'), c('(Intercept)', 'GNP.deflator', 'GNP', 'Unemployed', 'Armed.Forces', 'Population', 'Year'))));is.finite(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java
index 59854d0c5001ea9d7d32041a5c5f66c810256dac..7cd26105452f7fdc7f3c046c90fcc8974694cdcd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isinfinite.java
@@ -39,8 +39,7 @@ public class TestBuiltin_isinfinite extends TestBase {
 
     @Test
     public void testisinfinite5() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(80, 80, 75, 62, 62, 62, 62, 62, 58, 58, 58, 58, 58, 58, 50, 50, 50, 50, 50, 56, 70, 27, 27, 25, 24, 22, 23, 24, 24, 23, 18, 18, 17, 18, 19, 18, 18, 19, 19, 20, 20, 20, 89, 88, 90, 87, 87, 87, 93, 93, 87, 80, 89, 88, 82, 93, 89, 86, 72, 79, 80, 82, 91, 42, 37, 37, 28, 18, 18, 19, 20, 15, 14, 14, 13, 11, 12, 8, 7, 8, 8, 9, 15, 15), .Dim = c(21L, 4L), .Dimnames = list(NULL, c('Air.Flow', 'Water.Temp', 'Acid.Conc.', 'stack.loss'))));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(80, 80, 75, 62, 62, 62, 62, 62, 58, 58, 58, 58, 58, 58, 50, 50, 50, 50, 50, 56, 70, 27, 27, 25, 24, 22, 23, 24, 24, 23, 18, 18, 17, 18, 19, 18, 18, 19, 19, 20, 20, 20, 89, 88, 90, 87, 87, 87, 93, 93, 87, 80, 89, 88, 82, 93, 89, 86, 72, 79, 80, 82, 91, 42, 37, 37, 28, 18, 18, 19, 20, 15, 14, 14, 13, 11, 12, 8, 7, 8, 8, 9, 15, 15), .Dim = c(21L, 4L), .Dimnames = list(NULL, c('Air.Flow', 'Water.Temp', 'Acid.Conc.', 'stack.loss'))));is.infinite(argv[[1]]);");
     }
 
     @Test
@@ -85,7 +84,7 @@ public class TestBuiltin_isinfinite extends TestBase {
 
     @Test
     public void testisinfinite14() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(1, 0.5, 0.5, 1), .Dim = c(2L, 2L), .Dimnames = list(c('A', 'B'), c('A', 'B'))));is.infinite(argv[[1]]);");
+        assertEval("argv <- list(structure(c(1, 0.5, 0.5, 1), .Dim = c(2L, 2L), .Dimnames = list(c('A', 'B'), c('A', 'B'))));is.infinite(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ismatrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ismatrix.java
index 05ec35244b01276710464b42b5b15644bae27742..99c4cfb82ead072b84bb6ac8e1455a1e05f507d9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ismatrix.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_ismatrix.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.
  */
@@ -126,4 +126,9 @@ public class TestBuiltin_ismatrix extends TestBase {
     public void testismatrix23() {
         assertEval("argv <- list(0.0597289453377495);do.call('is.matrix', argv)");
     }
+
+    @Test
+    public void testismatrixGenericDispatch() {
+        assertEval("{ is.matrix.cls <- function(x) 42; is.matrix(structure(c(1,2), class='cls')); }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
index 0322c2fb15b31d0f72a46e157d86ae5b640881e2..5354f397e606491a842fc0ba3738fb87bc47503d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java
@@ -253,6 +253,7 @@ public class TestBuiltin_isna extends TestBase {
         assertEval("is.na(data.frame(col1=1:5, col2=c(NA, 1, NA, 2, NA)))");
 
         assertEval("v <- c(a=1,b=1234,c='ff',d='gg'); dim(v) <- c(foo=2,bar=2); dimnames(v) <- list(a=c('foo', 'bar'), n=c('f','g')); is.na(v)");
+        assertEval("{ is.na.cls <- function(x) 42; is.na(structure(c(1,2), class='cls')); }");
 
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java
index 786da412a54b73c17033640145516ba780b74086..4b78f7ebb6be340c7aa6d83d763bf2c01bdea189 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnan.java
@@ -61,4 +61,9 @@ public class TestBuiltin_isnan extends TestBase {
     public void testisnan10() {
         assertEval("argv <- list(structure(c(1, 1, 1, 1, 1, 1), .Dim = 1:3));is.nan(argv[[1]]);");
     }
+
+    @Test
+    public void testisnanGenericDispatch() {
+        assertEval("{ is.nan.cls <- function(x) 42; is.nan(structure(c(1,2), class='cls')); }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnumeric.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnumeric.java
index d7ee33c14408e64ce9000fb56f46c0b1c4be32b3..aa5097ae62482c015b0c894833f62b4fcdd99a83 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnumeric.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isnumeric.java
@@ -24,9 +24,7 @@ public class TestBuiltin_isnumeric extends TestBase {
 
     @Test
     public void testisnumeric2() {
-        // FIXME according to ?is.numeric the 'Date' class should return FALSE from is.numeric()
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(12784, 12874, 12965, 13057, 13149, 13239, 13330, 13422, 13514, 13604, 13695, 13787, 13879, 13970, 14061, 14153, 14245, 14335), class = 'Date'));is.numeric(argv[[1]]);");
+        assertEval("argv <- list(structure(c(12784, 12874, 12965, 13057, 13149, 13239, 13330, 13422, 13514, 13604, 13695, 13787, 13879, 13970, 14061, 14153, 14245, 14335), class = 'Date'));is.numeric(argv[[1]]);");
     }
 
     @Test
@@ -86,10 +84,8 @@ public class TestBuiltin_isnumeric extends TestBase {
 
     @Test
     public void testisnumeric14() {
-        // FIXME according to ?is.numeric the 'POSIXt' class should return FALSE from is.numeric()
-        assertEval(Ignored.ImplementationError, "is.numeric(structure(1L, class = c('POSIXct', 'POSIXt')))");
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(1386439154.20645, 1386469154.20645, 1386499154.20645, 1386529154.20645, 1386559154.20645, 1386589154.20645, 1386619154.20645, 1386649154.20645, 1386679154.20645, 1386709154.20645, 1386739154.20645, 1386769154.20645, 1386799154.20645, 1386829154.20645, 1386859154.20645, 1386889154.20645, 1386919154.20645, 1386949154.20645, 1386979154.20645, 1387009154.20645, 1387039154.20645, 1387069154.20645, 1387099154.20645, 1387129154.20645, 1387159154.20645, 1387189154.20645, 1387219154.20645, 1387249154.20645, 1387279154.20645, 1387309154.20645, 1387339154.20645, 1387369154.20645, 1387399154.20645, 1387429154.20645), class = c('POSIXct', 'POSIXt')));is.numeric(argv[[1]]);");
+        assertEval("is.numeric(structure(1L, class = c('POSIXct', 'POSIXt')))");
+        assertEval("argv <- list(structure(c(1386439154.20645, 1386469154.20645, 1386499154.20645, 1386529154.20645, 1386559154.20645, 1386589154.20645, 1386619154.20645, 1386649154.20645, 1386679154.20645, 1386709154.20645, 1386739154.20645, 1386769154.20645, 1386799154.20645, 1386829154.20645, 1386859154.20645, 1386889154.20645, 1386919154.20645, 1386949154.20645, 1386979154.20645, 1387009154.20645, 1387039154.20645, 1387069154.20645, 1387099154.20645, 1387129154.20645, 1387159154.20645, 1387189154.20645, 1387219154.20645, 1387249154.20645, 1387279154.20645, 1387309154.20645, 1387339154.20645, 1387369154.20645, 1387399154.20645, 1387429154.20645), class = c('POSIXct', 'POSIXt')));is.numeric(argv[[1]]);");
     }
 
     @Test
@@ -124,8 +120,7 @@ public class TestBuiltin_isnumeric extends TestBase {
 
     @Test
     public void testisnumeric21() {
-        // FIXME according to ?is.numeric the 'Date' class should return FALSE from is.numeric()
-        assertEval(Ignored.ImplementationError, "argv <- list(structure(16146, class = 'Date'));is.numeric(argv[[1]]);");
+        assertEval("argv <- list(structure(16146, class = 'Date'));is.numeric(argv[[1]]);");
     }
 
     @Test
@@ -135,7 +130,12 @@ public class TestBuiltin_isnumeric extends TestBase {
 
     @Test
     public void testisnumeric24() {
-        // FIXME according to ?is.numeric the 'Date' class should return FALSE from is.numeric()
-        assertEval(Ignored.ImplementationError, "argv <- list(structure(16352, class = 'Date'));do.call('is.numeric', argv)");
+        assertEval("argv <- list(structure(16352, class = 'Date'));do.call('is.numeric', argv)");
     }
+
+    @Test
+    public void testisnumericGenericDispatch() {
+        assertEval("{ is.numeric.cls <- function(x) 42; is.numeric(structure(c(1,2), class='cls')); }");
+    }
+
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
index 372f103da4a9ef759bf22ef55ce7720bc45dd42f..5a67e9ae37a4a0b85bc1db012f56d7e1ff67f586 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isvector.java
@@ -199,6 +199,7 @@ public class TestBuiltin_isvector extends TestBase {
         assertEval("{is.vector(c(TRUE,FALSE),\"logical\");}");
         assertEval("{x<-1;class(x)<-\"a\";is.vector(x);}");
         assertEval("{x<-1;names(x)<-\"a\";is.vector(x);}");
+        assertEval("is.vector(1L, 'numeric');");
         // FastR produces better error contexts
         assertEval(Output.IgnoreErrorContext, "{is.vector(c(1,2), c(\"sss\", \"dddd\"));}");
         assertEval(Output.IgnoreErrorContext, "{is.vector(c(1,2), TRUE);}");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lchoose.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lchoose.java
index 735053a45db19a92ad8399e5276bd37edb372c0a..eb2c92a864f8a4d875aad02bb1008bbb1cdc913f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lchoose.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lchoose.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.
  */
@@ -19,16 +19,19 @@ public class TestBuiltin_lchoose extends TestBase {
 
     @Test
     public void testlchoose1() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE, FALSE); .Internal(lchoose(argv[[1]], argv[[2]]))");
+        // FIXME not implemented: .Internal lchoose
+        assertEval(Ignored.Unimplemented, "argv <- list(FALSE, FALSE); .Internal(lchoose(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testlchoose2() {
-        assertEval(Ignored.Unknown, "argv <- list(50L, 0:48); .Internal(lchoose(argv[[1]], argv[[2]]))");
+        // FIXME not implemented: .Internal lchoose
+        assertEval(Ignored.Unimplemented, "argv <- list(50L, 0:48); .Internal(lchoose(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testlchoose3() {
-        assertEval(Ignored.Unknown, "argv <- list(0.5, 1:9); .Internal(lchoose(argv[[1]], argv[[2]]))");
+        // FIXME not implemented: .Internal lchoose
+        assertEval(Ignored.Unimplemented, "argv <- list(0.5, 1:9); .Internal(lchoose(argv[[1]], argv[[2]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_length.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_length.java
index 62dee27127dced946709a9b53cb034dd31b42166..d03f279dee4133967964c619cefcf45ba45a898d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_length.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_length.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -210,5 +210,6 @@ public class TestBuiltin_length extends TestBase {
         assertEval("{ length(1:3) }");
         assertEval("length(quote(x))");
         assertEval("length(as.symbol('x'))");
+        assertEval("{ foo <- function(...) length(get('...')); foo(a=1, b=2, c=3, d=4); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
index 72dcf3d5baaa6c8556895dcccbc5151a8d4e6296..8c26d2fcf77a8d06a4f623f76e4d18b4d854e685 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_lgamma.java
@@ -19,15 +19,12 @@ public class TestBuiltin_lgamma extends TestBase {
 
     @Test
     public void testlgamma1() {
-        // FastR: all numbers on a single line and last number has one extra digit
-        assertEval(Ignored.OutputFormatting, "argv <- list(structure(c(2, 1, 1, 1, 3, 1, 1, 1, 4), .Dim = c(3L, 3L)));lgamma(argv[[1]]);");
+        assertEval("argv <- list(structure(c(2, 1, 1, 1, 3, 1, 1, 1, 4), .Dim = c(3L, 3L)));lgamma(argv[[1]]);");
     }
 
     @Test
     public void testlgamma2() {
-        // FastR: both incorrect output numbers and missing column/row headers
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c(2, 3, 2, 1, 4, 4, 7, 2, 11, 11, 15, 10, 7, 8, 13, 12), .Dim = c(4L, 4L), .Dimnames = structure(list(income = c('< 15k', '15-25k', '25-40k', '> 40k'), satisfaction = c('VeryD', 'LittleD', 'ModerateS', 'VeryS')), .Names = c('income', 'satisfaction'))));lgamma(argv[[1]]);");
+        assertEval("argv <- list(structure(c(2, 3, 2, 1, 4, 4, 7, 2, 11, 11, 15, 10, 7, 8, 13, 12), .Dim = c(4L, 4L), .Dimnames = structure(list(income = c('< 15k', '15-25k', '25-40k', '> 40k'), satisfaction = c('VeryD', 'LittleD', 'ModerateS', 'VeryS')), .Names = c('income', 'satisfaction'))));lgamma(argv[[1]]);");
     }
 
     @Test
@@ -52,9 +49,7 @@ public class TestBuiltin_lgamma extends TestBase {
 
     @Test
     public void testlgamma7() {
-        // FastR: missing column headers 1 till 42
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(11.4065045686104, 9.40650456861037, 8.40650456861037, 11.4065045686104, 9.40650456861037, 6.40650456861036, 15.4065045686104, 9.40650456861037, 9.40650456861037, 8.40650456861037, 6.40650456861036, 7.40650456861036, 8.40650456861037, 7.40650456861036, 9.40650456861037, 13.4065045686104, 10.4065045686104, 11.4065045686104, 14.4065045686104, 10.4065045686104, 16.4065045686104, 10.4065045686104, 7.40650456861036, 9.40650456861037, 7.40650456861036, 13.4065045686104, 17.4065045686104, 4.40650456861036, 10.4065045686104, 5.40650456861036, 6.40650456861036, 4.40650456861036, 5.40650456861036, 4.40650456861036, 4.40650456861036, 8.40650456861037, 9.40650456861037, 5.40650456861036, 9.40650456861037, 7.40650456861036, 7.40650456861036, 8.40650456861037), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42')));lgamma(argv[[1]]);");
+        assertEval("argv <- list(structure(c(11.4065045686104, 9.40650456861037, 8.40650456861037, 11.4065045686104, 9.40650456861037, 6.40650456861036, 15.4065045686104, 9.40650456861037, 9.40650456861037, 8.40650456861037, 6.40650456861036, 7.40650456861036, 8.40650456861037, 7.40650456861036, 9.40650456861037, 13.4065045686104, 10.4065045686104, 11.4065045686104, 14.4065045686104, 10.4065045686104, 16.4065045686104, 10.4065045686104, 7.40650456861036, 9.40650456861037, 7.40650456861036, 13.4065045686104, 17.4065045686104, 4.40650456861036, 10.4065045686104, 5.40650456861036, 6.40650456861036, 4.40650456861036, 5.40650456861036, 4.40650456861036, 4.40650456861036, 8.40650456861037, 9.40650456861037, 5.40650456861036, 9.40650456861037, 7.40650456861036, 7.40650456861036, 8.40650456861037), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42')));lgamma(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java
index 0c1ddfeaa18ab25a7733b507ada92817b964df3f..0200332fdae65cbe35d5e3895b1de648f36e03a6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_list.java
@@ -29,8 +29,7 @@ public class TestBuiltin_list extends TestBase {
 
     @Test
     public void testlist3() {
-        assertEval(Ignored.OutputFormatting,
-                        "argv <- list(x = c(9.5367431640625e-07, 1.9073486328125e-06, 3.814697265625e-06, 7.62939453125e-06, 1.52587890625e-05, 3.0517578125e-05, 6.103515625e-05, 0.0001220703125, 0.000244140625, 0.00048828125, 0.0009765625, 0.001953125, 0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024), y = c(3.69420518444359e+25, 2.30887824027777e+24, 1.44304890017492e+23, 9.01905562612606e+21, 5.63690976641081e+20, 35230686042118275072, 2201917878145066496, 137619867512235136, 8601241751556820, 537577617482832, 33598603095309.8, 2099913194115.17, 131244699796.888, 8202825028.58974, 512684387.219832, 32044730.0464007, 2003284.70114408, 125327.674230857, 7863.68742857025, 499.272560819512, 33.2784230289721, 2.7659432263306, 0.488936768533843, -0.282943224311172, 7.32218543045282e-05, -0.00636442868227041, -0.0483709204009262, -0.0704795507649514, 0.0349437746169591, -0.0264830837608839, 0.0200901469411759), xlab = NULL, ylab = NULL);list(argv[[1]],argv[[2]],argv[[3]],argv[[4]]);");
+        assertEval("argv <- list(x = c(9.5367431640625e-07, 1.9073486328125e-06, 3.814697265625e-06, 7.62939453125e-06, 1.52587890625e-05, 3.0517578125e-05, 6.103515625e-05, 0.0001220703125, 0.000244140625, 0.00048828125, 0.0009765625, 0.001953125, 0.00390625, 0.0078125, 0.015625, 0.03125, 0.0625, 0.125, 0.25, 0.5, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024), y = c(3.69420518444359e+25, 2.30887824027777e+24, 1.44304890017492e+23, 9.01905562612606e+21, 5.63690976641081e+20, 35230686042118275072, 2201917878145066496, 137619867512235136, 8601241751556820, 537577617482832, 33598603095309.8, 2099913194115.17, 131244699796.888, 8202825028.58974, 512684387.219832, 32044730.0464007, 2003284.70114408, 125327.674230857, 7863.68742857025, 499.272560819512, 33.2784230289721, 2.7659432263306, 0.488936768533843, -0.282943224311172, 7.32218543045282e-05, -0.00636442868227041, -0.0483709204009262, -0.0704795507649514, 0.0349437746169591, -0.0264830837608839, 0.0200901469411759), xlab = NULL, ylab = NULL);list(argv[[1]],argv[[2]],argv[[3]],argv[[4]]);");
     }
 
     @Test
@@ -342,7 +341,12 @@ public class TestBuiltin_list extends TestBase {
 
     @Test
     public void testlist65() {
-        assertEval(Ignored.Unknown,
+        // FIXME Besides whitespace diff in "function (x, y..." output there's
+        // at several places e.g. after '[1] "signature"' GnuR outputs
+        // attr(,"class")attr(,"package")
+        // while FastR outputs just
+        // attr(,"package")
+        assertEval(Output.IgnoreWhitespace, Ignored.OutputFormatting,
                         "argv <- list(ANY = structure(function (x, y = NULL) .Internal(crossprod(x, y)), target = structure('ANY', class = structure('signature', package = 'methods'), .Names = 'x', package = 'methods'), defined = structure('ANY', class = structure('signature', package = 'methods'), .Names = 'x', package = 'methods'), generic = structure('crossprod', package = 'base'), class = structure('derivedDefaultMethod', package = 'methods')));list(argv[[1]]);");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_listfiles.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_listfiles.java
index 6b11db7b2dfe50eb3a22d6501181fb51f19067d6..5b592db95893ad97bedf47e055cae81ab7c273bb 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_listfiles.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_listfiles.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -30,8 +30,8 @@ public class TestBuiltin_listfiles extends TestBase {
     @Test
     public void testlistfiles3() {
         // FastR bug; not recursing in to "."
-        assertEval(Ignored.Unknown,
-                        "argv <- list('.', '^CITATION.*', FALSE, FALSE, TRUE, FALSE, FALSE, FALSE); .Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]]))");
+        assertEval(Output.IgnoreWhitespace,
+                        "print('Work dir: ', getwd()); argv <- list('.', '^CITATION.*', FALSE, FALSE, TRUE, FALSE, FALSE, FALSE); sort(.Internal(list.files(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]], argv[[8]])))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_match.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_match.java
index 4891bd18f90c19fca9ab77f730ae1321bdb23d9b..2456353db223c3413bc7836457d469ccf8227992 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_match.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_match.java
@@ -124,7 +124,10 @@ public class TestBuiltin_match extends TestBase {
 
     @Test
     public void testmatch22() {
-        assertEval(Ignored.Unknown, "argv <- list(c(NA, NA, 3, 4, 5), c(NA, NA, 4, 5), 0L, NA); .Internal(match(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
+        // FIXME docs say "For all types, ‘NA’ matches ‘NA’ and no other value."
+        // Expected output: [1] 0 0 0 3 4
+        // FastR output: Error: usage of 'incomparables' in match not implemented
+        assertEval(Ignored.ImplementationError, "argv <- list(c(NA, NA, 3, 4, 5), c(NA, NA, 4, 5), 0L, NA); .Internal(match(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matchfun.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matchfun.java
index c18152dc1746c78ca4c85867e935afd87cd7a5da..fbf64da9f0b1f0216dd71ecff6cd0306d99f5ad6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matchfun.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matchfun.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -82,5 +82,8 @@ public class TestBuiltin_matchfun extends TestBase {
         assertEval("x <- min; f <- function(x) { min <- function(x) x; match.fun(x, descend=T)}; f(min)");
         assertEval("min <- function(x) x; f <- function(x) { match.fun(x, descend=T)}; f(min)");
         assertEval("f <- function(x) { match.fun(x, descend=T)}; f2 <- function() { min <- max; f(min) }; f2()");
+        assertEval("{ foo <- function() { myfunc <- function(x) 42; lapply(2, 'myfunc'); }; " +
+                        "boo <- function() { myfunc <- function(x) 42; lapply(2, 'myfunc'); }; " +
+                        "list(foo = foo(), boo = boo()); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matrix.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matrix.java
index 5881b9f0dd95043991b81132e365d08853df5f4f..52ea31129b649f991c2dd31cf622274b8466e206 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matrix.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_matrix.java
@@ -251,4 +251,9 @@ public class TestBuiltin_matrix extends TestBase {
     public void testmatrix44() {
         assertEval("argv <- list(structure(list(a1 = 1:3, a2 = 4:6, a3 = 3.14159265358979, a4 = c('a', 'b', 'c')), .Names = c('a1', 'a2', 'a3', 'a4')), 2, 2, FALSE, NULL, FALSE, FALSE); .Internal(matrix(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]], argv[[6]], argv[[7]]))");
     }
+
+    @Test
+    public void testMatrixFastPath() {
+        assertEval("matrix(1:9,,3)");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
index 9d88cf794bd26b6ff7cefb48deaa23a2c76a609e..7278f8e037b98f3343a94885fac33c2bd06da69e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_max.java
@@ -214,11 +214,13 @@ public class TestBuiltin_max extends TestBase {
 
         assertEval("max(v<-42)");
 
-        assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(integer(0)) }");
-        assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(integer()) }");
+        assertEval("{ max(integer(0)) }");
+        assertEval("{ max(integer()) }");
         assertEval("{ max(as.double(NA), na.rm=TRUE) }");
-        assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.integer(NA), na.rm=TRUE) }");
-        assertEval(Ignored.Unknown, Output.IgnoreWarningContext, "{ max(as.integer(NA), as.integer(NA), na.rm=TRUE) }");
+        assertEval("{ max(as.integer(NA), na.rm=TRUE) }");
+        assertEval("{ max(as.integer(NA), as.integer(NA), na.rm=TRUE) }");
+        assertEval("{ max(logical(0)) }");
+        assertEval("{ max(seq_len(0)) }");
 
         assertEval("max(c(1,NA,2), na.rm=NA)");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_maxcol.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_maxcol.java
index 3766d48f7f52dfee060f75f20b2bf6eb56074fdb..7d71d0e5079525e4910407b4f67537983f243267 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_maxcol.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_maxcol.java
@@ -19,18 +19,21 @@ public class TestBuiltin_maxcol extends TestBase {
 
     @Test
     public void testmaxcol1() {
-        assertEval(Ignored.Unknown,
+        // FIXME RInternalError: not implemented: .Internal max.col
+        assertEval(Ignored.Unimplemented,
                         "argv <- list(structure(c(80.2, 17, 15, 12, 9.96, 22.2, 83.1, 45.1, 6, 9, 84.84, 22.2, 92.5, 39.7, 5, 5, 93.4, 20.2, 85.8, 36.5, 12, 7, 33.77, 20.3, 76.9, 43.5, 17, 15, 5.16, 20.6, 76.1, 35.3, 9, 7, 90.57, 26.6, 83.8, 70.2, 16, 7, 92.85, 23.6, 92.4, 67.8, 14, 8, 97.16, 24.9, 82.4, 53.3, 12, 7, 97.67, 21, 82.9, 45.2, 16, 13, 91.38, 24.4, 87.1, 64.5, 14, 6, 98.61, 24.5, 64.1, 62, 21, 12, 8.52, 16.5, 66.9, 67.5, 14, 7, 2.27, 19.1, 68.9, 60.7, 19, 12, 4.43, 22.7, 61.7, 69.3, 22, 5, 2.82, 18.7, 68.3, 72.6, 18, 2, 24.2, 21.2, 71.7, 34, 17, 8, 3.3, 20, 55.7, 19.4, 26, 28, 12.11, 20.2, 54.3, 15.2, 31, 20, 2.15, 10.8, 65.1, 73, 19, 9, 2.84, 20, 65.5, 59.8, 22, 10, 5.23, 18, 65, 55.1, 14, 3, 4.52, 22.4, 56.6, 50.9, 22, 12, 15.14, 16.7, 57.4, 54.1, 20, 6, 4.2, 15.3, 72.5, 71.2, 12, 1, 2.4, 21, 74.2, 58.1, 14, 8, 5.23, 23.8, 72, 63.5, 6, 3, 2.56, 18, 60.5, 60.8, 16, 10, 7.72, 16.3, 58.3, 26.8, 25, 19, 18.46, 20.9, 65.4, 49.5, 15, 8, 6.1, 22.5, 75.5, 85.9, 3, 2, 99.71, 15.1, 69.3, 84.9, 7, 6, 99.68, 19.8, 77.3, 89.7, 5, 2, 100, 18.3, 70.5, 78.2, 12, 6, 98.96, 19.4, 79.4, 64.9, 7, 3, 98.22, 20.2, 65, 75.9, 9, 9, 99.06, 17.8, 92.2, 84.6, 3, 3, 99.46, 16.3, 79.3, 63.1, 13, 13, 96.83, 18.1, 70.4, 38.4, 26, 12, 5.62, 20.3, 65.7, 7.7, 29, 11, 13.79, 20.5, 72.7, 16.7, 22, 13, 11.22, 18.9, 64.4, 17.6, 35, 32, 16.92, 23, 77.6, 37.6, 15, 7, 4.97, 20, 67.6, 18.7, 25, 7, 8.65, 19.5, 35, 1.2, 37, 53, 42.34, 18, 44.7, 46.6, 16, 29, 50.43, 18.2, 42.8, 27.7, 22, 29, 58.33, 19.3), .Dim = c(6L, 47L), .Dimnames = list(c('Fertility', 'Agriculture', 'Examination', 'Education', 'Catholic', 'Infant.Mortality'), c('Courtelary', 'Delemont', 'Franches-Mnt', 'Moutier', 'Neuveville', 'Porrentruy', 'Broye', 'Glane', 'Gruyere', 'Sarine', 'Veveyse', 'Aigle', 'Aubonne', 'Avenches', 'Cossonay', 'Echallens', 'Grandson', 'Lausanne', 'La Vallee', 'Lavaux', 'Morges', 'Moudon', 'Nyone', 'Orbe', 'Oron', 'Payerne', 'Paysd\\'enhaut', 'Rolle', 'Vevey', 'Yverdon', 'Conthey', 'Entremont', 'Herens', 'Martigwy', 'Monthey', 'St Maurice', 'Sierre', 'Sion', 'Boudry', 'La Chauxdfnd', 'Le Locle', 'Neuchatel', 'Val de Ruz', 'ValdeTravers', 'V. De Geneve', 'Rive Droite', 'Rive Gauche'))), 1L); .Internal(max.col(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testmaxcol2() {
-        assertEval(Ignored.Unknown,
+        // FIXME RInternalError: not implemented: .Internal max.col
+        assertEval(Ignored.Unimplemented,
                         "argv <- list(structure(c(0.0140185568997224, 0.0152950000405453, 0.013933189413423, 0.0141545247888734, 0.0144656253644622, 0.0138841285101751, 0.014995293880605, 0.0135531935867069, 0.0136464824425927, 0.0139216121812551, 0.0150015663096977, 0.0141230892456885, 0.013614290948012, 0.0169498879707739, 0.0167919904349555, 0.0164281655519131, 0.0145450130659148, 0.0154935322596005, 0.0140566103751186, 0.0137862479562347, 0.0138916844301758, 0.0144143878263478, 0.0153699249520618, 0.0156955405518398, 0.0143684930741837, 0.991123944314599, 0.772371856665358, 0.998388573397845, 0.997744681008954, 0.935000528851613, 0.995759465226583, 0.998319991897437, 0.998446741491899, 0.997291233910865, 0.998453850443283, 0.449550979690061, 0.99765492178392, 0.0744670889060699, 0.997953251276348, 0.998367231220745, 0.998303801028119, 0.996490251221358, 0.987068752837462, 0.963362766144961, 0.997745619693091, 0.998180187351627, 0.995230116685749, 0.99834615324817, 0.998224606721368, 0.998138182928866, 0.000101796455995556, 0.0169548122668949, 0.00010041243364593, 0.994976075194857, 0.000116262428296307, 0.000266333816370553, 0.000213420942072358, 0.000150164062855871, 9.91852669694001e-05, 0.962237984681016, 0.000109709045973819, 0.363503438381572, 0.000165884012322677, 0.000404227768170316, 0.000101407372837694, 0.000138346452367636, 0.76867700377653, 0.000101067307394145, 0.000798310678132636, 0.439735407970107, 0.000105640126458538, 0.000103729730504055, 0.000157422658078269, 0.00062878104546921, 0.000140302481934868, 0.987636544924171, 0.986762198204236, 0.987695606647598, 0.987542563977846, 0.987328468487257, 0.987729584212166, 0.986966061808917, 0.987959390267427, 0.987894530108167, 0.987703622276188, 0.986961786481457, 0.987564327481863, 0.987916920251847, 0.98565103396999, 0.98575611086066, 0.985998830615913, 0.98727397408636, 0.986627618096195, 0.987610242071539, 0.987797448350422, 0.987724349638781, 0.987363673212559, 0.986711269247982, 0.986491053812255, 0.987395229430566, 0.0127450421932153, 0.00673790924500044, 0.0168765170487183, 0.015797380803532, 0.00875985277873091, 0.0142537568101031, 0.0172964637554702, 0.0177648866573519, 0.0158550778308362, 0.0172334564486378, 0.00522951225361075, 0.016267073149734, 0.00347221059583105, 0.0218803200901225, 0.0183403081414579, 0.0180163362514856, 0.0146261930363668, 0.0119682371438135, 0.00971509310832369, 0.0157071233034631, 0.017455515535567, 0.0139105878597395, 0.0174050248646065, 0.0173796025035352, 0.0168918350504782, 0.00106971573173608, 0.0026383344434856, 0.00106703814487522, 0.0135614845327103, 0.0010949673490627, 0.00126684800065677, 0.0012190851300456, 0.00114670950680761, 0.00106469628452917, 0.00946684926508704, 0.00108427378412549, 0.00489096395354091, 0.00116581741675497, 0.00136406369196257, 0.00106938597766297, 0.00112914854449728, 0.00664571845549644, 0.00106837166942789, 0.00153810249624049, 0.0051794966429432, 0.00107683746869901, 0.00107356047093305, 0.00115632815053843, 0.001475874716352, 0.00113310775095649, 0.000705529701133523, 0.000706190813132159, 0.000705483416292851, 0.000705607277564461, 0.000705767694047911, 0.000705456690994395, 0.000706040550884142, 0.000705277731844386, 0.000705325918720134, 0.00070547711802582, 0.000706043725519247, 0.000705586003991082, 0.000705308033747408, 0.000706976814055453, 0.000706900888924168, 0.000706734153004456, 0.000705809204506355, 0.000706288779684405, 0.000705550244606539, 0.000705403095546089, 0.000705460812978617, 0.000705740784771567, 0.000706233802920496, 0.000706387215078423, 0.000705716602186515, 0.00537527373619432, 0.193553056279976, 0.000869791621482113, 0.00126068143747944, 0.0477132994644455, 0.00247011263414166, 0.000876993026210466, 0.000793804652755058, 0.00147446124252569, 0.000818798505743392, 0.527720370257185, 0.0012613575859543, 0.931485133910046, 0.000794860447953985, 0.000799403966921179, 0.000843774285071599, 0.00203097055872496, 0.00804383321163345, 0.0255537088264535, 0.00126855734163029, 0.000930853589102135, 0.00281671019786704, 0.000858777960111907, 0.000915470358337216, 0.000986308498091386, 0.999944492377256, 0.98624753604171, 0.999945310582066, 0.00303527549384713, 0.999935958318038, 0.99984366374275, 0.999876760118408, 0.999915533835607, 0.999946031942947, 0.0270168111120999, 0.999939809617296, 0.622685795280626, 0.999906081646851, 0.999754847875723, 0.999944697838299, 0.999922757726417, 0.198924025871316, 0.99994491987507, 0.99948964681356, 0.539122196215121, 0.999942224996369, 0.999943338667082, 0.999911124821608, 0.999605022779117, 0.999921489451661), .Dim = c(75L, 3L), .Dimnames = list(    NULL, c('c', 's', 'v'))), 1L); .Internal(max.col(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testmaxcol3() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(list(), .Dim = 0:1), 1L); .Internal(max.col(argv[[1]], argv[[2]]))");
+        // FIXME RInternalError: not implemented: .Internal max.col
+        assertEval(Ignored.Unimplemented, "argv <- list(structure(list(), .Dim = 0:1), 1L); .Internal(max.col(argv[[1]], argv[[2]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
index fa3485703328d226c661561007ec7254f68f3503..e0eb250d0b058e83e9325a6a904ddeb3e76b8272 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_mean.java
@@ -24,7 +24,11 @@ public class TestBuiltin_mean extends TestBase {
 
     @Test
     public void testmean2() {
-        assertEval(Ignored.Unknown, "argv <- list(c(0.104166666666667, 0.285714285714286, 0.285714285714286, NA)); .Internal(mean(argv[[1]]))");
+        // FIXME NA is returned by GnuR for NA input
+        // Expected output: [1] NA
+        // FastR output: [1] NaN
+
+        assertEval(Ignored.ImplementationError, "argv <- list(c(0.104166666666667, 0.285714285714286, 0.285714285714286, NA)); .Internal(mean(argv[[1]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
index 442c0c3a6cba894475d95ca9f1dcf50a9103ba87..5db4be652de1e05b9613b03a459a430462d94960 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_min.java
@@ -173,17 +173,11 @@ public class TestBuiltin_min extends TestBase {
         assertEval("{ min(\"42\", as.character(NA), \"7\", na.rm=TRUE) }");
         assertEval("{ min(\"42\", as.character(NA), \"7\", na.rm=FALSE) }");
 
-        // FIXME
-        // Expected output: [1] Inf
-        // FastR output: [1] 2147483647
-        assertEval(Ignored.ImplementationError, Output.IgnoreWarningContext, "{ min(integer(0)) }");
-        assertEval(Ignored.ImplementationError, Output.IgnoreWarningContext, "{ min(integer()) }");
+        assertEval("{ min(integer(0)) }");
+        assertEval("{ min(integer()) }");
         assertEval("{ min(as.double(NA), na.rm=TRUE) }");
-        // FIXME
-        // Expected output: [1] Inf
-        // FastR output: [1] 2147483647
-        assertEval(Ignored.ImplementationError, Output.IgnoreWarningContext, "{ min(as.integer(NA), na.rm=TRUE) }");
-        assertEval(Ignored.ImplementationError, Output.IgnoreWarningContext, "{ min(as.integer(NA), as.integer(NA), na.rm=TRUE) }");
+        assertEval("{ min(as.integer(NA), na.rm=TRUE) }");
+        assertEval("{ min(as.integer(NA), as.integer(NA), na.rm=TRUE) }");
 
         assertEval("min(c(1,NA,2), na.rm=NA)");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_oldClassassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_oldClassassign.java
index a971a63a5d66142a2a4ade582716af32d1750dce..63f8e4dcd346094493532aa633d67b1e793b818c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_oldClassassign.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_oldClassassign.java
@@ -23,9 +23,7 @@ public class TestBuiltin_oldClassassign extends TestBase {
 
     @Test
     public void testoldClassassign2() {
-        // FIXME UnsupportedSpecializationException: Unexpected values provided for oldClass<-: [],
-        // []
-        assertEval(Ignored.ImplementationError, "argv <- list(NULL, NULL);`oldClass<-`(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(NULL, NULL);`oldClass<-`(argv[[1]],argv[[2]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
index 7765b87195d4c999bc99dd80a8f038163416a862..81dafef3a6aa80aa8da0ddbd86aaca31f810d4ee 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java
@@ -60,7 +60,13 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators9() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1:10, class = structure('NumericNotStructure', package = '.GlobalEnv')), 1);`+`(argv[[1]],argv[[2]]);");
+        // FIXME GnuR outputs extra 'attr(,"class")' for the following:
+        // [1] "NumericNotStructure"
+        // attr(,"class")attr(,"package")
+        // FastR outputs
+        // [1] "NumericNotStructure"
+        // attr(,"package")
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(1:10, class = structure('NumericNotStructure', package = '.GlobalEnv')), 1);`+`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -115,8 +121,7 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators20() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(978350400, class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), c(1605796.39468342, 2250605.34500331, 3464617.14155227, 5492840.71388841, 1219772.31891453, 5433460.81468463, 5713396.02452517, 3996505.04896045, 3804881.73750043, 373683.36378783, 1245734.22899097, 1067815.23929536, 4155114.17658627, 2323059.28775668, 4656000.90815127, 3010085.0161314, 4340156.73798323, 5999048.06153476, 2298452.76521891, 4701988.69854212, 5653097.23772854, 1283037.96871752, 3941322.93728739, 759357.220374048, 1616150.60446411, 2335218.03170443, 80984.7349449992, 2312682.3643595, 5259890.2349174, 2058430.73196709, 2915620.53836882, 3626174.11217093, 2984937.82503158, 1126244.053334, 5003953.83093506, 4042886.83258742, 4803562.677674, 652843.049369752, 4377003.8016513, 2487387.75048405, 4965083.1868127, 3913420.05222291, 4735177.34632641, 3344763.6128068, 3203744.02103573, 4774026.48925781, 141107.11171478, 2886287.43334115, 4429033.49147737, 4189640.45360684, 2888643.47467571, 5208594.91588175, 2649611.30449176, 1480533.93148631, 427466.877132654, 601571.336723864, 1912811.28504127, 3136700.02379268, 4003806.70217425, 2460508.97211581, 5521073.589921, 1775713.19845319, 2776429.51241881, 2010322.98948616, 3936464.58484232, 1560485.48977822, 2894241.66157097, 4634646.93606645, 509525.338098407, 5293943.40406358, 2050713.12808245, 5076935.23793668, 2096741.74243212, 2018670.78146338, 2880972.33020514, 5396015.5351907, 5227525.11837333, 2358656.75892681, 4701235.58655381, 5809817.647174, 2628820.56391239, 4309288.77686709, 2419165.9430936, 1967729.81455922, 4578863.07127029, 1225882.75911659, 4300861.15349829, 735992.738373578, 1484714.53242749, 866704.886756837, 1449278.70250493, 356435.113750398, 3884559.38760191, 5299676.19835585, 4710875.96918643, 4822123.77896905, 2753499.89549071, 2480188.52821738, 4904143.22827756, 3658636.53959334));`+`(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(structure(978350400, class = c('POSIXct', 'POSIXt'), tzone = 'GMT'), c(1605796.39468342, 2250605.34500331, 3464617.14155227, 5492840.71388841, 1219772.31891453, 5433460.81468463, 5713396.02452517, 3996505.04896045, 3804881.73750043, 373683.36378783, 1245734.22899097, 1067815.23929536, 4155114.17658627, 2323059.28775668, 4656000.90815127, 3010085.0161314, 4340156.73798323, 5999048.06153476, 2298452.76521891, 4701988.69854212, 5653097.23772854, 1283037.96871752, 3941322.93728739, 759357.220374048, 1616150.60446411, 2335218.03170443, 80984.7349449992, 2312682.3643595, 5259890.2349174, 2058430.73196709, 2915620.53836882, 3626174.11217093, 2984937.82503158, 1126244.053334, 5003953.83093506, 4042886.83258742, 4803562.677674, 652843.049369752, 4377003.8016513, 2487387.75048405, 4965083.1868127, 3913420.05222291, 4735177.34632641, 3344763.6128068, 3203744.02103573, 4774026.48925781, 141107.11171478, 2886287.43334115, 4429033.49147737, 4189640.45360684, 2888643.47467571, 5208594.91588175, 2649611.30449176, 1480533.93148631, 427466.877132654, 601571.336723864, 1912811.28504127, 3136700.02379268, 4003806.70217425, 2460508.97211581, 5521073.589921, 1775713.19845319, 2776429.51241881, 2010322.98948616, 3936464.58484232, 1560485.48977822, 2894241.66157097, 4634646.93606645, 509525.338098407, 5293943.40406358, 2050713.12808245, 5076935.23793668, 2096741.74243212, 2018670.78146338, 2880972.33020514, 5396015.5351907, 5227525.11837333, 2358656.75892681, 4701235.58655381, 5809817.647174, 2628820.56391239, 4309288.77686709, 2419165.9430936, 1967729.81455922, 4578863.07127029, 1225882.75911659, 4300861.15349829, 735992.738373578, 1484714.53242749, 866704.886756837, 1449278.70250493, 356435.113750398, 3884559.38760191, 5299676.19835585, 4710875.96918643, 4822123.77896905, 2753499.89549071, 2480188.52821738, 4904143.22827756, 3658636.53959334));`+`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -171,7 +176,13 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators31() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(FALSE, class = structure('foo', package = '.GlobalEnv')), NA);`+`(argv[[1]],argv[[2]]);");
+        // FIXME GnuR outputs extra 'attr(,"class")' for the following:
+        // [1] "foo"
+        // attr(,"class")attr(,"package")
+        // FastR outputs
+        // [1] "foo"
+        // attr(,"package")
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(FALSE, class = structure('foo', package = '.GlobalEnv')), NA);`+`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -212,7 +223,10 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators39() {
-        assertEval(Ignored.Unknown,
+        // FIXME number of digits in output:
+        // GnuR: 79.38889 98.88889 114.22222 123.38889
+        // FastR: 79.3889 98.8889 114.2222 123.3889
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(c(-24.5833333333333, -5.08333333333333, 10.25, 19.4166666666667), .Dim = 4L, .Dimnames = structure(list(N = c('0.0cwt', '0.2cwt', '0.4cwt', '0.6cwt')), .Names = 'N'), strata = structure('Within', .Names = 'N'), class = 'mtable'), structure(103.972222222222, class = 'mtable'));`+`(argv[[1]],argv[[2]]);");
     }
 
@@ -379,7 +393,16 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators72() {
-        assertEval(Ignored.Unknown,
+        // FIXME
+        // Expected output: [1] 1:1 1:1 1:2 2:2 2:3 2:3
+        // Levels: 1:1 1:2 1:3 2:1 2:2 2:3
+        // FastR output: [1] 1
+        // Warning messages:
+        // 1: In argv[[1]]:argv[[2]] :
+        // numerical expression has 6 elements: only the first used
+        // 2: In argv[[1]]:argv[[2]] :
+        // numerical expression has 6 elements: only the first used
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(c(1L, 1L, 1L, 2L, 2L, 2L), .Label = c('1', '2'), class = 'factor'), structure(c(1L, 1L, 2L, 2L, 3L, 3L), .Label = c('1', '2', '3'), class = 'factor'));`:`(argv[[1]],argv[[2]]);");
     }
 
@@ -470,9 +493,7 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators91() {
-        // GnuR outputs "TRUE" not "[1] TRUE"
-        assertEval(Ignored.OutputFormatting,
-                        "argv <- list(structure(list(c(3L, 0L, 1L)), class = c('R_system_version', 'package_version', 'numeric_version')), structure('3.1', .Names = 'gridSVG2'));`<`(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(structure(list(c(3L, 0L, 1L)), class = c('R_system_version', 'package_version', 'numeric_version')), structure('3.1', .Names = 'gridSVG2'));`<`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -552,18 +573,21 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators107() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(0:100, .Tsp = c(1, 101, 1), class = 'ts'), 0);`<=`(argv[[1]],argv[[2]]);");
+        // FIXME FastR output ignores .Tsp attribute of structure()
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(0:100, .Tsp = c(1, 101, 1), class = 'ts'), 0);`<=`(argv[[1]],argv[[2]]);");
     }
 
     @Test
     public void testoperators108() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR output ignores .Tsp attribute of structure()
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(c(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280, 290, 300, 310, 320, 330, 340, 350, 360, 370, 380, 390, 400, 410, 420, 430, 440, 450, 460, 470, 480, 490, 500, 510, 520, 530, 540, 550, 560, 570, 580, 590, 600, 610, 620, 630, 640, 650, 660, 670, 680, 690, 700, 710, 720, 730, 740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 890, 900, 910, 920, 930, 940, 950, 960, 970, 980, 990, 1000, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96), .Dim = c(101L, 3L), .Dimnames = list(NULL, c('t1', '10 * t1', 't1 - 4')), .Tsp = c(1, 101, 1), class = c('mts', 'ts', 'matrix')), 0);`<=`(argv[[1]],argv[[2]]);");
     }
 
     @Test
     public void testoperators109() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR output ignores .Tsp attribute of structure()
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, 104, 118, 115, 126, 141, 135, 125, 149, 170, 170, 158, 133, 114, 140, 145, 150, 178, 163, 172, 178, 199, 199, 184, 162, 146, 166, 171, 180, 193, 181, 183, 218, 230, 242, 209, 191, 172, 194, 196, 196, 236, 235, 229, 243, 264, 272, 237, 211, 180, 201, 204, 188, 235, 227, 234, 264, 302, 293, 259, 229, 203, 229, 242, 233, 267, 269, 270, 315, 364, 347, 312, 274, 237, 278, 284, 277, 317, 313, 318, 374, 413, 405, 355, 306, 271, 306, 315, 301, 356, 348, 355, 422, 465, 467, 404, 347, 305, 336, 340, 318, 362, 348, 363, 435, 491, 505, 404, 359, 310, 337, 360, 342, 406, 396, 420, 472, 548, 559, 463, 407, 362, 405, 417, 391, 419, 461, 472, 535, 622, 606, 508, 461, 390, 432, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 419.147602949539, 391.474665943444, 435.919286153217, 443.935203034261, 455.023399013445, 517.28707821144, 589.71337277669, 582.999919227301, 484.573388713116, 428.878182738437, 368.526582998452, 406.728709993152, 415.660571294428, 388.716535970235, 433.006017658935, 440.885684396326, 451.651900136866, 513.051252429496, 584.327164324967, 577.055407135124, 479.076505013118, 423.494870357491, 363.43932958967, 400.592058645117, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 484.030717075782, 462.954959541421, 526.353307750503, 546.165638262644, 569.502470928676, 657.838443307596, 761.241730163307, 763.280655335144, 642.989004951864, 576.423799567567, 501.429012064338, 559.981301364233, 591.700754553767, 565.210772316967, 642.377841008703, 666.682421047093, 695.547100430962, 804.065022775202, 931.340589597203, 934.837830059897, 788.422986194072, 707.666678543854, 616.37838266375, 689.250456425465), .Dim = c(168L, 3L), .Dimnames = list(NULL, c('structure(c(112, 118, 132, 129, 121, 135, 148, 148, 136, 119, ', 'structure(c(419.147602949539, 391.474665943444, 435.919286153217, ', 'structure(c(484.030717075782, 462.954959541421, 526.353307750503, ')), .Tsp = c(1949, 1962.91666666667, 12), class = c('mts', 'ts', 'matrix')), 0);`<=`(argv[[1]],argv[[2]]);");
     }
 
@@ -584,7 +608,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators113() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR output: Error in Ops.factor(c(2L, 2L, ...
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = c('fm2', 'original'), class = c('ordered', 'factor')), 'original');`!=`(argv[[1]],argv[[2]]);");
     }
 
@@ -620,7 +645,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators120() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR output ignores .Tsp attribute of structure()
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12), .Tsp = c(1959, 1997.91666666667, 12), class = 'ts'), 10L);`==`(argv[[1]],argv[[2]]);");
     }
 
@@ -669,7 +695,7 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators130() {
-        assertEval(Ignored.Unknown, "argv <- list(2, structure(list(2L), class = structure('L', package = '.GlobalEnv')));`==`(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(2, structure(list(2L), class = structure('L', package = '.GlobalEnv')));`==`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -704,7 +730,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators137() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(2, 1, 0, 1, 2), .Tsp = c(-1, 3, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);");
+        // FIXME FastR output ignores .Tsp attribute of structure()
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(c(2, 1, 0, 1, 2), .Tsp = c(-1, 3, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -729,9 +756,7 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators142() {
-        // GnuR outputs "TRUE" not "[1] TRUE"
-        assertEval(Ignored.OutputFormatting,
-                        "argv <- list(structure(list(c(3L, 0L, 1L)), class = c('R_system_version', 'package_version', 'numeric_version')), structure('2.13.2', .Names = 'SweaveListingUtils'));`>`(argv[[1]],argv[[2]]);");
+        assertEval("argv <- list(structure(list(c(3L, 0L, 1L)), class = c('R_system_version', 'package_version', 'numeric_version')), structure('2.13.2', .Names = 'SweaveListingUtils'));`>`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -756,7 +781,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators147() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(0, .Tsp = c(1, 1, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);");
+        // FIXME FastR output ignores .Tsp in structure()
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(0, .Tsp = c(1, 1, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -947,7 +973,9 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators185() {
-        assertEval(Ignored.Unknown,
+        // FIXME NullPointerException
+        // at com.oracle.truffle.r.nodes.builtin.base.MatMult.left0Dim(MatMult.java:118)
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(numeric(0), .Dim = c(10L, 0L), .Dimnames = list(c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10'), NULL)), structure(numeric(0), .Names = character(0)));`%*%`(argv[[1]],argv[[2]]);");
     }
 
@@ -1208,7 +1236,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators240() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(numeric(0), .Dim = c(0L, 4L)), structure(numeric(0), .Dim = c(0L, 4L)));`-`(argv[[1]],argv[[2]]);");
+        // FIXME FastR output ignores .Dim attribute of structure()
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(numeric(0), .Dim = c(0L, 4L)), structure(numeric(0), .Dim = c(0L, 4L)));`-`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -1283,7 +1312,13 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators257() {
-        assertEval(Ignored.Unknown,
+        // FIXME GnuR outputs extra 'attr(,"class")' for the following:
+        // [1] "withId"
+        // attr(,"class")attr(,"package")
+        // FastR outputs
+        // [1] "withId"
+        // attr(,"package")
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(c(1, 1.4142135623731, 1.73205080756888, 2, 2.23606797749979, 2.44948974278318, 2.64575131106459, 2.82842712474619, 3, 3.16227766016838), id = 'test 1', class = structure('withId', package = '.GlobalEnv')), 1);`%%`(argv[[1]],argv[[2]]);");
     }
 
@@ -1359,7 +1394,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators272() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(4, 3, 2, 1, 0), .Tsp = c(-1, 3, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);");
+        // FIXME FastR output ignores .Tsp attribute of structure()
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(c(4, 3, 2, 1, 0), .Tsp = c(-1, 3, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -1374,7 +1410,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators275() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(0, 1, 2, 3, 4, 5, 6, 7, 8), .Tsp = c(3, 11, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);");
+        // FIXME FastR output ignores .Tsp attribute of structure()
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(c(0, 1, 2, 3, 4, 5, 6, 7, 8), .Tsp = c(3, 11, 1), class = 'ts'), 1e-05);`>`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -1419,7 +1456,9 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators284() {
-        assertEval(Ignored.Unknown, "argv <- list(10, -324:-307);`^`(argv[[1]],argv[[2]]);");
+        // FIXME FastR only outputs 0e+00
+        // while GnuR sequence of 0.000000e+00 9.881313e-324 ... 1.000000e-307
+        assertEval(Ignored.ImplementationError, "argv <- list(10, -324:-307);`^`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -1444,7 +1483,10 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators289() {
-        assertEval(Ignored.Unknown, "argv <- list(0+0i, -3:3);`^`(argv[[1]],argv[[2]]);");
+        // FIXME
+        // Expected output: [1] Inf+0i Inf+0i Inf+0i 1+0i 0+0i 0+0i 0+0i
+        // FastR output: [1] Inf+NaNi Inf+NaNi Inf+NaNi 1+ 0i 0+ 0i 0+ 0i 0+ 0i
+        assertEval(Ignored.ImplementationError, "argv <- list(0+0i, -3:3);`^`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -1464,12 +1506,22 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators293() {
-        assertEval(Ignored.Unknown, "argv <- list(c(NA, -2L, -1L, 0L, 1L, 2L, NA, NA, NA), 0L);`^`(argv[[1]],argv[[2]]);");
+        // FIXME
+        // Expected output: [1] 1 1 1 1 1 1 1 1 1
+        // FastR output: [1] NA 1 1 1 1 1 NA NA NA
+        assertEval(Ignored.ImplementationError, "argv <- list(c(NA, -2L, -1L, 0L, 1L, 2L, NA, NA, NA), 0L);`^`(argv[[1]],argv[[2]]);");
     }
 
     @Test
     public void testoperators294() {
-        assertEval(Ignored.Unknown,
+        // FIXME 'NaN' instead of 'Inf' in output
+        // Expected output: [1] 0.0000000-0.5000000i 0.0000000-0.5773503i 0.0000000-0.7071068i
+        // [4] 0.0000000-1.0000000i Inf+0.0000000i 1.0000000+0.0000000i
+        // ...
+        // FastR output: [1] 0.0000000-0.5000000i 0.0000000-0.5773503i 0.0000000-0.7071068i
+        // [4] 0.0000000-1.0000000i NaN+ NaNi 1.0000000+0.0000000i
+        // ...
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(c(-4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i, -4+0i, -3+0i, -2+0i, -1+0i, 0+0i, 1+0i, 2+0i, 3+0i, 4+0i, 5+0i, 6+0i, 7+0i, 8+0i, 9+0i, 10+0i, 11+0i, 12+0i), c(-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 1.5, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2));`^`(argv[[1]],argv[[2]]);");
     }
 
@@ -1535,7 +1587,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators307() {
-        assertEval(Ignored.Unknown, "argv <- list(logical(0), structure(logical(0), .Dim = c(0L, 0L), .Dimnames = list(NULL, NULL)));`|`(argv[[1]],argv[[2]]);");
+        // FIXME FastR ignores .Dim attribute of the structure()
+        assertEval(Ignored.OutputFormatting, "argv <- list(logical(0), structure(logical(0), .Dim = c(0L, 0L), .Dimnames = list(NULL, NULL)));`|`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -1560,7 +1613,8 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators312() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR ignores .Dimnames attribute of the structure()
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(c(0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0), .Dim = c(6L, 3L), .Dimnames = structure(list(`  p L s` = c('. . .', '. | .', '. . |', '. | |', '. . ?', '. | ?'), c('perm', 'LDL', 'super')), .Names = c('  p L s', ''))), c(4, 2, 1));`%*%`(argv[[1]],argv[[2]]);");
     }
 
@@ -1596,7 +1650,9 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators319() {
-        assertEval(Ignored.Unknown, "argv <- list(numeric(0), structure(numeric(0), .Dim = c(1L, 0L)));`%*%`(argv[[1]],argv[[2]]);");
+        // FIXME NullPointerException
+        // at com.oracle.truffle.r.nodes.builtin.base.MatMult.right0Dim(MatMult.java:125)
+        assertEval(Ignored.ImplementationError, "argv <- list(numeric(0), structure(numeric(0), .Dim = c(1L, 0L)));`%*%`(argv[[1]],argv[[2]]);");
     }
 
     @Test
@@ -1703,13 +1759,15 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators340() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR ignores .Tsp attribute of the structure()
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(c(FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Tsp = c(1790, 1970, 0.1), class = 'ts'), c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE));`&`(argv[[1]],argv[[2]]);");
     }
 
     @Test
     public void testoperators341() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR ignores .Tsp attribute of the structure()
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE), .Dim = c(101L, 3L), .Dimnames = list(NULL, c('t1', '10 * t1', 't1 - 4')), .Tsp = c(1, 101, 1), class = c('mts', 'ts', 'matrix')), structure(c(TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE, TRUE), .Dim = c(101L, 3L), .Dimnames = list(NULL, c('t1', '10 * t1', 't1 - 4'))));`&`(argv[[1]],argv[[2]]);");
     }
 
@@ -1755,7 +1813,10 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators351() {
-        assertEval(Ignored.Unknown, "argv <- list(.Primitive('log'));`(`(argv[[1]]);");
+        // FIXME exp(1) expressed as number in FastR
+        // Expected output: function (x, base = exp(1)) .Primitive("log")
+        // FastR output: function (x, base = 2.718282) .Primitive("log")
+        assertEval(Ignored.OutputFormatting, "argv <- list(.Primitive('log'));`(`(argv[[1]]);");
     }
 
     @Test
@@ -1775,7 +1836,13 @@ public class TestBuiltin_operators extends TestBase {
 
     @Test
     public void testoperators355() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(NA, .Dim = c(1L, 1L), name = 'Sam', class = structure('Foo', package = '.GlobalEnv')));`(`(argv[[1]]);");
+        // FIXME GnuR outputs extra 'attr(,"class")' for the following:
+        // [1] "Foo"
+        // attr(,"class")attr(,"package")
+        // FastR outputs
+        // [1] "Foo"
+        // attr(,"package")
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(NA, .Dim = c(1L, 1L), name = 'Sam', class = structure('Foo', package = '.GlobalEnv')));`(`(argv[[1]]);");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_options.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_options.java
index 56452811e63d7ed88fd07b0df14c9ee90b3d83bb..97b6fd5ca14a135fd97d82c11f6cbb9879929d9e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_options.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_options.java
@@ -39,8 +39,7 @@ public class TestBuiltin_options extends TestBase {
 
     @Test
     public void testoptions5() {
-        // FIXME RInternalError: should not reach here
-        assertEval(Ignored.Unimplemented, "options(list(NULL));");
+        assertEval("options(list(NULL));");
         assertEval("options(NA);");
         // IMHO ReferenceError since NULL makes little sense as parameter value
         // here just like NA which outputs 'invalid argument' both in GnuR and FastR.
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_paste.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_paste.java
index 15183cd6f32c514481cd5d217b543b0ca0f95b49..d132fb4543837fdb1a9e3780fe62cf6172a86b2c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_paste.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_paste.java
@@ -80,6 +80,7 @@ public class TestBuiltin_paste extends TestBase {
         assertEval("{ paste(1:2, 1:3, FALSE, collapse=NULL) }");
         assertEval("{ paste(sep=\"\") }");
         assertEval("{ paste(1:2, 1:3, FALSE, collapse=\"-\", sep=\"+\") }");
+        assertEval("{ paste(NULL, list(), sep = \"=\") }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_paste0.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_paste0.java
index 85f5157879cc2ed0ae5d067ad6148f2a4c5157a3..eac30ba19df7bc8ae3bc39ccbc2bc94974a45a18 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_paste0.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_paste0.java
@@ -59,10 +59,7 @@ public class TestBuiltin_paste0 extends TestBase {
 
     @Test
     public void testpaste011() {
-        // FIXME:
-        // FastR output: '[1] ""'
-        // GnuR output: 'character(0)'
-        assertEval(Ignored.ImplementationError, "argv <- list(list(character(0), character(0), character(0)), NULL); .Internal(paste0(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(list(character(0), character(0), character(0)), NULL); .Internal(paste0(argv[[1]], argv[[2]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
index 0b873424d18b832deaa51e573156d5bd30148e69..13330f9079da2aabd25459dc2f52150348b75cec 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_pathexpand.java
@@ -37,6 +37,11 @@ public class TestBuiltin_pathexpand extends TestBase {
         assertEval("argv <- structure(list(path = '/tmp/RtmpagC9oa/Pkgs/exNSS4'),     .Names = 'path');do.call('path.expand', argv)");
     }
 
+    @Test
+    public void testpathexpand6() {
+        assertEval("path.expand('.'); wd <- getwd(); tryCatch({ setwd('/tmp'); path.expand('.') }, finally = { setwd(wd) })");
+    }
+
     @Test
     public void testArgsValidation() {
         assertEval("path.expand(NULL)");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_polyroot.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_polyroot.java
index 0ca6aa687d6bb273d00fd5cbe0dcc438078ce648..e4d3bf46418720fd8cf08e58e7e4f7e2ae060e74 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_polyroot.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_polyroot.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.
  */
@@ -19,31 +19,37 @@ public class TestBuiltin_polyroot extends TestBase {
 
     @Test
     public void testpolyroot1() {
-        assertEval(Ignored.Unknown, "argv <- list(1:2); .Internal(polyroot(argv[[1]]))");
+        // RInternalError: not implemented: .Internal polyroot
+        assertEval(Ignored.Unimplemented, "argv <- list(1:2); .Internal(polyroot(argv[[1]]))");
     }
 
     @Test
     public void testpolyroot2() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE); .Internal(polyroot(argv[[1]]))");
+        // RInternalError: not implemented: .Internal polyroot
+        assertEval(Ignored.Unimplemented, "argv <- list(FALSE); .Internal(polyroot(argv[[1]]))");
     }
 
     @Test
     public void testpolyroot3() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(1, 0.035205614861993, 0.237828814667385), .Names = c('', '', ''))); .Internal(polyroot(argv[[1]]))");
+        // RInternalError: not implemented: .Internal polyroot
+        assertEval(Ignored.Unimplemented, "argv <- list(structure(c(1, 0.035205614861993, 0.237828814667385), .Names = c('', '', ''))); .Internal(polyroot(argv[[1]]))");
     }
 
     @Test
     public void testpolyroot4() {
-        assertEval(Ignored.Unknown, "argv <- list(c(1, -1.16348488318732, 0.667550726251972, -0.342308178637008)); .Internal(polyroot(argv[[1]]))");
+        // RInternalError: not implemented: .Internal polyroot
+        assertEval(Ignored.Unimplemented, "argv <- list(c(1, -1.16348488318732, 0.667550726251972, -0.342308178637008)); .Internal(polyroot(argv[[1]]))");
     }
 
     @Test
     public void testpolyroot5() {
-        assertEval(Ignored.Unknown, "argv <- list(c(1, 0.0853462951557329, -0.433003162033324, 0.141816558560935, -0.268523717394886, -0.0970671649038473)); .Internal(polyroot(argv[[1]]))");
+        // RInternalError: not implemented: .Internal polyroot
+        assertEval(Ignored.Unimplemented, "argv <- list(c(1, 0.0853462951557329, -0.433003162033324, 0.141816558560935, -0.268523717394886, -0.0970671649038473)); .Internal(polyroot(argv[[1]]))");
     }
 
     @Test
     public void testpolyroot6() {
-        assertEval(Ignored.Unknown, "argv <- list(c(1, 8, 28, 56, 70, 56, 28, 8, 1)); .Internal(polyroot(argv[[1]]))");
+        // RInternalError: not implemented: .Internal polyroot
+        assertEval(Ignored.Unimplemented, "argv <- list(c(1, 8, 28, 56, 70, 56, 28, 8, 1)); .Internal(polyroot(argv[[1]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printfunction.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printfunction.java
index ff8128581d25abd8f18dff4d2500a9dda2bc4c9a..c28a39b059e0dcb80dc09338b583cde4cf0b7f52 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printfunction.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_printfunction.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.
  */
@@ -19,17 +19,25 @@ public class TestBuiltin_printfunction extends TestBase {
 
     @Test
     public void testprintfunction1() {
-        assertEval(Ignored.Unknown, "argv <- list(.Primitive('+'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))");
+        // FIXME maybe we could show arg names
+        // Expected output: function (e1, e2) .Primitive("+")
+        // FastR output: function (null, null) .Primitive("+")
+        assertEval(Ignored.OutputFormatting, "argv <- list(.Primitive('+'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testprintfunction2() {
-        assertEval(Ignored.Unknown, "argv <- list(.Primitive('if'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))");
+        // Expected output: .Primitive("if")
+        // FastR output: function(x).Primitive("if")
+        assertEval(Ignored.OutputFormatting, "argv <- list(.Primitive('if'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testprintfunction3() {
-        assertEval(Ignored.Unknown, "argv <- list(.Primitive('c'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))");
+        // ?c shows 'recursive' arg so marked as ReferenceError
+        // Expected output: function (...) .Primitive("c")
+        // FastR output: function (..., recursive) .Primitive("c")
+        assertEval(Ignored.ReferenceError, "argv <- list(.Primitive('c'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -39,6 +47,9 @@ public class TestBuiltin_printfunction extends TestBase {
 
     @Test
     public void testprintfunction5() {
-        assertEval(Ignored.Unknown, "argv <- list(.Primitive('log'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))");
+        // FIXME exp(1) sligthly better than 2.718282 but definitely a minor issue
+        // Expected output: function (x, base = exp(1)) .Primitive("log")
+        // FastR output: function (x, base = 2.718282) .Primitive("log")
+        assertEval(Ignored.OutputFormatting, "argv <- list(.Primitive('log'), TRUE); .Internal(print.function(argv[[1]], argv[[2]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java
index 7d0b9d0fddf7dfbc8d302c572ab70c8403083aa1..42a9f0ef49eb81f41d325bbc09fcefceac17ba45 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_prod.java
@@ -39,7 +39,7 @@ public class TestBuiltin_prod extends TestBase {
 
     @Test
     public void testprod5() {
-        assertEval(Ignored.Unknown, "argv <- list(integer(0));prod(argv[[1]]);");
+        assertEval("argv <- list(integer(0));prod(argv[[1]]);");
     }
 
     @Test
@@ -59,7 +59,7 @@ public class TestBuiltin_prod extends TestBase {
 
     @Test
     public void testprod9() {
-        assertEval(Ignored.Unknown, "argv <- list(NA_integer_);prod(argv[[1]]);");
+        assertEval("argv <- list(NA_integer_);prod(argv[[1]]);");
     }
 
     @Test
@@ -69,7 +69,7 @@ public class TestBuiltin_prod extends TestBase {
 
     @Test
     public void testprod11() {
-        assertEval(Ignored.Unknown, "argv <- list(numeric(0));prod(argv[[1]]);");
+        assertEval("argv <- list(numeric(0));prod(argv[[1]]);");
     }
 
     @Test
@@ -92,12 +92,16 @@ public class TestBuiltin_prod extends TestBase {
         assertEval("{prod(42,2+3i)}");
         assertEval("{prod('a')}");
         assertEval("{prod(list())}");
+        assertEval("prod()");
+        assertEval("prod(numeric())");
+        assertEval("prod(complex())");
+        assertEval("{ foo <- function(...) prod(...); foo(); }");
     }
 
     @Test
     public void testProdNa() {
-        assertEval(Ignored.Unknown, "{prod(c(2,4,NA))}");
-        assertEval(Ignored.Unknown, "{prod(c(2,4,3,NA),TRUE)}");
-        assertEval(Ignored.Unknown, "{prod(c(1,2,3,4,5,NA),FALSE)}");
+        assertEval("{prod(c(2,4,NA))}");
+        assertEval("{prod(c(2,4,3,NA),TRUE)}");
+        assertEval("{prod(c(1,2,3,4,5,NA),FALSE)}");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_putconst.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_putconst.java
index 374c703f37b0ea7c07adbc38a749eec4b9b0750c..c5167e42ce7b1a90ee62c8221a7d9eb1e8f8a028 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_putconst.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_putconst.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.
  */
@@ -19,11 +19,13 @@ public class TestBuiltin_putconst extends TestBase {
 
     @Test
     public void testputconst1() {
-        assertEval(Ignored.Unknown, "argv <- list(list(NULL), 0, NULL); .Internal(putconst(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal putconst
+        assertEval(Ignored.Unimplemented, "argv <- list(list(NULL), 0, NULL); .Internal(putconst(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testputconst2() {
-        assertEval(Ignored.Unknown, "argv <- list(list(list(), NULL), 1, list()); .Internal(putconst(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME RInternalError: not implemented: .Internal putconst
+        assertEval(Ignored.Unimplemented, "argv <- list(list(list(), NULL), 1, list()); .Internal(putconst(argv[[1]], argv[[2]], argv[[3]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_radixsort.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_radixsort.java
index d02f41837f0d43733119ecb75401d91cc5e1a84b..35ebee4cf0357714a979ccf8aaf0fdb51b0310a1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_radixsort.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_radixsort.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.
  */
@@ -19,28 +19,39 @@ public class TestBuiltin_radixsort extends TestBase {
 
     @Test
     public void testradixsort1() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1L, .Label = c('Ctl', 'Trt'), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME ArrayIndexOutOfBoundsException: 3
+        // at InternalNode$InternalCallWrapNode.prepareArgs(InternalNode.java:309)
+        assertEval(Ignored.ImplementationError, "argv <- list(structure(1L, .Label = c('Ctl', 'Trt'), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testradixsort2() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(2L, 1L, 3L), .Label = c('1', '2', NA), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME ArrayIndexOutOfBoundsException: 3
+        // at InternalNode$InternalCallWrapNode.prepareArgs(InternalNode.java:309)
+        assertEval(Ignored.ImplementationError,
+                        "argv <- list(structure(c(2L, 1L, 3L), .Label = c('1', '2', NA), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testradixsort3() {
-        assertEval(Ignored.Unknown,
+        // FIXME ArrayIndexOutOfBoundsException: 3
+        // at InternalNode$InternalCallWrapNode.prepareArgs(InternalNode.java:309)
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(c(3L, 7L, 1L, 5L, 10L, 8L, 2L, 6L, 4L, 9L), .Label = c('Svansota', 'No. 462', 'Manchuria', 'No. 475', 'Velvet', 'Peatland', 'Glabron', 'No. 457', 'Wisconsin No. 38', 'Trebi'), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testradixsort5() {
-        assertEval(Ignored.Unknown,
+        // FIXME ArrayIndexOutOfBoundsException: 3
+        // at InternalNode$InternalCallWrapNode.prepareArgs(InternalNode.java:309)
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(c(64L, 67L, 92L, 71L, 74L, 69L, 78L, 94L, 95L, 80L, 119L, 114L, 97L, 72L, 75L, 96L, 99L, 54L, 101L, 93L, 58L, 138L, NA, 139L, 126L, 84L, 79L, 62L, 52L, 68L, 81L, 87L, 109L, 35L, 51L, 61L, 59L, 131L, 137L, 73L, 77L, 70L, 90L, 107L, 29L, 89L, 57L, 66L, 76L, 37L, 155L, 16L, 102L, 56L, 123L, 36L, 60L, 40L, 43L, 85L, 65L, 11L, 47L, 103L, 86L, 13L, 63L, 132L, 91L, 98L, 105L, 134L, 14L, 124L, 117L, 55L, 41L, 24L, 50L, 110L, 129L, 88L, 141L, 145L, 133L, 25L, 46L, 120L, 83L, 121L, 104L, 53L, 44L, 113L, 100L, 19L, 108L, 31L, 82L, 127L, 111L, 116L, 38L, 150L, 48L, 22L, 112L, 140L, 27L, 149L, 115L, 130L, 8L, 28L, 106L, 23L, 125L, 33L, 39L, 32L, 15L, 49L, 144L, 7L, 17L, 122L, 118L, 5L, 128L, 12L, 45L, 21L, 42L, 147L, 26L, 1L, 4L, 153L, 151L, 3L, 136L), .Label = c('(360,365]', '(365,370]', '(370,375]', '(375,380]', '(380,385]', '(385,390]', '(390,395]', '(395,400]', '(400,405]', '(405,410]', '(410,415]', '(415,420]', '(420,425]', '(425,430]', '(430,435]', '(435,440]', '(440,445]', '(445,450]', '(450,455]', '(455,460]', '(460,465]', '(465,470]', '(470,475]', '(475,480]', '(480,485]', '(485,490]', '(490,495]', '(495,500]', '(500,505]', '(505,510]', '(510,515]', '(515,520]', '(520,525]', '(525,530]', '(530,535]', '(535,540]', '(540,545]', '(545,550]', '(550,555]', '(555,560]', '(560,565]', '(565,570]', '(570,575]', '(575,580]', '(580,585]', '(585,590]', '(590,595]', '(595,600]', '(600,605]', '(605,610]', '(610,615]', '(615,620]', '(620,625]', '(625,630]', '(630,635]', '(635,640]', '(640,645]', '(645,650]', '(650,655]', '(655,660]', '(660,665]', '(665,670]', '(670,675]', '(675,680]', '(680,685]', '(685,690]', '(690,695]', '(695,700]', '(700,705]', '(705,710]', '(710,715]', '(715,720]', '(720,725]', '(725,730]', '(730,735]', '(735,740]', '(740,745]', '(745,750]', '(750,755]', '(755,760]', '(760,765]', '(765,770]', '(770,775]', '(775,780]', '(780,785]', '(785,790]', '(790,795]', '(795,800]', '(800,805]', '(805,810]', '(810,815]', '(815,820]', '(820,825]', '(825,830]', '(830,835]', '(835,840]', '(840,845]', '(845,850]', '(850,855]', '(855,860]', '(860,865]', '(865,870]', '(870,875]', '(875,880]', '(880,885]', '(885,890]', '(890,895]', '(895,900]', '(900,905]', '(905,910]', '(910,915]', '(915,920]', '(920,925]', '(925,930]', '(930,935]', '(935,940]', '(940,945]', '(945,950]', '(950,955]', '(955,960]', '(960,965]', '(965,970]', '(970,975]', '(975,980]', '(980,985]', '(985,990]', '(990,995]', '(995,1000]', '(1000,1005]', '(1005,1010]', '(1010,1015]', '(1015,1020]', '(1020,1025]', '(1025,1030]', '(1030,1035]', '(1035,1040]', '(1040,1045]', '(1045,1050]', '(1050,1055]', '(1055,1060]', '(1060,1065]', '(1065,1070]', '(1070,1075]', '(1075,1080]', '(1080,1085]', '(1085,1090]', '(1090,1095]', '(1095,1100]', '(1100,1105]', '(1105,1110]', '(1110,1115]', '(1115,1120]', '(1120,1125]', '(1125,1130]', '(1130,1135]'), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testradixsort6() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(integer(0), .Label = character(0), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME ArrayIndexOutOfBoundsException: 3
+        // at InternalNode$InternalCallWrapNode.prepareArgs(InternalNode.java:309)
+        assertEval(Ignored.ImplementationError, "argv <- list(structure(integer(0), .Label = character(0), class = 'factor'), TRUE, FALSE); .Internal(radixsort(argv[[1]], argv[[2]], argv[[3]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_range.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_range.java
index 46cd9ba2ed297edc052f85606e5b4bc15a42af6c..a59ce3191e6d2f43d2de2af1a03be19b9cd09be0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_range.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_range.java
@@ -177,4 +177,10 @@ public class TestBuiltin_range extends TestBase {
     public void testNaRmAndFiniteWithLogical() {
         assertEval(template("range(c(T, F, NA, NA, T)%0)", OPTIONAL_ARGS));
     }
+
+    @Test
+    public void testRangeCharacter() {
+        assertEval(template("range(c('a', 'b', 'c')%0)", OPTIONAL_ARGS));
+        assertEval(template("range(c('1', '2', '3')%0)", OPTIONAL_ARGS));
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexec.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexec.java
index 9455b8270e8ba157fa8e0490096dfebae10c02cd..a65117eb42687fd2a04b1fe23f7aa9c2c2f0f5e5 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexec.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_regexec.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.
  */
@@ -19,7 +19,11 @@ public class TestBuiltin_regexec extends TestBase {
 
     @Test
     public void testregexec1() {
-        assertEval(Ignored.Unknown,
+        // FIXME Outputs match but in addition GnuR outputs:
+        // attr(,"useBytes")
+        // [1] TRUE
+        // docs do not mention that so ReferenceError for now.
+        assertEval(Ignored.ReferenceError,
                         "argv <- list('^(([^:]+)://)?([^:/]+)(:([0-9]+))?(/.*)', 'http://stat.umn.edu:80/xyz', FALSE, FALSE, FALSE); .Internal(regexec(argv[[1]], argv[[2]], argv[[3]], argv[[4]], argv[[5]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
index f40826faf1a65e0cb55d9de0457e58dbbfdcae4f..46cc3614b3d2077f752e153e3f6fb429fa4554d1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java
@@ -234,5 +234,7 @@ public class TestBuiltin_rep extends TestBase {
         assertEval("v <- 1; names(v) <- 'asdf'; rep(v, 2)");
         assertEval("v <- 1; class(v) <- 'asdf'; rep(v, 1)");
         assertEval("v <- 1; class(v) <- 'asdf'; rep(v, 2)");
+
+        assertEval("{ rep.cls <- function(x) 42; rep(structure(c(1,2), class='cls')); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java
index a2225e026a21cec3caf2e512d6d5be12bb0a1826..40ff969ca503f15168ab7c4249af8a2dcf3e4c33 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -55,5 +55,6 @@ public class TestBuiltin_rep_len extends TestBase {
         assertEval("{ rep_len(7, NULL) }");
         assertEval("{ rep_len(7, c(7, 42)) }");
 
+        assertEval("rep_len(1L, 4L)");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
index c6a77e41ad28e7ee7b8154f1a62639f6943249f0..8c1225f570ebcb0bdfb17198a546c1113bde92ff 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java
@@ -79,7 +79,9 @@ public class TestBuiltin_repint extends TestBase {
 
     @Test
     public void testrepint13() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1:4, .Label = c('A', 'B', 'C', 'D'), class = 'factor', .Names = c('a', 'b', 'c', 'd')), 2); .Internal(rep.int(argv[[1]], argv[[2]]))");
+        // FIXME FastR output does not honor .Label and .Names in structure()
+        assertEval(Ignored.OutputFormatting,
+                        "argv <- list(structure(1:4, .Label = c('A', 'B', 'C', 'D'), class = 'factor', .Names = c('a', 'b', 'c', 'd')), 2); .Internal(rep.int(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -186,5 +188,4 @@ public class TestBuiltin_repint extends TestBase {
         assertEval("{ rep.int(c(1+2i,100-400i,20+30i), c(3,7)) }");
         assertEval("{ rep.int(c(1+2i,100-400i,20+30i), c(3,-7)) }");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowMeans.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowMeans.java
index ef59e51b868a175f92ff83f63bfc27ca72be5d31..d5c271e0c13ed4803940b4b100f82be141e3a978 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowMeans.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowMeans.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -61,7 +61,9 @@ public class TestBuiltin_rowMeans extends TestBase {
 
         assertEval("{x<-matrix(c(\"1\",\"2\",\"3\",\"4\"),ncol=2);rowMeans(x)}");
         assertEval(ArithmeticWhiteList.WHITELIST, "{rowMeans(matrix(c(NaN,4+5i,2+0i,5+10i),nrow=2,ncol=2), na.rm = FALSE)}");
-        // Internal error in matrix(NA, NA, NA)
-        assertEval(Ignored.Unknown, "{rowMeans(matrix(NA,NA,NA),TRUE)}");
+        // FIXME GnuR error description slightly better for matrix()
+        // Expected output: Error in matrix(NA, NA, NA) : invalid 'nrow' value (too large or NA)
+        // FastR output: Error: the dims contain missing values
+        assertEval(Ignored.OutputFormatting, "{rowMeans(matrix(NA,NA,NA),TRUE)}");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java
index 7179dd4688cc195e3ef3a97b63466c68a27087ab..84081fcd460d218c37d1707820bfc5981a4a4f33 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rowsum.java
@@ -63,18 +63,17 @@ public class TestBuiltin_rowsum extends TestBase {
     public void testRowsumArgCoverage() {
         assertEval("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, ug, FALSE, as.character(ug)))");
         // 2nd parm function => GnuR Error: segfault
-        assertEvalFastR("{ x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug))); }",
-                        "cat(\"Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\\n invalid 'g' argument\"");
+        assertEvalFastR("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug)));",
+                        "cat(\"Error: invalid 'g' argument\\n\")");
         // 3rd parm is function => GnuR Error: "Error: unimplemented type 'closure' in
         // 'HashTableSetup'"
         assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, print, FALSE, as.character(ug)))");
         // 2nd parm NULL => GnuR Error: segfault\n" +
         assertEvalFastR("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, NULL, ug, FALSE,as.character(ug)))",
-                        "cat(\"Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\\n invalid 'g' argument\"");
+                        "cat(\"Error: invalid 'g' argument\\n\")");
         // 3rd parm NULL => GnuR Error: Error: unimplemented type 'NULL' in 'HashTableSetup'
         assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, NULL, FALSE,as.character(ug)))");
         assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, , ug, FALSE,as.character(ug)))");
         assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, , FALSE,as.character(ug)))");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
index e15202aaa8a4d4ea5fc6978def95d1a80d7f0f84..235ea98984f9bada9fa1ca2c48ce74212771462b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sample.java
@@ -64,14 +64,35 @@ public class TestBuiltin_sample extends TestBase {
 
         assertEval("{ set.seed(9567, \"Marsaglia-Multicarry\");x <- c(\"Heads\", \"Tails\") ; prob <- c(.3, .7) ; sample(x, 10, TRUE, prob) ; }");
 
-        assertEval(Ignored.Unknown, "{ set.seed(9567, \"Marsaglia-Multicarry\");x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, TRUE, prob) ; }");
-        assertEval(Ignored.Unknown, "{ set.seed(9567, \"Marsaglia-Multicarry\");x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, FALSE, prob) ; }");
-        assertEval(Ignored.Unknown, "{ set.seed(4357, \"default\"); x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, TRUE, prob) ; }");
-        assertEval(Ignored.Unknown, "{ set.seed(4357, \"default\"); x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, FALSE, prob) ; }");
-
-        // Fails because of error message mismatch.
-        assertEval(Ignored.Unknown, "{ set.seed(4357, \"default\"); x <- 5 ; sample(x, 6, FALSE, NULL) ;}");
-        assertEval(Ignored.Unknown, "{ set.seed(9567, \"Marsaglia-Multicarry\"); x <- 5 ; sample(x, 6, FALSE, NULL) ;}");
+        // FIXME algorithm difference?? ImplementationError for now
+        // Expected output: [1] 3 5 3 1 5
+        // FastR output: [1] 4 5 4 1 5
+        assertEval(Ignored.ImplementationError, "{ set.seed(9567, \"Marsaglia-Multicarry\");x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, TRUE, prob) ; }");
+        // FIXME algorithm difference?? ImplementationError for now
+        // Expected output: [1] 3 5 2 1 4
+        // FastR output: [1] 4 5 2 1 3
+        assertEval(Ignored.ImplementationError, "{ set.seed(9567, \"Marsaglia-Multicarry\");x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, FALSE, prob) ; }");
+        // FIXME algorithm difference?? ImplementationError for now
+        // Expected output: [1] 4 2 2 3 4
+        // FastR output: [1] 3 2 2 4 3
+        assertEval(Ignored.ImplementationError, "{ set.seed(4357, \"default\"); x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, TRUE, prob) ; }");
+        // FIXME algorithm difference?? ImplementationError for now
+        // Expected output: [1] 4 2 3 5 1
+        // FastR output: [1] 3 2 4 5 1
+        assertEval(Ignored.ImplementationError, "{ set.seed(4357, \"default\"); x <- c(5) ; prob <- c(1, 2, 3, 4, 5) ; sample(x, 5, FALSE, prob) ; }");
+
+        // FIXME GnuR's error message maybe more descriptive
+        // Expected output: Error in sample.int(x, size, replace, prob) :
+        // cannot take a sample larger than the population when 'replace = FALSE'
+        // FastR output: Error in sample.int(x, size, replace, prob) :
+        // incorrect number of probabilities
+        assertEval(Ignored.ImplementationError, "{ set.seed(4357, \"default\"); x <- 5 ; sample(x, 6, FALSE, NULL) ;}");
+        // FIXME GnuR's error message maybe more descriptive
+        // Expected output: Error in sample.int(x, size, replace, prob) :
+        // cannot take a sample larger than the population when 'replace = FALSE'
+        // FastR output: Error in sample.int(x, size, replace, prob) :
+        // incorrect number of probabilities
+        assertEval(Ignored.ImplementationError, "{ set.seed(9567, \"Marsaglia-Multicarry\"); x <- 5 ; sample(x, 6, FALSE, NULL) ;}");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java
index 493b12767940d7ac502e55ecca14c56fb533b2e9..1475666adc8634ce6761f211714152f68ac78f23 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java
@@ -144,6 +144,13 @@ public class TestBuiltin_seq extends TestBase {
         assertEval(Output.MayIgnoreErrorContext, template("%0(1, 20, 3, length.out=10)", SEQFUNS));
     }
 
+    // argument matching corner-case appearing in seq (because it has a fast-path and varargs)
+    // taken and adapted from the scales package
+    @Test
+    public void testSeqArgMatching() {
+        assertEval("{ foo <- function(beg, end, by, len) seq(beg, end, by, length.out = len); foo(beg=1, by=1, len=10) }");
+    }
+
     // Old tests, undoubtedly partially overlapping
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seqint.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seqint.java
index 51307af886e6deb8f6f6eaf1686ed54474c84d01..145ce17527e1f5c79a23ec0ecd0529379498488d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seqint.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seqint.java
@@ -156,4 +156,9 @@ public class TestBuiltin_seqint extends TestBase {
     public void testseqint29() {
         assertEval(Output.IgnoreErrorContext, "argv <- list(NaN);do.call('seq.int', argv)");
     }
+
+    @Test
+    public void testseqintGenericDispatch() {
+        assertEval("{ seq.int.cls <- function(x) 42; seq.int(structure(c(1,2), class='cls')); }");
+    }
 }
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 018b22c6522e7f87fd641f22e554eb5fe53ca58d..e0ef86b8142d201c59940a44be130243039b8688 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
@@ -115,5 +115,6 @@ public class TestBuiltin_serialize extends TestBase {
     @Test
     public void testSerializeWithPromises() {
         assertEval("{ f <- function(...) serialize(mget('...'),NULL); length(unserialize(f(a=3,b=2,c=1))[[1]]); }");
+        assertEval("{ f <- function(...) serialize(environment()[['...']],NULL); x <- unserialize(f(a=3,b=2,c=1)); typeof(x) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java
index e74b1ef0db9e5f3f9a6397ba1b65f688b50b7004..05d9ab1503af4b5050944b0b305e6c6516595cd7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setS4Object.java
@@ -25,19 +25,21 @@ public class TestBuiltin_setS4Object extends TestBase {
 
     @Test
     public void testsetS4Object2() {
-        assertEval(Ignored.Unknown,
+        // Quotes (GnuR) vs. Apostrophes (FastR) used to quote standardGeneric('toeplitz')
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(function (x, ...) standardGeneric('toeplitz'), generic = character(0), package = character(0), group = list(), valueClass = character(0), signature = character(0), default = quote(`\\001NULL\\001`), skeleton = quote(`<undef>`()), class = structure('standardGeneric', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testsetS4Object3() {
-        assertEval(Ignored.Unknown,
+        assertEval(Output.IgnoreWhitespace,
                         "argv <- list(structure(character(0), package = character(0), class = structure('ObjectsWithPackage', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testsetS4Object4() {
-        assertEval(Ignored.Unknown,
+        // Quotes (GnuR) vs. Apostrophes (FastR) used to quote standardGeneric('qr.Q')
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(function (qr, complete = FALSE, Dvec) standardGeneric('qr.Q'), generic = character(0), package = character(0), group = list(), valueClass = character(0), signature = character(0), default = quote(`\\001NULL\\001`), skeleton = quote(`<undef>`()), class = structure('standardGeneric', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
@@ -48,19 +50,28 @@ public class TestBuiltin_setS4Object extends TestBase {
 
     @Test
     public void testsetS4Object6() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR outputs error
+        // Error in dimnames(mm) <- list(sigSlots, names(allSlots[[1L]])) :
+        // length of 'dimnames' [1] not equal to array extent
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(function (x) .Internal(drop(x)), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testsetS4Object7() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR outputs error
+        // Error in dimnames(mm) <- list(sigSlots, names(allSlots[[1L]])) :
+        // length of 'dimnames' [1] not equal to array extent
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(function (x, y = NULL) .Internal(crossprod(x, y)), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testsetS4Object8() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR outputs error
+        // Error in dimnames(mm) <- list(sigSlots, names(allSlots[[1L]])) :
+        // length of 'dimnames' [1] not equal to array extent
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(function (x, i, j, ...) x@aa[[i]], target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('MethodDefinition', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
@@ -71,31 +82,44 @@ public class TestBuiltin_setS4Object extends TestBase {
 
     @Test
     public void testsetS4Object10() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR outputs the following error as part of output:
+        // Error in dimnames(mm) <- list(sigSlots, names(allSlots[[1L]])) :
+        // length of 'dimnames' [1] not equal to array extent
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(function (object) cat('I am a \\\'foo\\\'\\n'), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('MethodDefinition', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testsetS4Object11() {
-        assertEval(Ignored.Unknown,
+        // Besides whitespace differences there's just apostrophe vs. quote
+        // difference in standardGeneric('diag')
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(function (x = 1, nrow, ncol) standardGeneric('diag'), generic = character(0), package = character(0), group = list(), valueClass = character(0), signature = character(0), default = quote(`\\001NULL\\001`), skeleton = quote(`<undef>`()), class = structure('standardGeneric', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testsetS4Object12() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR outputs the following error as part of output:
+        // Error in dimnames(mm) <- list(sigSlots, names(allSlots[[1L]])) :
+        // length of 'dimnames' [1] not equal to array extent
+
+        // FastR uses apostrophes to quote string: function (object) cat('I am a \'foo\'\n')
+        // GnuR outputs several attr(,"class")attr(,"package") while GnuR just attr(,"package")
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(list(`NA` = structure(function (object) cat('I am a \\\'foo\\\'\\n'), target = structure('foo', .Names = 'object', package = 'myTst', class = structure('signature', package = 'methods')), defined = structure('foo', .Names = 'object', package = 'myTst', class = structure('signature', package = 'methods')), generic = structure('show', package = 'methods'), class = structure('MethodDefinition', package = 'methods'))), .Names = NA_character_, arguments = structure('object', simpleOnly = TRUE), signatures = list(), generic = structure(function (object) standardGeneric('show'), generic = structure('show', package = 'methods'), package = 'methods', group = list(), valueClass = character(0), signature = structure('object', simpleOnly = TRUE), default = structure(function (object) showDefault(object, FALSE), target = structure('ANY', class = structure('signature', package = 'methods'), .Names = 'object', package = 'methods'), defined = structure('ANY', class = structure('signature', package = 'methods'), .Names = 'object', package = 'methods'), generic = structure('show', package = 'methods'), class = structure('derivedDefaultMethod', package = 'methods')), skeleton = quote((function (object) showDefault(object, FALSE))(object)), class = structure('standardGeneric', package = 'methods')), class = structure('listOfMethods', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testsetS4Object13() {
-        assertEval(Ignored.Unknown,
+        // Quotes (GnuR) vs. Apostrophes (FastR) used to quote string.
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(function (x, type = c('O', 'I', 'F', 'M', '2')) {    if (identical('2', type)) {        svd(x, nu = 0L, nv = 0L)$d[1L]    } else .Internal(La_dlange(x, type))}, target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
     public void testsetS4Object14() {
-        assertEval(Ignored.Unknown,
+        // Quotes (GnuR) vs. Apostrophes (FastR) used to quote UseMethod('plot')
+        assertEval(Ignored.OutputFormatting,
                         "argv <- list(structure(function (x, y, ...) UseMethod('plot'), target = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), defined = structure(character(0), .Names = character(0), package = character(0), class = structure('signature', package = 'methods')), generic = character(0), class = structure('derivedDefaultMethod', package = 'methods')), TRUE, 0L); .Internal(setS4Object(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setSessionTimeLimit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setSessionTimeLimit.java
index d35bcaea7879a45ff2b13f7653b78238580e8c67..65e70cabddcf084e49942bf4553109c305382037 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setSessionTimeLimit.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setSessionTimeLimit.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.
  */
@@ -19,11 +19,13 @@ public class TestBuiltin_setSessionTimeLimit extends TestBase {
 
     @Test
     public void testsetSessionTimeLimit1() {
-        assertEval(Ignored.Unknown, "argv <- list(NULL, NULL); .Internal(setSessionTimeLimit(argv[[1]], argv[[2]]))");
+        // FIXME RInternalError: not implemented: .Internal setSessionTimeLimit
+        assertEval(Ignored.Unimplemented, "argv <- list(NULL, NULL); .Internal(setSessionTimeLimit(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testsetSessionTimeLimit2() {
-        assertEval(Ignored.Unknown, "argv <- list(FALSE, Inf); .Internal(setSessionTimeLimit(argv[[1]], argv[[2]]))");
+        // FIXME RInternalError: not implemented: .Internal setSessionTimeLimit
+        assertEval(Ignored.Unimplemented, "argv <- list(FALSE, Inf); .Internal(setSessionTimeLimit(argv[[1]], argv[[2]]))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_signif.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_signif.java
index 11edd702bd10b3e34f218a74782a8db040499ed2..69ae9275e75aff15c5422f9aab77dc8bd2f15432 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_signif.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_signif.java
@@ -20,11 +20,14 @@ public class TestBuiltin_signif extends TestBase {
 
     @Test
     public void testsignif1() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(c(0, NaN, 0, 4.94065645841247e-324), class = 'integer64'));do.call('signif', argv)");
+        // FIXME RInternalError: java.lang.NumberFormatException: Infinite or NaN
+        assertEval(Ignored.ImplementationError, "argv <- list(structure(c(0, NaN, 0, 4.94065645841247e-324), class = 'integer64'));do.call('signif', argv)");
     }
 
     @Test
     public void testSignif() {
+        assertEval("{ signif(8.175, 3) }");
+        assertEval("{ signif(8.125, 3) }");
         assertEval("{ signif(0.555, 2) }");
         assertEval("{ signif(0.5549, 2) }");
         assertEval("{ signif(0.5551, 2) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sinpi.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sinpi.java
index 151dd8d4927dadb1b7999af3412548dc1b587a6a..25ac0d6955ee7c8d008f30eb2367fe61759b926d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sinpi.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sinpi.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
@@ -56,13 +56,15 @@ public class TestBuiltin_sinpi extends TestBase {
 
     @Test
     public void testsin6() {
-        assertEval(Ignored.Unimplemented,
-                        "argv <- list(c(-0.560475646552213-0.710406563699301i, -0.23017748948328+0.25688370915653i, 1.55870831414912-0.24669187846237i, 0.070508391424576-0.347542599397733i, 0.129287735160946-0.951618567265016i, 1.71506498688328-0.04502772480892i, 0.460916205989202-0.784904469457076i, -1.26506123460653-1.66794193658814i, -0.686852851893526-0.380226520287762i, -0.445661970099958+0.918996609060766i, 1.22408179743946-0.57534696260839i, 0.359813827057364+0.607964322225033i, 0.40077145059405-1.61788270828916i, 0.11068271594512-0.055561965524539i, -0.555841134754075+0.519407203943462i, 1.78691313680308+0.30115336216671i, 0.497850478229239+0.105676194148943i, -1.96661715662964-0.64070600830538i, 0.701355901563686-0.849704346033582i, -0.47279140772793-1.02412879060491i, -1.06782370598685+0.11764659710013i, -0.217974914658295-0.947474614184802i, -1.02600444830724-0.49055744370067i, -0.72889122929114-0.256092192198247i, -0.62503926784926+1.84386200523221i, -1.68669331074241-0.65194990169546i, 0.837787044494525+0.235386572284857i, 0.153373117836515+0.077960849563711i, -1.13813693701195-0.96185663413013i, 1.25381492106993-0.0713080861236i, 0.42646422147681+1.44455085842335i, -0.295071482992271+0.451504053079215i, 0.895125661045022+0.04123292199294i, 0.878133487533042-0.422496832339625i, 0.82158108163749-2.05324722154052i, 0.68864025410009+1.13133721341418i, 0.55391765353759-1.46064007092482i, -0.061911710576722+0.739947510877334i, -0.30596266373992+1.90910356921748i, -0.38047100101238-1.4438931609718i, -0.694706978920513+0.701784335374711i, -0.207917278019599-0.262197489402468i, -1.26539635156826-1.57214415914549i, 2.16895596533851-1.51466765378175i, 1.20796199830499-1.60153617357459i, -1.12310858320335-0.5309065221703i, -0.40288483529908-1.4617555849959i, -0.466655353623219+0.687916772975828i, 0.77996511833632+2.10010894052567i, -0.08336906647183-1.28703047603518i, 0.253318513994755+0.787738847475178i, -0.028546755348703+0.76904224100091i, -0.042870457291316+0.332202578950118i, 1.36860228401446-1.00837660827701i, -0.225770985659268-0.119452606630659i, 1.51647060442954-0.28039533517025i, -1.54875280423022+0.56298953322048i, 0.584613749636069-0.372438756103829i, 0.123854243844614+0.976973386685621i, 0.215941568743973-0.374580857767014i, 0.37963948275988+1.05271146557933i, -0.5023234531093-1.04917700666607i, -0.33320738366942-1.26015524475811i, -1.01857538310709+3.2410399349424i, -1.07179122647558-0.41685758816043i, 0.303528641404258+0.298227591540715i, 0.448209778629426+0.636569674033849i, 0.053004226730504-0.483780625708744i, 0.922267467879738+0.516862044313609i, 2.05008468562714+0.36896452738509i, -0.491031166056535-0.215380507641693i, -2.30916887564081+0.06529303352532i, 1.00573852446226-0.03406725373846i, -0.70920076258239+2.12845189901618i, -0.688008616467358-0.741336096272828i, 1.0255713696967-1.09599626707466i, -0.284773007051009+0.037788399171079i, -1.22071771225454+0.31048074944314i, 0.18130347974915+0.436523478910183i, -0.138891362439045-0.458365332711106i, 0.00576418589989-1.06332613397119i, 0.38528040112633+1.26318517608949i, -0.370660031792409-0.349650387953555i, 0.644376548518833-0.865512862653374i, -0.220486561818751-0.236279568941097i, 0.331781963915697-0.197175894348552i, 1.09683901314935+1.10992028971364i, 0.435181490833803+0.084737292197196i, -0.325931585531227+0.754053785184521i, 1.14880761845109-0.49929201717226i, 0.993503855962119+0.214445309581601i, 0.54839695950807-0.324685911490835i, 0.238731735111441+0.094583528173571i, -0.627906076039371-0.895363357977542i, 1.36065244853001-1.31080153332797i, -0.60025958714713+1.99721338474797i, 2.18733299301658+0.60070882367242i, 1.53261062618519-1.25127136162494i, -0.235700359100477-0.611165916680421i, -1.02642090030678-1.18548008459731i));sinpi(argv[[1]]);");
+        assertEval("argv <- list(c(-0.560475646552213-0.710406563699301i, -0.23017748948328+0.25688370915653i, 1.55870831414912-0.24669187846237i, 0.070508391424576-0.347542599397733i, 0.129287735160946-0.951618567265016i, 1.71506498688328-0.04502772480892i, 0.460916205989202-0.784904469457076i, -1.26506123460653-1.66794193658814i, -0.686852851893526-0.380226520287762i, -0.445661970099958+0.918996609060766i, 1.22408179743946-0.57534696260839i, 0.359813827057364+0.607964322225033i, 0.40077145059405-1.61788270828916i, 0.11068271594512-0.055561965524539i, -0.555841134754075+0.519407203943462i, 1.78691313680308+0.30115336216671i, 0.497850478229239+0.105676194148943i, -1.96661715662964-0.64070600830538i, 0.701355901563686-0.849704346033582i, -0.47279140772793-1.02412879060491i, -1.06782370598685+0.11764659710013i, -0.217974914658295-0.947474614184802i, -1.02600444830724-0.49055744370067i, -0.72889122929114-0.256092192198247i, -0.62503926784926+1.84386200523221i, -1.68669331074241-0.65194990169546i, 0.837787044494525+0.235386572284857i, 0.153373117836515+0.077960849563711i, -1.13813693701195-0.96185663413013i, 1.25381492106993-0.0713080861236i, 0.42646422147681+1.44455085842335i, -0.295071482992271+0.451504053079215i, 0.895125661045022+0.04123292199294i, 0.878133487533042-0.422496832339625i, 0.82158108163749-2.05324722154052i, 0.68864025410009+1.13133721341418i, 0.55391765353759-1.46064007092482i, -0.061911710576722+0.739947510877334i, -0.30596266373992+1.90910356921748i, -0.38047100101238-1.4438931609718i, -0.694706978920513+0.701784335374711i, -0.207917278019599-0.262197489402468i, -1.26539635156826-1.57214415914549i, 2.16895596533851-1.51466765378175i, 1.20796199830499-1.60153617357459i, -1.12310858320335-0.5309065221703i, -0.40288483529908-1.4617555849959i, -0.466655353623219+0.687916772975828i, 0.77996511833632+2.10010894052567i, -0.08336906647183-1.28703047603518i, 0.253318513994755+0.787738847475178i, -0.028546755348703+0.76904224100091i, -0.042870457291316+0.332202578950118i, 1.36860228401446-1.00837660827701i, -0.225770985659268-0.119452606630659i, 1.51647060442954-0.28039533517025i, -1.54875280423022+0.56298953322048i, 0.584613749636069-0.372438756103829i, 0.123854243844614+0.976973386685621i, 0.215941568743973-0.374580857767014i, 0.37963948275988+1.05271146557933i, -0.5023234531093-1.04917700666607i, -0.33320738366942-1.26015524475811i, -1.01857538310709+3.2410399349424i, -1.07179122647558-0.41685758816043i, 0.303528641404258+0.298227591540715i, 0.448209778629426+0.636569674033849i, 0.053004226730504-0.483780625708744i, 0.922267467879738+0.516862044313609i, 2.05008468562714+0.36896452738509i, -0.491031166056535-0.215380507641693i, -2.30916887564081+0.06529303352532i, 1.00573852446226-0.03406725373846i, -0.70920076258239+2.12845189901618i, -0.688008616467358-0.741336096272828i, 1.0255713696967-1.09599626707466i, -0.284773007051009+0.037788399171079i, -1.22071771225454+0.31048074944314i, 0.18130347974915+0.436523478910183i, -0.138891362439045-0.458365332711106i, 0.00576418589989-1.06332613397119i, 0.38528040112633+1.26318517608949i, -0.370660031792409-0.349650387953555i, 0.644376548518833-0.865512862653374i, -0.220486561818751-0.236279568941097i, 0.331781963915697-0.197175894348552i, 1.09683901314935+1.10992028971364i, 0.435181490833803+0.084737292197196i, -0.325931585531227+0.754053785184521i, 1.14880761845109-0.49929201717226i, 0.993503855962119+0.214445309581601i, 0.54839695950807-0.324685911490835i, 0.238731735111441+0.094583528173571i, -0.627906076039371-0.895363357977542i, 1.36065244853001-1.31080153332797i, -0.60025958714713+1.99721338474797i, 2.18733299301658+0.60070882367242i, 1.53261062618519-1.25127136162494i, -0.235700359100477-0.611165916680421i, -1.02642090030678-1.18548008459731i));sinpi(argv[[1]]);");
     }
 
     @Test
     public void testsin7() {
-        assertEval(Ignored.Unknown, "argv <- list(Inf);sinpi(argv[[1]]);");
+        // FIXME Missing warning
+        // Warning message:
+        // In sinpi(argv[[1]]) : NaNs produced
+        assertEval(Output.MissingWarning, "argv <- list(Inf);sinpi(argv[[1]]);");
     }
 
     @Test
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 75d197910998b927b624bb978c5964475a5ab71a..57f77f394a6a1379bfe851d67699523664e0350c 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
@@ -24,14 +24,14 @@ public class TestBuiltin_split extends TestBase {
 
     @Test
     public void testsplit2() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(-1.13864415195445, 0.574433648632919, 0.61125743366192, 0.291104607198021, 1.44367450704693, 0.408616385050392, -0.252815027721455, 0.73544465026571, -0.711029326417947, -0.611820918993561, -0.963259276248408, -0.28935033673839, -0.482346616963731, 0.575284398820533, 0.0664802498883062, 0.0889008730409177, -0.527009741835806, -0.572160487726669, 0.458433701366337, 0.0259549922279207, 0.79246010222197, 0.200856719794408, 0.681708382019133, 1.24959713166139, 2.28504683598586, 0.885201117877485, 0.275047494865858, 0.0611635446204713, -0.226340664609402, -0.701634984067551, -1.36331112409512, -0.470720710127998, 0.0116712292760789, 0.680960771805182, 1.25010637890252, -0.168484448953506, -0.703880448859559, -0.342493773069341, -0.359950801091045, 0.187018301421814, 0.332611568778467, 0.418088885897922, 1.52526747601546, 1.23881025318897, 1.97893910443604, 1.67980257496383, -0.0423836378777035, -0.085940264442189, 0.0751591419566941, 1.33615888669544, 1.29143414265875, 0.211686019646981, 0.107754613497605, -0.842122877395922, -0.363550334633855, -1.04260396788242, -1.00216202750311, -0.725219786582336, -0.702075395338802, -0.0588517433215815, 0.676181221812652, 0.606054389584641, -0.0722001122493283, -0.565579974058951, -1.50420998542363, -1.38835023347894, -1.6387526999868, -1.22317617387598, -2.6439685322602, -1.50311594814139, 0.58539278534518, 0.476423420506994, -0.229810354321508, -0.669629539423225, -0.500767918117353, -1.30780681405878, -0.0658147956438969, 0.619743292251259, 0.947409254626009, 0.137968713284014, -0.0705143536229389, -0.316245167388448, 0.423768217540825, -1.77132723836955, 0.437524374017483, 1.05217040293853, 1.29145821945076, 0.189519814277623, 0.405463210651828, -1.10579240546022, 0.470126971026959, 1.3013241742778, 1.57690948154138, 0.836753145709701, -0.0990436481848584, 0.305059193206195, 0.722542224965483, 0.497020187014643, -0.798519685959293, -0.162044448918511, -0.268976403560686, 0.471344909208507, 1.07960447064393, 0.816448434674936, 1.01857006703316, -0.19352270657549, 0.193745914189151, -0.0118346974247015, 0.515110447770272, 1.29117007883295, 0.484844437955959, 0.357506193819553, -1.95817055695569, -1.62102859205691, -2.13900473718215, -2.19173201733318, -1.86372596557808, -1.18864210270607, -1.19890597040604, 0.432503235072499, 0.594410727524479, 1.21432538936706, 2.15795981275539, 1.31528364302187, 0.38422055227912, 0.786869292659675, -0.703717985086569, -0.535651668024763, 0.34627858116184, 0.537117318247469, 0.901014803953916, 1.2151594352426, 0.827351473348557, -0.682186392255085, -1.33342351753519, -1.26893821314864, -1.4632463728941, -1.64736130434257, -1.21073183651285, -0.643396605364174), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140')), structure(c(9L, 9L, 9L, 9L, 9L, 9L, 9L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 19L, 19L, 19L, 19L, 19L, 19L, 19L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 18L, 18L, 18L, 18L, 18L, 18L, 18L, 20L, 20L, 20L, 20L, 20L, 20L, 20L, 12L, 12L, 12L, 12L, 12L, 12L, 12L), .Label = c('10', '8', '2', '6', '3', '5', '9', '7', '1', '4', '17', '20', '11', '12', '16', '13', '14', '18', '15', '19'), class = c('ordered', 'factor'))); .Internal(split(argv[[1]], argv[[2]]))");
+        assertEval("{ .Internal(split(structure(1:4, names=c('a','b','c','d')), factor(c(1,2)))); }");
+        assertEval("{ .Internal(split(structure(c(TRUE,FALSE,FALSE,FALSE), names=c('a','b','c','d')), factor(c(1,2)))); }");
+        assertEval("argv <- list(structure(c(-1.13864415195445, 0.574433648632919, 0.61125743366192, 0.291104607198021, 1.44367450704693, 0.408616385050392, -0.252815027721455, 0.73544465026571, -0.711029326417947, -0.611820918993561, -0.963259276248408, -0.28935033673839, -0.482346616963731, 0.575284398820533, 0.0664802498883062, 0.0889008730409177, -0.527009741835806, -0.572160487726669, 0.458433701366337, 0.0259549922279207, 0.79246010222197, 0.200856719794408, 0.681708382019133, 1.24959713166139, 2.28504683598586, 0.885201117877485, 0.275047494865858, 0.0611635446204713, -0.226340664609402, -0.701634984067551, -1.36331112409512, -0.470720710127998, 0.0116712292760789, 0.680960771805182, 1.25010637890252, -0.168484448953506, -0.703880448859559, -0.342493773069341, -0.359950801091045, 0.187018301421814, 0.332611568778467, 0.418088885897922, 1.52526747601546, 1.23881025318897, 1.97893910443604, 1.67980257496383, -0.0423836378777035, -0.085940264442189, 0.0751591419566941, 1.33615888669544, 1.29143414265875, 0.211686019646981, 0.107754613497605, -0.842122877395922, -0.363550334633855, -1.04260396788242, -1.00216202750311, -0.725219786582336, -0.702075395338802, -0.0588517433215815, 0.676181221812652, 0.606054389584641, -0.0722001122493283, -0.565579974058951, -1.50420998542363, -1.38835023347894, -1.6387526999868, -1.22317617387598, -2.6439685322602, -1.50311594814139, 0.58539278534518, 0.476423420506994, -0.229810354321508, -0.669629539423225, -0.500767918117353, -1.30780681405878, -0.0658147956438969, 0.619743292251259, 0.947409254626009, 0.137968713284014, -0.0705143536229389, -0.316245167388448, 0.423768217540825, -1.77132723836955, 0.437524374017483, 1.05217040293853, 1.29145821945076, 0.189519814277623, 0.405463210651828, -1.10579240546022, 0.470126971026959, 1.3013241742778, 1.57690948154138, 0.836753145709701, -0.0990436481848584, 0.305059193206195, 0.722542224965483, 0.497020187014643, -0.798519685959293, -0.162044448918511, -0.268976403560686, 0.471344909208507, 1.07960447064393, 0.816448434674936, 1.01857006703316, -0.19352270657549, 0.193745914189151, -0.0118346974247015, 0.515110447770272, 1.29117007883295, 0.484844437955959, 0.357506193819553, -1.95817055695569, -1.62102859205691, -2.13900473718215, -2.19173201733318, -1.86372596557808, -1.18864210270607, -1.19890597040604, 0.432503235072499, 0.594410727524479, 1.21432538936706, 2.15795981275539, 1.31528364302187, 0.38422055227912, 0.786869292659675, -0.703717985086569, -0.535651668024763, 0.34627858116184, 0.537117318247469, 0.901014803953916, 1.2151594352426, 0.827351473348557, -0.682186392255085, -1.33342351753519, -1.26893821314864, -1.4632463728941, -1.64736130434257, -1.21073183651285, -0.643396605364174), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36', '37', '38', '39', '40', '41', '42', '43', '44', '45', '46', '47', '48', '49', '50', '51', '52', '53', '54', '55', '56', '57', '58', '59', '60', '61', '62', '63', '64', '65', '66', '67', '68', '69', '70', '71', '72', '73', '74', '75', '76', '77', '78', '79', '80', '81', '82', '83', '84', '85', '86', '87', '88', '89', '90', '91', '92', '93', '94', '95', '96', '97', '98', '99', '100', '101', '102', '103', '104', '105', '106', '107', '108', '109', '110', '111', '112', '113', '114', '115', '116', '117', '118', '119', '120', '121', '122', '123', '124', '125', '126', '127', '128', '129', '130', '131', '132', '133', '134', '135', '136', '137', '138', '139', '140')), structure(c(9L, 9L, 9L, 9L, 9L, 9L, 9L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 6L, 6L, 6L, 6L, 6L, 6L, 6L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 13L, 13L, 13L, 13L, 13L, 13L, 13L, 14L, 14L, 14L, 14L, 14L, 14L, 14L, 16L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 17L, 19L, 19L, 19L, 19L, 19L, 19L, 19L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 18L, 18L, 18L, 18L, 18L, 18L, 18L, 20L, 20L, 20L, 20L, 20L, 20L, 20L, 12L, 12L, 12L, 12L, 12L, 12L, 12L), .Label = c('10', '8', '2', '6', '3', '5', '9', '7', '1', '4', '17', '20', '11', '12', '16', '13', '14', '18', '15', '19'), class = c('ordered', 'factor'))); .Internal(split(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testsplit3() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(1034.46153846154, 480.076923076923, 504.692307692308, 480.076923076923, 0, 0, 0, 0, 480.076923076923, 517.230769230769, 444.307692307692, 819.846153846154, 945.230769230769, 542.769230769231, 0, 0, 0, 1824.30769230769, 444.307692307692, 912.153846153846, 0, 0, 1514.07692307692, 0, 936, 0), .Dim = 26L, .Dimnames = list(c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('1', '2'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(1034.46153846154, 480.076923076923, 504.692307692308, 480.076923076923, 0, 0, 0, 0, 480.076923076923, 517.230769230769, 444.307692307692, 819.846153846154, 945.230769230769, 542.769230769231, 0, 0, 0, 1824.30769230769, 444.307692307692, 912.153846153846, 0, 0, 1514.07692307692, 0, 936, 0), .Dim = 26L, .Dimnames = list(c('1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2'))), structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c('1', '2'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -41,7 +41,9 @@ public class TestBuiltin_split extends TestBase {
 
     @Test
     public void testsplit5() {
-        assertEval(Ignored.Unknown,
+        // FIXME ArrayIndexOutOfBoundsException: 2147483647
+        // at com.oracle.truffle.r.nodes.builtin.base.Split.split(Split.java:152)
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(c(1, 3, 5, 7, 8, 3, 5, NA, 4, 5, 7, 9), structure(c(8L, 6L, 3L, 2L, NA, 5L, 1L, 4L, 7L, 3L, NA, NA), .Label = c('0', '2', '6', '8', '15', '22', '29', '35'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))");
     }
 
@@ -87,8 +89,7 @@ public class TestBuiltin_split extends TestBase {
 
     @Test
     public void testsplit16() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(47.432, 12.482), .Names = c('(Intercept)', 'group2')), structure(1:2, .Label = c('0', '1'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(47.432, 12.482), .Names = c('(Intercept)', 'group2')), structure(1:2, .Label = c('0', '1'), class = 'factor')); .Internal(split(argv[[1]], argv[[2]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java
index 024362fa915abf7ec5eacfd11ca15285a7b33bf5..4fee95e62edcbd039e3d07d33089fb58368b249e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sprintf.java
@@ -24,7 +24,8 @@ public class TestBuiltin_sprintf extends TestBase {
 
     @Test
     public void testsprintf2() {
-        assertEval(Ignored.Unknown, "argv <- list('%1.0f', 3.14159265358979); .Internal(sprintf(argv[[1]], argv[[2]]))");
+        // FIXME According to docs "a precision of 0 suppresses the decimal point"
+        assertEval(Ignored.ImplementationError, "argv <- list('%1.0f', 3.14159265358979); .Internal(sprintf(argv[[1]], argv[[2]]))");
     }
 
     @Test
@@ -50,7 +51,8 @@ public class TestBuiltin_sprintf extends TestBase {
 
     @Test
     public void testsprintf7() {
-        assertEval(Ignored.Unknown, "argv <- list('p,L,S = (%2d,%2d,%2d): ', TRUE, FALSE, NA); .Internal(sprintf(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
+        // FIXME NA translated to -1 in output
+        assertEval(Ignored.ImplementationError, "argv <- list('p,L,S = (%2d,%2d,%2d): ', TRUE, FALSE, NA); .Internal(sprintf(argv[[1]], argv[[2]], argv[[3]], argv[[4]]))");
     }
 
     @Test
@@ -65,7 +67,8 @@ public class TestBuiltin_sprintf extends TestBase {
 
     @Test
     public void testsprintf10() {
-        assertEval(Ignored.Unknown, "argv <- list('%.0f%% said yes (out of a sample of size %.0f)', 66.666, 3); .Internal(sprintf(argv[[1]], argv[[2]], argv[[3]]))");
+        // FIXME According to docs "a precision of 0 suppresses the decimal point"
+        assertEval(Ignored.ImplementationError, "argv <- list('%.0f%% said yes (out of a sample of size %.0f)', 66.666, 3); .Internal(sprintf(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -105,7 +108,8 @@ public class TestBuiltin_sprintf extends TestBase {
 
     @Test
     public void testsprintf18() {
-        assertEval(Ignored.Unknown,
+        // FIXME %5g should mean 5 significant digits but we output six
+        assertEval(Ignored.ImplementationError,
                         "argv <- list('%5g', structure(c(18, 18, 0, 14, 4, 12, 12, 0, 4, 8, 26, 23, 3, 18, 5, 8, 5, 3, 0, 5, 21, 0, 21, 0, 0), .Dim = c(5L, 5L), .Dimnames = list(NULL, c('', '', '', '', '')))); .Internal(sprintf(argv[[1]], argv[[2]]))");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sqrt.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sqrt.java
index 586e0d3214a700095a8c0247a24425a56e2fed2a..cc75851fa2cb41368f94ef8fa984ccec610f710d 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sqrt.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sqrt.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -49,7 +49,11 @@ public class TestBuiltin_sqrt extends TestBase {
 
     @Test
     public void testsqrt7() {
-        assertEval(Ignored.Unknown, "argv <- list(structure(1:10, id = 'test 1', class = structure('withId', package = '.GlobalEnv')));sqrt(argv[[1]]);");
+        // FIXME GnuR outputs
+        // attr(,"class")attr(,"package")
+        // while FastR outputs just
+        // attr(,"package")
+        assertEval(Ignored.OutputFormatting, "argv <- list(structure(1:10, id = 'test 1', class = structure('withId', package = '.GlobalEnv')));sqrt(argv[[1]]);");
     }
 
     @Test
@@ -64,7 +68,8 @@ public class TestBuiltin_sqrt extends TestBase {
 
     @Test
     public void testsqrt10() {
-        assertEval(Ignored.Unknown, "argv <- list(c(6L, 5L, 4L, 3L, 2L, 1L, 0L, -1L, -2L, -3L, -4L));sqrt(argv[[1]]);");
+        // FIXME missing warning about NaNs being produced
+        assertEval(Output.MissingWarning, "argv <- list(c(6L, 5L, 4L, 3L, 2L, 1L, 0L, -1L, -2L, -3L, -4L));sqrt(argv[[1]]);");
     }
 
     @Test
@@ -87,7 +92,7 @@ public class TestBuiltin_sqrt extends TestBase {
         assertEval("{ sqrt(c(a=9,b=81)) }");
         assertEval("{ sqrt(1:5) }");
 
-        assertEval(Ignored.Unknown, "{ sqrt(-1L) }"); // FIXME warning
-        assertEval(Ignored.Unknown, "{ sqrt(-1) }"); // FIXME warning
+        assertEval(Output.MissingWarning, "{ sqrt(-1L) }"); // FIXME warning
+        assertEval(Output.MissingWarning, "{ sqrt(-1) }"); // FIXME warning
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java
index 0c3fa4db12cce8484d2a9ee99aa9fd709684163d..363f4cfe0f04b6ee6f01525d61023aef9d5f2fe4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strptime.java
@@ -69,9 +69,11 @@ public class TestBuiltin_strptime extends TestBase {
 
     @Test
     public void testArgsCasts() {
-        assertEval("{ .Internal(strptime(,'','') }");
-        assertEval("{ .Internal(strptime('',,'') }");
-        assertEval("{ .Internal(strptime('','',) }");
+        assertEval("{ .Internal(strptime('1970-01-01 0:3:22', '%H:%M:%S', 'UTC')); }");
+        // Ingoring error context since changing casts has no effect
+        // due to hitting InternalNode:152 first that throws the resulting RError
+        assertEval(Output.IgnoreErrorContext, "{ .Internal(strptime(,'','')); }");
+        assertEval(Output.IgnoreErrorContext, "{ .Internal(strptime('',,'')); }");
+        assertEval(Output.IgnoreErrorContext, "{ .Internal(strptime('','',)); }");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java
index 818a0413bd5d0dd396904e6f972134bd0a74caea..5b2ceaa08e93144827495edc7ba769fafab4fb1c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strrep.java
@@ -38,11 +38,10 @@ public class TestBuiltin_strrep extends TestBase {
     @Test
     public void testArgsCasts() {
         // GnuR fails with segfault
-        assertEvalFastR("{ .Internal(strrep(NULL, 5) }", "cat(\"character(0)\")");
+        assertEvalFastR(".Internal(strrep(NULL, 5))", "cat(\"character(0)\\n\")");
         // GnuR - infinite loop
-        assertEvalFastR("{ .Internal(strrep('aa', NULL) }", "cat(\"character(0)\")");
+        assertEvalFastR(".Internal(strrep('aa', NULL))", "cat(\"character(0)\\n\")");
         assertEval("{ .Internal(strrep(, '') }");
         assertEval("{ .Internal(strrep('', ) }");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java
index f06f1669ca542addb832b1f4b26154654006cc2e..dd40c57132e6884495892cf0b5f644f696b001c1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_strsplit.java
@@ -142,6 +142,7 @@ public class TestBuiltin_strsplit extends TestBase {
         assertEval("strsplit(c('1', 'b'), c('1', 'b'), fixed=FALSE)");
         assertEval("strsplit(c('a1a', 'a1b'), c('1', '1'), fixed=FALSE)");
         assertEval("strsplit(c('a1a', 'a1b'), '1', fixed=FALSE)");
+        assertEval("strsplit(c('','a , b'), '[[:space:]]*,[[:space:]]*')");
 
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java
index ad2e9940d396e8865d77cb87da8e0c412f93eee5..f6ff5dcb0d200307287838f2a86794e251e8d86c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substitute.java
@@ -112,5 +112,7 @@ public class TestBuiltin_substitute extends TestBase {
         assertEval("substitute(quote(x+1), environment())");
         assertEval("f<-function() {}; substitute(quote(x+1), f)");
         assertEval("substitute(quote(x+1), setClass('a'))");
+
+        assertEval("typeof(substitute(set))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java
index 3942c970d887d28a85bb8200d35d96f4ec238753..ac9d3ee1947aee60951febafd02bd6da242a3dc3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_substr.java
@@ -29,9 +29,7 @@ public class TestBuiltin_substr extends TestBase {
 
     @Test
     public void testsubstr3() {
-        // FIXME: We do not treat .Names as column headers while GnuR does
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c('as.formula', 'coef', 'makepredictcall', 'na.fail', 'predict'), .Names = c('as.formula', 'coef', 'makepredictcall', 'na.fail', 'predict')), 1L, 6L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c('as.formula', 'coef', 'makepredictcall', 'na.fail', 'predict'), .Names = c('as.formula', 'coef', 'makepredictcall', 'na.fail', 'predict')), 1L, 6L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -41,11 +39,7 @@ public class TestBuiltin_substr extends TestBase {
 
     @Test
     public void testsubstr5() {
-        // FIXME: GnuR outputs all params to structure(...) as result of substr() i.e. here:
-        // attr(,"Rd_tag")
-        // [1] "TEXT"
-        // IMHO superfluous => ReferenceError
-        assertEval(Ignored.ReferenceError, "argv <- list(structure('to be supported).', Rd_tag = 'TEXT'), 17L, 17L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure('to be supported).', Rd_tag = 'TEXT'), 17L, 17L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
@@ -60,9 +54,7 @@ public class TestBuiltin_substr extends TestBase {
 
     @Test
     public void testsubstr8() {
-        // FIXME: We do not treat .Names as column headers while GnuR does
-        assertEval(Ignored.ImplementationError,
-                        "argv <- list(structure(c('model.frame', 'predict', 'residuals'), .Names = c('model.frame', 'predict', 'residuals')), 1L, 6L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))");
+        assertEval("argv <- list(structure(c('model.frame', 'predict', 'residuals'), .Names = c('model.frame', 'predict', 'residuals')), 1L, 6L); .Internal(substr(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java
index c505c30846a814ee0f0e7118adb8b768f5f7a274..bdd46202cfd8e039ae46b5be09f8b5380c8cd6d1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summary.java
@@ -20,7 +20,8 @@ public class TestBuiltin_summary extends TestBase {
 
     @Test
     public void testsummary1() {
-        assertEval(Ignored.Unknown,
+        // Little rounding difference 1.4189 vs. 1.419 in FastR
+        assertEval(Ignored.OutputFormatting,
                         "argv <- structure(list(object = structure(c(4L, 4L, 4L, 4L, 4L,     3L, 4L, 4L, 4L, 4L, 3L, 4L, 3L, 4L, 4L, 4L, 4L, 2L, 4L, 3L,     4L, 4L, 4L, 2L), .Dim = c(6L, 4L), .Dimnames = structure(list(c('25-34',     '35-44', '45-54', '55-64', '65-74', '75+'), c('0-39g/day',     '40-79', '80-119', '120+')), .Names = c('', '')), class = 'table')),     .Names = 'object');" +
                                         "do.call('summary', argv)");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java
index f3f28eb9901d0e5c3e4d8095a63329ce6fbd9549..81dce8c9bc9d42be4819c13298d579533b4fa6b8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -20,7 +20,15 @@ public class TestBuiltin_sweep extends TestBase {
 
     @Test
     public void testsweep1() {
-        assertEval(Ignored.Unknown,
+        // FIXME FastR does not honor .Dim attr in output:
+        // Expected output:
+        // [1,]
+        // [2,]
+        // [3,]
+        // [4,]
+        // [5,]
+        // FastR output: integer(0)
+        assertEval(Ignored.OutputFormatting,
                         "argv <- structure(list(x = structure(integer(0), .Dim = c(5L,     0L)), MARGIN = 2, STATS = integer(0)), .Names = c('x', 'MARGIN',     'STATS'));" + "do.call('sweep', argv)");
     }
 
@@ -32,8 +40,12 @@ public class TestBuiltin_sweep extends TestBase {
 
         assertEval("{ A <- matrix(1:15, ncol=5); sweep(A, 2, colSums(A), \"/\") }");
 
-        // Correct output but warnings
-        assertEval(Ignored.Unknown, "{ A <- matrix(1:50, nrow=4); sweep(A, 1, 5, '-') }");
-        assertEval(Ignored.Unknown, "{ A <- matrix(7:1, nrow=5); sweep(A, 1, -1, '*') }");
+        // FIXME results are the same but GnuR outputs the following warning:
+        // Warning message:
+        // In matrix(1:50, nrow = 4) :
+        // data length [50] is not a sub-multiple or multiple of the number of rows [4]
+        assertEval(Output.MissingWarning, "{ A <- matrix(1:50, nrow=4); sweep(A, 1, 5, '-') }");
+        // Similar problem like on the line above
+        assertEval(Output.MissingWarning, "{ A <- matrix(7:1, nrow=5); sweep(A, 1, -1, '*') }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscall.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscall.java
index 54d6ce721f9d5d609956d7a6427022ceaf546596..37058fbb8f7b7a7904069fedc1d47e0fd59739cd 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscall.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscall.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -40,7 +40,7 @@ public class TestBuiltin_syscall extends TestBase {
         assertEval("{ f <- function(x, y) sys.call() ; f(y=1, x=2) }");
 
         // fails because can't parse out the "name"
-        assertEval(Ignored.Unknown, "{ (function() sys.call())() }");
+        assertEval(Output.IgnoreWhitespace, "{ (function() sys.call())() }");
 
         assertEval("{ foo<-function(x, z) UseMethod(\"foo\"); foo.baz<-function(x, z) NextMethod(); y<-1; class(y)<-c(\"baz\", \"bar\"); foo.bar<-function(x, z) sys.call(0); foo(y, 42) }");
         assertEval("{ foo<-function(x, ...) UseMethod(\"foo\"); foo.baz<-function(x, ...) NextMethod(); y<-1; class(y)<-c(\"baz\", \"bar\"); foo.bar<-function(x, ...) sys.call(0); foo(y, 42) }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysonexit.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysonexit.java
index 269c6122bc06cf6447b1842646170061b64ab84a..b4d82de50c6e7e911508fab1c28c688d4e9e8bce 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysonexit.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysonexit.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.
  */
@@ -19,6 +19,7 @@ public class TestBuiltin_sysonexit extends TestBase {
 
     @Test
     public void testsysonexit1() {
-        assertEval(Ignored.Unknown, " .Internal(sys.on.exit())");
+        // FIXME unimplemented
+        assertEval(Ignored.Unimplemented, " .Internal(sys.on.exit())");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java
index 693cde32eb6e252583908b569377a1a8b142a8c2..b4640e1d0567158ad6dba2e8ccfc5be46df9f85a 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_t.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -46,5 +46,6 @@ public class TestBuiltin_t extends TestBase {
         assertEval("t(1)");
         assertEval("t(TRUE)");
         assertEval("t(as.raw(c(1,2,3,4)))");
+        assertEval("t(matrix(1:6, 3, 2, dimnames=list(x=c(\"x1\",\"x2\",\"x3\"),y=c(\"y1\",\"y2\"))))");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tanpi.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tanpi.java
index 493d8442509d23d523afe342b455dbb9b38f04eb..741bd2dffbad8dae8a93688dd01fcf0ce1851628 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tanpi.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tanpi.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
@@ -61,12 +61,14 @@ public class TestBuiltin_tanpi extends TestBase {
 
     @Test
     public void testtan7() {
-        assertEval(Ignored.Unknown, "argv <- list(Inf);tanpi(argv[[1]]);");
+        // FIXME Missing warning about NaNs produced
+        assertEval(Output.IgnoreWarningMessage, "argv <- list(Inf);tanpi(argv[[1]]);");
     }
 
     @Test
     public void testTrigExp() {
-        assertEval(Ignored.Unknown, "{ tanpi(c(0,0.5,-0.5)) }");
+        // FIXME Missing warning about NaNs produced
+        assertEval(Output.IgnoreWarningMessage, "{ tanpi(c(0,0.5,-0.5)) }");
         assertEval("{ tanpi(1.2) }");
         assertEval("{ tannpi(c(0.3,0.6,0.9)) }");
         assertEval("{ tanpi() }");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tcrossprod.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tcrossprod.java
index 01fb137aebc1254013557b60ec723df70f21f588..463501fc5b7937471a51b7f93a6dfa3c5dd7f4f0 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tcrossprod.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tcrossprod.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.
  */
@@ -19,47 +19,46 @@ public class TestBuiltin_tcrossprod extends TestBase {
 
     @Test
     public void testtcrossprod1() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(5, 2, 0, 2, 5, 2, 0, 2, 5), .Dim = c(3L, 3L)), structure(c(0, 1, 0, 0, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0), .Dim = c(5L, 3L), .Dimnames = list(c('a', 'b', 'c', 'd', 'e'), NULL))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(5, 2, 0, 2, 5, 2, 0, 2, 5), .Dim = c(3L, 3L)), structure(c(0, 1, 0, 0, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0), .Dim = c(5L, 3L), .Dimnames = list(c('a', 'b', 'c', 'd', 'e'), NULL))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testtcrossprod2() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(5, 2, 0, 2, 5, 2, 0, 2, 5), .Dim = c(3L, 3L), .Dimnames = list(c('A', 'B', 'C'), c('A', 'B', 'C'))), structure(c(0, 1, 0, 0, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0), .Dim = c(5L, 3L), .Dimnames = list(NULL, c('A', 'B', 'C')))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(5, 2, 0, 2, 5, 2, 0, 2, 5), .Dim = c(3L, 3L), .Dimnames = list(c('A', 'B', 'C'), c('A', 'B', 'C'))), structure(c(0, 1, 0, 0, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0), .Dim = c(5L, 3L), .Dimnames = list(NULL, c('A', 'B', 'C')))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testtcrossprod3() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(-1.67712982705863, -1.48498667828929, -1.66855080519244, -1.58355627712096, -1.82359988031979, -1.9949008033236, -0.0318360538544526, -0.560218641212122, 0.066207937805176, 0.499775901814107, -0.00128363357081381, -0.00713986667014182, 0.296776079992064, -0.138150806520963, 0.253601178172029, -0.170225064799926, -0.240191246767341, -0.00408674943172847, -0.242382276284081, 0.0729153527553058, 0.269807081327349, 0.0299339639014576, -0.077267349576335, -0.0293027062153706, -0.0099926992270607, 0.0334924583850379, -0.0453336990810482, 0.0438958486872448, -0.112099180250145, 0.089015596249019), .Dim = c(6L, 5L)), structure(c(-0.399602067979347, -0.353820997034499, -0.397557983601584, -0.377306725388702, -0.434500818950138, -0.47531590790431, -0.0422023061126668, -0.742633452454394, 0.087766143100416, 0.662509734796894, -0.00170160212505116, -0.00946470439441127, 0.584095849615428, -0.271899651454647, 0.499121747385523, -0.335026171424641, -0.472729171281292, -0.00804328091925277, -0.637436340955898, 0.191758639997983, 0.70956029179181, 0.0787227379500612, -0.2032038701195, -0.0770626058818733, -0.062340518587102, 0.208946269374942, -0.282819110829524, 0.273848927982668, -0.699342677207614, 0.555333279468297), .Dim = c(6L, 5L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(-1.67712982705863, -1.48498667828929, -1.66855080519244, -1.58355627712096, -1.82359988031979, -1.9949008033236, -0.0318360538544526, -0.560218641212122, 0.066207937805176, 0.499775901814107, -0.00128363357081381, -0.00713986667014182, 0.296776079992064, -0.138150806520963, 0.253601178172029, -0.170225064799926, -0.240191246767341, -0.00408674943172847, -0.242382276284081, 0.0729153527553058, 0.269807081327349, 0.0299339639014576, -0.077267349576335, -0.0293027062153706, -0.0099926992270607, 0.0334924583850379, -0.0453336990810482, 0.0438958486872448, -0.112099180250145, 0.089015596249019), .Dim = c(6L, 5L)), structure(c(-0.399602067979347, -0.353820997034499, -0.397557983601584, -0.377306725388702, -0.434500818950138, -0.47531590790431, -0.0422023061126668, -0.742633452454394, 0.087766143100416, 0.662509734796894, -0.00170160212505116, -0.00946470439441127, 0.584095849615428, -0.271899651454647, 0.499121747385523, -0.335026171424641, -0.472729171281292, -0.00804328091925277, -0.637436340955898, 0.191758639997983, 0.70956029179181, 0.0787227379500612, -0.2032038701195, -0.0770626058818733, -0.062340518587102, 0.208946269374942, -0.282819110829524, 0.273848927982668, -0.699342677207614, 0.555333279468297), .Dim = c(6L, 5L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testtcrossprod4() {
-        assertEval(Ignored.Unknown, "argv <- list(c(2, 3), structure(c(0, 0, 1, 0), .Dim = c(2L, 2L), .Dimnames = list(NULL, NULL))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(c(2, 3), structure(c(0, 0, 1, 0), .Dim = c(2L, 2L), .Dimnames = list(NULL, NULL))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testtcrossprod5() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(-0.106539372596213, -2.87400113021639, 0.341152775291742, 1.88577541025803, 0.842201032082677, -1.43117364207636, -0.69348461621825, -2.41970841038843, -3.02719090531729, -0.226641199170227, -0.332680183991575, -1.62371869115524, -1.66979618600051, -1.10431770731054, 1.88731633228519, 2.05877121721062, -0.223853590000374, 2.00359231906507, 2.73128102907396, 0.539089155601206, -0.199828039026098, -1.05787977326062, 0.306997029957149, 1.45711168105796, 1.49857746263809, -0.757919845814536, 0.268252398125501, -0.535834002202256, -0.271560453176356, -2.05847896960824, 0.980553291004929, 0.685818887220841, -0.522933983909647, -0.337189871316714, 0.191459457586776, 1.89272736696455, -0.453746315234956, 0.612338437255857, 1.37687299952389, -1.15071450872488, -0.20817483353688, -0.081142998844394, -0.253631714967276, -0.410462721238244, -0.68459626706876, -0.624834027577721, 0.00753430632431097, -0.0556623066116985, -0.563702942039652, 0.0408500401240061, -0.420302429975138, 0.033747665813787, 0.339840694442255, -0.250248532584852, -0.31434827109732, 0.378366203759376, -0.193977362697154, -0.518701418701189, 1.24086430187875, 0.0626244079886504, -0.168813902431602, -0.233723461170579, -0.0800002226605061, -0.0555238917407563, -0.947495254278566, -0.0485572234634504, -0.0296030565974314, -0.095544458696536, 0.0295824037592777, 0.194854132525369, 0.267233992325682, -0.087254491408015, 0.126110082843019, 0.159157280802928, -0.155595903815538, 0.170585777111235, -0.160659663851048, -0.059679874503493, 0.0114766797349517, -0.288711739670586, 0.192267902822735, -0.558695699349865, -0.0862396209998433, 0.00725278175306798, -0.128294571915242, -0.130284537275488, -0.0857140300930927, -0.0514859262258765, -0.0490801347386973, 0.0204665694600954, -0.14875269796722, 0.196176132315475, -0.0529883263026191, -0.132778199491125, -0.228017010951841, 0.0529472898389869), .Dim = c(12L, 8L)), structure(c(-0.0185462290552347, -0.500302207222603, 0.059387411050087, 0.328273218183171, 0.146609210012521, -0.249136760776327, -0.120720858638907, -0.421219548532773, -0.526969274886959, -0.0394533916498165, -0.057912513881884, -0.282654740999492, -0.321354169237256, -0.212527194864884, 0.363216168017541, 0.396212855019715, -0.0430808772043306, 0.385593613508892, 0.525638130815129, 0.103748319223306, -0.0384571326787796, -0.203590161804909, 0.0590819264933657, 0.28042279511599, 0.416779971858557, -0.210790446196582, 0.0746055707690415, -0.149024582263218, -0.0755255973444945, -0.572498138010465, 0.272708607475933, 0.190737938906932, -0.145436866983219, -0.0937782587701373, 0.0532481432121619, 0.52639978807016, -0.204031585044791, 0.275344124552216, 0.61912476435818, -0.517430328944052, -0.0936079034183924, -0.0364867638890611, -0.114048046419078, -0.184568682552654, -0.307835583002935, -0.280962892162748, 0.0033878764630103, -0.0250291148686315, -0.338839482109357, 0.0245547883601272, -0.252642033739931, 0.0202855808510911, 0.204276820851501, -0.150423346865756, -0.188953431740463, 0.227434343460447, -0.116598981866977, -0.311789254542753, 0.745878344887204, 0.0376432698639114, -0.159472254176866, -0.220789915226282, -0.0755732534972413, -0.0524513683353668, -0.895063746796005, -0.0458702143055051, -0.0279649134231136, -0.0902573187573718, 0.0279454034502495, 0.184071497085901, 0.252446075441722, -0.0824260930614398, 0.167922807083695, 0.211927046257706, -0.207184868571959, 0.227144744458931, -0.21392755544038, -0.0794671752416819, 0.0152818571968794, -0.384436237535829, 0.256015738204522, -0.743935362069355, -0.114833000769291, 0.00965749481472171, -0.300640883681616, -0.30530409690622, -0.200859174058623, -0.120650267011609, -0.115012621802916, 0.0479606224687302, -0.348581720171566, 0.459712089888966, -0.124170937293853, -0.311147655218321, -0.534326859224339, 0.124074773921503), .Dim = c(12L, 8L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(-0.106539372596213, -2.87400113021639, 0.341152775291742, 1.88577541025803, 0.842201032082677, -1.43117364207636, -0.69348461621825, -2.41970841038843, -3.02719090531729, -0.226641199170227, -0.332680183991575, -1.62371869115524, -1.66979618600051, -1.10431770731054, 1.88731633228519, 2.05877121721062, -0.223853590000374, 2.00359231906507, 2.73128102907396, 0.539089155601206, -0.199828039026098, -1.05787977326062, 0.306997029957149, 1.45711168105796, 1.49857746263809, -0.757919845814536, 0.268252398125501, -0.535834002202256, -0.271560453176356, -2.05847896960824, 0.980553291004929, 0.685818887220841, -0.522933983909647, -0.337189871316714, 0.191459457586776, 1.89272736696455, -0.453746315234956, 0.612338437255857, 1.37687299952389, -1.15071450872488, -0.20817483353688, -0.081142998844394, -0.253631714967276, -0.410462721238244, -0.68459626706876, -0.624834027577721, 0.00753430632431097, -0.0556623066116985, -0.563702942039652, 0.0408500401240061, -0.420302429975138, 0.033747665813787, 0.339840694442255, -0.250248532584852, -0.31434827109732, 0.378366203759376, -0.193977362697154, -0.518701418701189, 1.24086430187875, 0.0626244079886504, -0.168813902431602, -0.233723461170579, -0.0800002226605061, -0.0555238917407563, -0.947495254278566, -0.0485572234634504, -0.0296030565974314, -0.095544458696536, 0.0295824037592777, 0.194854132525369, 0.267233992325682, -0.087254491408015, 0.126110082843019, 0.159157280802928, -0.155595903815538, 0.170585777111235, -0.160659663851048, -0.059679874503493, 0.0114766797349517, -0.288711739670586, 0.192267902822735, -0.558695699349865, -0.0862396209998433, 0.00725278175306798, -0.128294571915242, -0.130284537275488, -0.0857140300930927, -0.0514859262258765, -0.0490801347386973, 0.0204665694600954, -0.14875269796722, 0.196176132315475, -0.0529883263026191, -0.132778199491125, -0.228017010951841, 0.0529472898389869), .Dim = c(12L, 8L)), structure(c(-0.0185462290552347, -0.500302207222603, 0.059387411050087, 0.328273218183171, 0.146609210012521, -0.249136760776327, -0.120720858638907, -0.421219548532773, -0.526969274886959, -0.0394533916498165, -0.057912513881884, -0.282654740999492, -0.321354169237256, -0.212527194864884, 0.363216168017541, 0.396212855019715, -0.0430808772043306, 0.385593613508892, 0.525638130815129, 0.103748319223306, -0.0384571326787796, -0.203590161804909, 0.0590819264933657, 0.28042279511599, 0.416779971858557, -0.210790446196582, 0.0746055707690415, -0.149024582263218, -0.0755255973444945, -0.572498138010465, 0.272708607475933, 0.190737938906932, -0.145436866983219, -0.0937782587701373, 0.0532481432121619, 0.52639978807016, -0.204031585044791, 0.275344124552216, 0.61912476435818, -0.517430328944052, -0.0936079034183924, -0.0364867638890611, -0.114048046419078, -0.184568682552654, -0.307835583002935, -0.280962892162748, 0.0033878764630103, -0.0250291148686315, -0.338839482109357, 0.0245547883601272, -0.252642033739931, 0.0202855808510911, 0.204276820851501, -0.150423346865756, -0.188953431740463, 0.227434343460447, -0.116598981866977, -0.311789254542753, 0.745878344887204, 0.0376432698639114, -0.159472254176866, -0.220789915226282, -0.0755732534972413, -0.0524513683353668, -0.895063746796005, -0.0458702143055051, -0.0279649134231136, -0.0902573187573718, 0.0279454034502495, 0.184071497085901, 0.252446075441722, -0.0824260930614398, 0.167922807083695, 0.211927046257706, -0.207184868571959, 0.227144744458931, -0.21392755544038, -0.0794671752416819, 0.0152818571968794, -0.384436237535829, 0.256015738204522, -0.743935362069355, -0.114833000769291, 0.00965749481472171, -0.300640883681616, -0.30530409690622, -0.200859174058623, -0.120650267011609, -0.115012621802916, 0.0479606224687302, -0.348581720171566, 0.459712089888966, -0.124170937293853, -0.311147655218321, -0.534326859224339, 0.124074773921503), .Dim = c(12L, 8L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testtcrossprod6() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(-1.22589324018138, -0.740548974281808, -0.54768368397833, -0.441021701509591, -0.370068251595057, -0.319690799411412, -0.282987166340516, -0.254112864677485, -0.230083320312515, 0.203647970189376, -0.0305516337408725, -0.0825170335109532, -0.0984577177107505, -0.100129992839015, -0.0988979642888749, -0.0945771185256416, -0.0902309571831907, -0.0871241228998968, -0.00955870050771132, 0.0197754782700907, 0.0125304440435148, 0.00419858922572787, -0.00191073996840182, -0.0061756059258365, -0.00956682744689523, -0.0127366531032827, -0.0131079781713544, 0.000214464770644159, -0.000956552371122151, 5.72249143534175e-05, 0.00029865136977495, 0.00077852017665313, 0.00142425180877207, 0.000491677810053133, -0.000120006753650731, -0.00247588122373662, 4.2574997724815e-05, -0.000297064220851874, 0.000399761711902461, 5.67830351414009e-05, -0.00026523273781528, 0.000320119491527155, -0.00026454073650643, -0.000195756422133707, 0.000192249930248858, -4.94461924222768e-07, 2.80125995838013e-05, -0.000119138513940463, 0.000151917649712048, -7.31975645151543e-05, 4.92140187851149e-05, -1.13604576670922e-05, -3.74519303853871e-05, 9.55915555684852e-06), .Dim = c(9L, 6L)), structure(c(-0.709851441473678, -0.428813651666777, -0.317135326144804, -0.255372882626744, -0.214287405483635, -0.185116425598763, -0.163863247924954, -0.147143631578904, -0.133229363887123, 0.633337192677659, -0.0950143815681878, -0.256624734846691, -0.306199636924392, -0.311400346924765, -0.307568786499592, -0.294131125799441, -0.280614734641737, -0.270952601985731, -0.28505721606605, 0.58973945020027, 0.373679821042009, 0.125209295460755, -0.0569816174886273, -0.184167401344961, -0.285299575647986, -0.379829336915808, -0.390902901787376, 0.0675695685124445, -0.301372718615498, 0.0180293609967187, 0.0940935153626058, 0.245281648154537, 0.448726753036158, 0.154908693733931, -0.0378094944843564, -0.780054577138554, 0.056333641054865, -0.393064241503382, 0.528949712019966, 0.0751331835725979, -0.350946016360591, 0.423570111428232, -0.350030386168567, -0.259017559788085, 0.254377901167792, -0.00226968135332679, 0.128583560874789, -0.546870143699694, 0.697333080468545, -0.335991790571385, 0.225902410856869, -0.0521468239901137, -0.171912019667483, 0.0438784789244046), .Dim = c(9L, 6L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(-1.22589324018138, -0.740548974281808, -0.54768368397833, -0.441021701509591, -0.370068251595057, -0.319690799411412, -0.282987166340516, -0.254112864677485, -0.230083320312515, 0.203647970189376, -0.0305516337408725, -0.0825170335109532, -0.0984577177107505, -0.100129992839015, -0.0988979642888749, -0.0945771185256416, -0.0902309571831907, -0.0871241228998968, -0.00955870050771132, 0.0197754782700907, 0.0125304440435148, 0.00419858922572787, -0.00191073996840182, -0.0061756059258365, -0.00956682744689523, -0.0127366531032827, -0.0131079781713544, 0.000214464770644159, -0.000956552371122151, 5.72249143534175e-05, 0.00029865136977495, 0.00077852017665313, 0.00142425180877207, 0.000491677810053133, -0.000120006753650731, -0.00247588122373662, 4.2574997724815e-05, -0.000297064220851874, 0.000399761711902461, 5.67830351414009e-05, -0.00026523273781528, 0.000320119491527155, -0.00026454073650643, -0.000195756422133707, 0.000192249930248858, -4.94461924222768e-07, 2.80125995838013e-05, -0.000119138513940463, 0.000151917649712048, -7.31975645151543e-05, 4.92140187851149e-05, -1.13604576670922e-05, -3.74519303853871e-05, 9.55915555684852e-06), .Dim = c(9L, 6L)), structure(c(-0.709851441473678, -0.428813651666777, -0.317135326144804, -0.255372882626744, -0.214287405483635, -0.185116425598763, -0.163863247924954, -0.147143631578904, -0.133229363887123, 0.633337192677659, -0.0950143815681878, -0.256624734846691, -0.306199636924392, -0.311400346924765, -0.307568786499592, -0.294131125799441, -0.280614734641737, -0.270952601985731, -0.28505721606605, 0.58973945020027, 0.373679821042009, 0.125209295460755, -0.0569816174886273, -0.184167401344961, -0.285299575647986, -0.379829336915808, -0.390902901787376, 0.0675695685124445, -0.301372718615498, 0.0180293609967187, 0.0940935153626058, 0.245281648154537, 0.448726753036158, 0.154908693733931, -0.0378094944843564, -0.780054577138554, 0.056333641054865, -0.393064241503382, 0.528949712019966, 0.0751331835725979, -0.350946016360591, 0.423570111428232, -0.350030386168567, -0.259017559788085, 0.254377901167792, -0.00226968135332679, 0.128583560874789, -0.546870143699694, 0.697333080468545, -0.335991790571385, 0.225902410856869, -0.0521468239901137, -0.171912019667483, 0.0438784789244046), .Dim = c(9L, 6L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testtcrossprod7() {
-        assertEval(Ignored.Unknown, "argv <- list(0, 0); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(0, 0); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
     }
 
     @Test
     public void testtcrossprod8() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(1.1173625565162, 1.46907016195074, 1.1173625565162, -0.59596185089264, -1.32605913508878e-308, 0.595961850892641), .Dim = c(3L, 2L)), structure(c(0.517876924314756, 0.680886908762812, 0.517876924314755, -0.707106781186547, -1.57336481399136e-308, 0.707106781186548), .Dim = c(3L, 2L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+        assertEval("argv <- list(structure(c(1.1173625565162, 1.46907016195074, 1.1173625565162, -0.59596185089264, -1.32605913508878e-308, 0.595961850892641), .Dim = c(3L, 2L)), structure(c(0.517876924314756, 0.680886908762812, 0.517876924314755, -0.707106781186547, -1.57336481399136e-308, 0.707106781186548), .Dim = c(3L, 2L))); .Internal(tcrossprod(argv[[1]], argv[[2]]))");
+    }
+
+    @Test
+    public void testTCrossprodDimnames() {
+        assertEval("{ tcrossprod(structure(1:9, .Dim=c(3L,3L), .Dimnames=list(c('a', 'b', 'c'), c('A', 'B', 'C'))), structure(1:9, .Dim=c(3L,3L), .Dimnames=list(c('d', 'e', 'f'), c('D', 'E', 'F')))) }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java
index 6773ef1d1aa7659430e9f11b781b27a290b2bf0a..a5c28d6e0256d4db78209ff9e55b8c256b176b97 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tdefault.java
@@ -84,8 +84,7 @@ public class TestBuiltin_tdefault extends TestBase {
 
     @Test
     public void testtdefault14() {
-        assertEval(Ignored.Unknown,
-                        "argv <- list(structure(c(794, 86, 150, 570), .Dim = c(2L, 2L), .Dimnames = structure(list(`1st Survey` = c('Approve', 'Disapprove'), `2nd Survey` = c('Approve', 'Disapprove')), .Names = c('1st Survey', '2nd Survey')))); .Internal(t.default(argv[[1]]))");
+        assertEval("argv <- list(structure(c(794, 86, 150, 570), .Dim = c(2L, 2L), .Dimnames = structure(list(`1st Survey` = c('Approve', 'Disapprove'), `2nd Survey` = c('Approve', 'Disapprove')), .Names = c('1st Survey', '2nd Survey')))); .Internal(t.default(argv[[1]]))");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_trunc.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_trunc.java
index f2080c629791428866d06c5d55d58a8be498e3ed..c979ed66c228c9c40eb90a3c9a4306cc12b952c2 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_trunc.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_trunc.java
@@ -41,7 +41,8 @@ public class TestBuiltin_trunc extends TestBase {
     public void testTrunc() {
         assertEval("{ typeof(trunc(42L)); }");
         assertEval("{ typeof(trunc(TRUE)); }");
-        assertEval("{ trunc(1+1i); }");
+        // not implemented for complex in GNU R
+        assertEvalFastR("{ trunc(1.1+1.9i); }", "1+1i");
         assertEval("{ trunc(\"aaa\"); }");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java
index 7508bec871d30bf9a0cc7024e238c45af050a967..7beb5839d2c2f90561a96c652fe6e333d68da693 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unlist.java
@@ -34,9 +34,10 @@ public class TestBuiltin_unlist extends TestBase {
 
     @Test
     public void testunlist4() {
+        // FIXME The default = quote(`\\001... gets evaluated even when quoted
         // Output.IgnoreWhitespace is not enough; '\\001NULL\\001' shows up 'translated' in FastR
         // but not in GnuR
-        assertEval(Ignored.Unknown,
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(list(list(structure(function (e1, e2) standardGeneric('Ops'), generic = structure('Ops', package = 'base'), package = 'base', group = list(), valueClass = character(0), signature = c('e1', 'e2'), default = quote(`\\001NULL\\001`), skeleton = quote((function (e1, e2) stop('invalid call in method dispatch to \\'Ops\\' (no default method)', domain = NA))(e1, e2)), groupMembers = list('Arith', 'Compare', 'Logic'), class = structure('groupGenericFunction', package = 'methods')))), FALSE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
@@ -178,7 +179,9 @@ public class TestBuiltin_unlist extends TestBase {
 
     @Test
     public void testunlist32() {
-        assertEval(Ignored.Unknown,
+        // FIXME Looks like FastR does not honor recursive=TRUE flag
+        // so the nested components are not unlisted
+        assertEval(Ignored.ImplementationError,
                         "argv <- list(structure(list(mean = c(0, 1), vcov = structure(c(1, 1, 1, 0), .Dim = c(2L, 2L))), .Names = c('mean', 'vcov'), class = c('relistable', 'list')), TRUE, TRUE); .Internal(unlist(argv[[1]], argv[[2]], argv[[3]]))");
     }
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unzip.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unzip.java
new file mode 100644
index 0000000000000000000000000000000000000000..39c11a7d5d17bbb39eab0dcc885938ce0257eca8
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_unzip.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package com.oracle.truffle.r.test.builtins;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestBuiltin_unzip extends TestBase {
+
+    @Test
+    public void testunzip() {
+        // writes out a small dummy zip file
+        assertEval("n <- tempfile(); writeBin(con=n,as.raw(c(0x50, 0x4b, 0x03, 0x04, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0xf3, 0x4a, 0xb7, 0xef, 0xdc, 0x83, 0x01, " +
+                        "0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x66, 0x6f, 0x6f, 0x31, 0x55, 0x54, 0x09, 0x00, 0x03, 0xa3, 0x47, 0x6f, 0x59, 0xad, " +
+                        "0x47, 0x6f, 0x59, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xf5, 0x01, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x31, 0x50, 0x4b, 0x01, 0x02, 0x1e, 0x03, " +
+                        "0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x6e, 0xf3, 0x4a, 0xb7, 0xef, 0xdc, 0x83, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x04, 0x00, 0x18, " +
+                        "0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa4, 0x81, 0x00, 0x00, 0x00, 0x00, 0x66, 0x6f, 0x6f, 0x31, 0x55, 0x54, 0x05, 0x00, 0x03, 0xa3, " +
+                        "0x47, 0x6f, 0x59, 0x75, 0x78, 0x0b, 0x00, 0x01, 0x04, 0xf5, 0x01, 0x00, 0x00, 0x04, 0x14, 0x00, 0x00, 0x00, 0x50, 0x4b, 0x05, 0x06, 0x00, 0x00, 0x00, " +
+                        "0x00, 0x01, 0x00, 0x01, 0x00, 0x4a, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00)))\n" +
+                        "length(unzip(n,list=T))\n" +
+                        "names(unzip(n,list=T))\n" +
+                        "unzip(n,list=T)[1:2]\n" + // leave out date (depends on time zone)
+                        "target <- tempdir()\n" +
+                        "v <- unzip(n,exdir=target, files=c('bar','baz'))\n" +
+                        "v\n" +
+                        "file.exists(paste0(target, '/foo1'))\n" +
+                        "v <- unzip(n,exdir=target)\n" +
+                        "length(v)\n" +
+                        "file.exists(v)\n" +
+                        "readBin(paste0(target, '/foo1'), what='raw', n=1000)");
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java
index 931015c40709bdd2df477a7f1e4382553d67ffda..c171773a5fce99766a9cde7e06727872a7d4e1a1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_vapply.java
@@ -53,4 +53,10 @@ public class TestBuiltin_vapply extends TestBase {
         assertEval("{ m <- matrix(c(1,2,3,4,5,6),2) ; apply(m,1,sum) }");
         assertEval("{ m <- matrix(c(1,2,3,4,5,6),2) ; apply(m,2,sum) }");
     }
+
+    @Test
+    public void testVapplyNames() {
+        assertEval("{ a <- vapply(list(a=1:20,b=1:20), function (x) x, FUN.VALUE=1:20); attributes(a); a[1:5] }");
+        assertEval("{ b <- list(a=structure(c(1:3), names=c('x','y')),b=structure(c(1:3), names=c('x2','y2','z2'))); a <- vapply(b, function (x) x, FUN.VALUE=1:3); attributes(a); a[1:5] }");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_within.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_within.java
index 82a6d25768376b06093a6f52ef9e017fa7acff5d..15b5e8bb78aa6e2b98deeee05ecaa4138c79fd6c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_within.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_within.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.
  */
@@ -20,7 +20,7 @@ public class TestBuiltin_within extends TestBase {
 
     @Test
     public void testwithin1() {
-        assertEval(Ignored.Unknown,
+        assertEval(Output.IgnoreErrorMessage,
                         "argv <- structure(list(data = structure(list(a = 1:5, b = 2:6,     c = 3:7), .Names = c('a', 'b', 'c'), row.names = c(NA, -5L),     class = 'data.frame')), .Names = 'data');" +
                                         "do.call('within', argv)");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels1.R
index 2fcc1bef21fae4cb7df0bfd0111301fe4b16714c..661999283c2731318dcfce65fb67929b851f3eb1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels1.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels1.R
@@ -1,6 +1,6 @@
 # test remote updated of atomic vector (must stay private)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1]<-7; .fastr.channel.send(ch, x)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels10.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels10.R
index 27a0504a89621d2cbb489e849b0720b8f3e7f263..23b243b0e8b37e85ddba337e749f625ecd473bd9 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels10.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels10.R
@@ -1,6 +1,6 @@
 # test remote updated of atomic vector with shareable attribute (must stay private)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1]<-7; .fastr.channel.send(ch, x)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels11.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels11.R
index 8a29a1e7f5579e8aa80ff3b55e2cde4377ea2d65..80dfee51e5f4b1e16218ba908a92e685802e5499 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels11.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels11.R
@@ -1,6 +1,6 @@
 # test remote updated of atomic vector with serializable attribute (must stay private)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1]<-7; .fastr.channel.send(ch, x)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels12.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels12.R
index ba44457240d723d5a5d6d5f7b2e1a6e124e0dfe1..5ce095baf4462848a66af07e184badce0acb0a0f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels12.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels12.R
@@ -1,6 +1,6 @@
 # test sending environment with global parent and assigning it remotely (should assign remotely but not locally)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); assign('y', 7, pos=env); .fastr.channel.send(ch, get('x', envir=env))"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels13.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels13.R
index f9bc278c9bb024c7c3092f18a629552db1cd4393..b5f14d911a9e7e173d60d93c9b4290c232560ef1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels13.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels13.R
@@ -1,6 +1,6 @@
 # test sending environment with a parent and global grandparent and assigning it remotely (should assign remotely but not locally)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); assign('y', 70, pos=env); assign('z', 420, pos=parent.env(env)); .fastr.channel.send(ch, c(get('w', envir=env), get('x', envir=parent.env(env))))"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels14.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels14.R
index 4444daa2129b29329ee7f1a8f9e255b43c6f9e17..8363515abb01e813f2852f551808cb90489d420c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels14.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels14.R
@@ -1,6 +1,6 @@
 # test passing a promise (environment must stay private)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[['y']]<-7; .fastr.channel.send(ch, x[['y']])"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels15.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels15.R
index 1f88fd32030ef77602e4ed531a1f25873bc646d3..15cb20a46ea19bd8589ab1ac3671c2b2f5179124 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels15.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels15.R
@@ -1,6 +1,6 @@
 # test remote updated of function with shareable attribute (attribute must stay private)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); f<-.fastr.channel.receive(ch); attr(f, 'foo') <- c('baz', 'bar'); .fastr.channel.send(ch, attr(f, 'foo'))"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels16.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels16.R
index 9c1470b87072bafaae37c77086b404a807d931f7..e1e99e50451e1918b63cae7c134f070d8cf6cac8 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels16.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels16.R
@@ -1,6 +1,6 @@
 # test recursion - sending environment containing vector with same environment attribute
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); .fastr.channel.send(ch, get('v', envir=env))"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R
index 68cc2c1f8467af241a592f689a0420c43fe56fc8..5c0208ce583c6d48db1f0a02d26805b60143a1f7 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels17.R
@@ -1,6 +1,6 @@
 # test passing a function (environment must stay private)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); f<-.fastr.channel.receive(ch); env <- environment(f); env[['x']] <- 7; .fastr.channel.send(ch, env[['x']])"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels2.R
index 3e4b27396ea2c358d0354d85dba0e9b678ac93fe..9137709cf3d21fc3733c9eeb35eedbfdecbfd9b6 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels2.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels2.R
@@ -1,6 +1,6 @@
 # test remote update of a list containing atomic vector (must stay private)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1][1]<-7; .fastr.channel.send(ch, x)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels3.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels3.R
index 67a6a97e1a45dfe92ae303748acb706a7a9e7ef1..dc91331f0d6a899534a968ec1fb657b13995d781 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels3.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels3.R
@@ -1,6 +1,6 @@
 # test sending a function
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); f<-.fastr.channel.receive(ch); x<-f(7); .fastr.channel.send(ch, x)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels4.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels4.R
index abf201a00e9e9dc670404e8fb31809e52d95237d..bab350ba97c21c437cd6e660a3bc6516e187a48b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels4.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels4.R
@@ -1,6 +1,6 @@
 # test sending global environment and assigning it remotely (should assign remotely but not locally)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); assign('y', 7, pos=env); .fastr.channel.send(ch, y)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels5.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels5.R
index 3a87fe57a2fe9bda3f32b44991fbf59dd488ba38..11c27c1916394c7a49c948e8ae58332ef408d509 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels5.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels5.R
@@ -1,6 +1,6 @@
 # test sending global environment as an attribute and assigning it remotely (should assign remotely but not locally)
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); msg<-.fastr.channel.receive(ch); env<-attr(msg, 'GLOBAL'); assign('y', 7, pos=env); .fastr.channel.send(ch, y)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels6.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels6.R
index 0f860c85d88aba9db43c304f768b4cc1f426a7d9..55a6ebda041d5e2f9945cb1074c7dcb18e35151f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels6.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels6.R
@@ -2,7 +2,7 @@
 # of another list) and assigning it remotely (should assign remotely but not locally)
 
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); msg<-.fastr.channel.receive(ch); env<-attr(attr(msg, 'LIST'), 'GLOBAL'); assign('y', 7, pos=env); .fastr.channel.send(ch, y)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels7.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels7.R
index 24addfd020342ed6cae99aa3439bacdf9741a120..3ee3110ef66c345f3ffdc0362da9281f894e779f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels7.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels7.R
@@ -1,6 +1,6 @@
 # test remote vector transfer for read - should use the same vector
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); y<-x[1]; z<-.fastr.identity(x); .fastr.channel.send(ch, z)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels8.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels8.R
index baab3f7bb24cda7b2b7d282e321544e27085d6ca..584ffb14e97aba181d7548aa75e3e19b91450030 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels8.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels8.R
@@ -1,6 +1,6 @@
 # test remote list transfer for read - should use the same vector elements
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); y<-x[[1]][1]; z<-.fastr.identity(x[[1]]); .fastr.channel.send(ch, z)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels9.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels9.R
index bdd1b853797f334beb40d55c57b5c459d11e7e73..0fe96e665c77dcfce446fac3b25eaa5d9d4e316c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels9.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/channels9.R
@@ -1,7 +1,7 @@
 # test remote list transfer for read - should use the same vector elements despite non-sharable content
 # also in the list
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch <- .fastr.channel.create(1L)
     code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); y<-x[[1]][1]; z<-c(.fastr.identity(x[[1]]), .fastr.identity(x[[2]])) ; .fastr.channel.send(ch, z)"
     cx <- .fastr.context.spawn(code)
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/contexts1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/contexts1.R
new file mode 100644
index 0000000000000000000000000000000000000000..7eab6d3f7b142fd630918a3dade2a540724988b0
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/contexts1.R
@@ -0,0 +1,17 @@
+if (any(R.version$engine == "FastR")) {
+    ch0 <- .fastr.channel.create(1L)
+    ch1 <- .fastr.channel.create(2L)
+    code0 <- "ch <- .fastr.channel.get(1L); .fastr.channel.send(ch, 7L)"
+    code1 <- "ch <- .fastr.channel.get(2L); .fastr.channel.send(ch, 42L)"
+    cx0 <- .fastr.context.spawn(code0)
+    cx1 <- .fastr.context.spawn(code1)
+    x<-.fastr.channel.receive(ch0)
+    y<-.fastr.channel.receive(ch1)
+    .fastr.context.join(cx0)
+    .fastr.context.join(cx1)
+    .fastr.channel.close(ch0)
+    .fastr.channel.close(ch1)
+    print(c(x,y))
+} else {
+    print(c(7L, 42L))
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R
index 5a96c5964206e95944672aad6f548b19288dc56f..515792055adfb6fde00143d199074ea9b87a0490 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing1.R
@@ -1,6 +1,6 @@
 # test remote update in global space - values should remain distinct
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch1 <- .fastr.channel.create(1L)
     code <- "ch2 <- .fastr.channel.get(1L); x <- 7; .fastr.channel.send(ch2, x)"
     x <- 42
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R
index 3c02fba5abc04a0d0c663d5c715828f69efde269..3131567747bce6f881064355d383da34e10971ac 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing2.R
@@ -1,6 +1,6 @@
 # test subsequent remote updates in global space - second time value should have been reset
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch1 <- .fastr.channel.create(1L)
     code <- "ch2 <- .fastr.channel.get(1L); x <- 7; .fastr.channel.send(ch2, x)"
     x <- 42
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R
index ec10067a70355cc808f00d8dbb2eec40c0b4633e..306402593a8b015ff1b18c90e1661507a791f3d1 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing3.R
@@ -1,6 +1,6 @@
 # test remote update in base space - values should remain distinct
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch1 <- .fastr.channel.create(1L)
 	# use an obscure name so it doesn't clash with other tests
     code <- "ch2 <- .fastr.channel.get(1L); assign('tmp59857', 7, env=baseenv()); .fastr.channel.send(ch2, get('tmp59857', env=baseenv(), inherits=F))"
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R
index 147da5fcf5939daa2e22f3a78696a799cbd6795a..4946b0e62a987aa9de288fe189411540187c8e4e 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/channels/R/sharing4.R
@@ -1,6 +1,6 @@
 # test access to global environment with multiple context instantiations varying context number
 
-if (length(grep("FastR", R.Version()$version.string)) == 1) {
+if (any(R.version$engine == "FastR")) {
     ch1 <- .fastr.channel.create(1L)
     code <- "ch2 <- .fastr.channel.get(1L); x <- .fastr.channel.receive(ch2); .fastr.channel.send(ch2, x)"
     x <- 7
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/AbstractMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/AbstractMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..0b838170299ca9e3e30c0d29566e5432d46939e2
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/AbstractMRTest.java
@@ -0,0 +1,230 @@
+/*
+ * 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.InteropException;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+public abstract class AbstractMRTest {
+
+    protected static PolyglotEngine engine;
+
+    @BeforeClass
+    public static void before() {
+        engine = PolyglotEngine.newBuilder().build();
+    }
+
+    @AfterClass
+    public static void after() {
+        engine.dispose();
+    }
+
+    /**
+     * Create TruffleObject-s to be rudimentary tested for IS_NULL, IS_BOXED/UNBOX, IS_EXECUTABLE,
+     * IS_POINTER, HAS_SIZE/GET_SIZE/KEYS behavior.
+     *
+     * @throws Exception
+     */
+    protected abstract TruffleObject[] createTruffleObjects() throws Exception;
+
+    /**
+     * Create a test TruffleObject having size == 0.
+     */
+    protected abstract TruffleObject createEmptyTruffleObject() throws Exception;
+
+    protected String[] getKeys() {
+        return null;
+    }
+
+    protected boolean isNull(@SuppressWarnings("unused") TruffleObject obj) {
+        return false;
+    }
+
+    protected boolean isExecutable(@SuppressWarnings("unused") TruffleObject obj) {
+        return false;
+    }
+
+    protected boolean isPointer(@SuppressWarnings("unused") TruffleObject obj) {
+        return false;
+    }
+
+    protected boolean isBoxed(@SuppressWarnings("unused") TruffleObject obj) {
+        return false;
+    }
+
+    protected boolean hasSize(@SuppressWarnings("unused") TruffleObject obj) {
+        return false;
+    }
+
+    protected int getSize(@SuppressWarnings("unused") TruffleObject obj) {
+        throw new UnsupportedOperationException("override if hasSize returns true");
+    }
+
+    protected Object getUnboxed(@SuppressWarnings("unused") TruffleObject obj) {
+        throw new UnsupportedOperationException("override if isBoxed returns true");
+    }
+
+    @Test
+    public void testIsNull() throws Exception {
+        for (TruffleObject obj : createTruffleObjects()) {
+            assertEquals(isNull(obj), ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), obj));
+        }
+    }
+
+    @Test
+    public void testIsExecutable() throws Exception {
+        for (TruffleObject obj : createTruffleObjects()) {
+            assertEquals(isExecutable(obj), ForeignAccess.sendIsExecutable(Message.IS_EXECUTABLE.createNode(), obj));
+        }
+    }
+
+    @Test
+    public void testIsPointer() throws Exception {
+        for (TruffleObject obj : createTruffleObjects()) {
+            assertEquals(isPointer(obj), ForeignAccess.sendIsPointer(Message.IS_POINTER.createNode(), obj));
+        }
+    }
+
+    @Test
+    public void testNativePointer() throws Exception {
+        for (TruffleObject obj : createTruffleObjects()) {
+            try {
+                assertTrue(ForeignAccess.sendToNative(Message.TO_NATIVE.createNode(), obj) instanceof NativePointer);
+            } catch (UnsupportedMessageException unsupportedMessageException) {
+            }
+        }
+    }
+
+    @Test
+    public void testSize() throws Exception {
+        for (TruffleObject obj : createTruffleObjects()) {
+            boolean hasSize = ForeignAccess.sendHasSize(Message.HAS_SIZE.createNode(), obj);
+            assertEquals("" + obj.getClass() + " " + obj, hasSize(obj), hasSize);
+            if (hasSize) {
+                assertEquals(getSize(obj), ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), obj));
+            } else {
+                assertInteropException(() -> ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), obj), UnsupportedMessageException.class);
+            }
+        }
+    }
+
+    @Test
+    public void testBoxed() throws Exception {
+        for (TruffleObject obj : createTruffleObjects()) {
+            boolean isBoxed = ForeignAccess.sendIsBoxed(Message.IS_BOXED.createNode(), obj);
+            assertEquals(isBoxed(obj), isBoxed);
+            if (isBoxed) {
+                assertEquals(getUnboxed(obj), ForeignAccess.sendUnbox(Message.UNBOX.createNode(), obj));
+            }
+            // else {
+            // assertInteropException(() -> ForeignAccess.sendUnbox(Message.UNBOX.createNode(),
+            // obj), UnsupportedMessageException.class);
+            // }
+        }
+    }
+
+    @Test
+    public void testKeys() throws Exception {
+        String[] keys = getKeys();
+        if (keys == null) {
+            return;
+        }
+        for (TruffleObject obj : createTruffleObjects()) {
+            TruffleObject keysObj = ForeignAccess.sendKeys(Message.KEYS.createNode(), obj);
+            int size = (int) ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), keysObj);
+            assertEquals(keys.length, size);
+
+            Set<Object> set = new HashSet<>();
+            for (int i = 0; i < size; i++) {
+                set.add(ForeignAccess.sendRead(Message.READ.createNode(), keysObj, i));
+            }
+            for (String key : keys) {
+                assertTrue(set.contains(key));
+            }
+        }
+    }
+
+    @Test
+    public void testEmpty() throws Exception {
+
+        TruffleObject obj = createEmptyTruffleObject();
+        if (obj != null) {
+            if (hasSize(obj)) {
+                int size = (int) ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), obj);
+                assertEquals(0, size);
+            }
+
+            TruffleObject keys = null;
+            try {
+                keys = ForeignAccess.sendKeys(Message.KEYS.createNode(), obj);
+            } catch (UnsupportedMessageException ex) {
+            }
+            if (keys != null) {
+                boolean keysHasSize = ForeignAccess.sendHasSize(Message.HAS_SIZE.createNode(), keys);
+                if (keysHasSize) {
+                    int keysSize = (int) ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), keys);
+                    assertEquals(0, keysSize);
+                }
+            }
+        }
+    }
+
+    protected interface ForeignCall {
+        void call() throws Exception;
+    }
+
+    protected void assertInteropException(ForeignCall c, Class<? extends InteropException> expectedClazz) {
+        boolean ie = false;
+        try {
+            c.call();
+        } catch (InteropException ex) {
+            if (expectedClazz != null && ex.getClass() != expectedClazz) {
+                Assert.fail(expectedClazz + " was expected but got instead: " + ex);
+            }
+            ie = true;
+        } catch (Exception ex) {
+            if (expectedClazz != null && ex.getClass() != expectedClazz) {
+                Assert.fail(expectedClazz + " was expected but got instead: " + ex);
+            } else {
+                Assert.fail("InteropException was expected but got insteat: " + ex);
+            }
+        }
+        assertTrue(ie);
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ActiveBindingMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ActiveBindingMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..fbeaa5c52e829089c11176913001d80cf5465384
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ActiveBindingMRTest.java
@@ -0,0 +1,56 @@
+/*
+ * 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.TruffleObject;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
+
+public class ActiveBindingMRTest extends AbstractMRTest {
+
+    @Override
+    protected boolean isBoxed(TruffleObject obj) {
+        return true;
+    }
+
+    @Override
+    protected Object getUnboxed(TruffleObject obj) {
+        return ((ActiveBinding) obj).readValue();
+    }
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        Source src = Source.newBuilder("f=function() {}").mimeType("text/x-r").name("test.R").build();
+        PolyglotEngine.Value result = engine.eval(src);
+        RFunction fn = result.as(RFunction.class);
+        return new TruffleObject[]{new ActiveBinding(RType.Any, fn)};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ListMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ListMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d9c4aaa65ebeb5006ccd3d64187b81b4788ae5f8
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/ListMRTest.java
@@ -0,0 +1,186 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.KeyInfo;
+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.interop.java.JavaInterop;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
+import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
+import com.oracle.truffle.r.runtime.data.RPairList;
+import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
+
+public class ListMRTest extends AbstractMRTest {
+
+    private String testValues = "i=1L, d=2.1, b=TRUE, fn=function() {}, n=NULL, 4";
+
+    @Override
+    @Test
+    public void testNativePointer() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
+        assertTrue(ForeignAccess.sendToNative(Message.TO_NATIVE.createNode(), create("list", testValues)) instanceof NativePointer);
+        assertTrue(ForeignAccess.sendToNative(Message.TO_NATIVE.createNode(), create("pairlist", testValues)) instanceof NativePointer);
+    }
+
+    @Test
+    public void testKeysReadWrite() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
+        testKeysReadWrite("list");
+        testKeysReadWrite("pairlist");
+    }
+
+    private void testKeysReadWrite(String createFun) throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
+
+        RAbstractContainer l = create(createFun, testValues);
+
+        assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, "i"));
+        assertEquals(2.1, ForeignAccess.sendRead(Message.READ.createNode(), l, "d"));
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), l, "b"));
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), l, "n") instanceof RNull);
+
+        assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, 0));
+        assertEquals(2.1, ForeignAccess.sendRead(Message.READ.createNode(), l, 1));
+        assertEquals(4d, ForeignAccess.sendRead(Message.READ.createNode(), l, 5d));
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), l, 2));
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), l, 4) instanceof RNull);
+
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, -1), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, 0f), UnknownIdentifierException.class);
+
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, "nnnoooonnne"), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), l, 100), UnknownIdentifierException.class);
+
+        TruffleObject obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "d", 123.1);
+        assertEquals(123.1, ForeignAccess.sendRead(Message.READ.createNode(), obj, "d"));
+
+        obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 2, false);
+        RAbstractContainer returnedList = JavaInterop.asJavaObject(RAbstractContainer.class, obj);
+        assertEquals((byte) 0, returnedList.getDataAtAsObject(2));
+        assertEquals(false, ForeignAccess.sendRead(Message.READ.createNode(), obj, "b"));
+
+        obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "newnew", "nneeww");
+        assertEquals("nneeww", ForeignAccess.sendRead(Message.READ.createNode(), obj, "newnew"));
+
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 0f, false), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), l, 0d, false), UnknownIdentifierException.class);
+    }
+
+    @Test
+    public void testKeysInfo() {
+        testKeysInfo("list");
+        testKeysInfo("pairlist");
+    }
+
+    public void testKeysInfo(String createFun) {
+
+        RAbstractContainer l = create(createFun, testValues);
+
+        int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "nnoonnee");
+        assertFalse(KeyInfo.isExisting(info));
+        assertFalse(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "d");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "fn");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, -1);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, l.getLength());
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 1f);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 0);
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, 1d);
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+    }
+
+    private static RAbstractContainer create(String createFun, String values) {
+        Source src = Source.newBuilder(createFun + "(" + values + ")").mimeType("text/x-r").name("test.R").build();
+        PolyglotEngine.Value result = engine.eval(src);
+        return result.as(RAbstractContainer.class);
+    }
+
+    @Override
+    protected String[] getKeys() {
+        return new String[]{"i", "d", "b", "fn", "n", ""};
+    }
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{create("list", testValues), create("pairlist", testValues)};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        // cant have an emtpy pair list
+        return create("list", "");
+    }
+
+    @Override
+    protected boolean hasSize(TruffleObject arg0) {
+        return true;
+    }
+
+    @Override
+    protected int getSize(TruffleObject obj) {
+        return obj instanceof RList ? ((RList) obj).getLength() : ((RPairList) obj).getLength();
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RArgsValuesAndNamesMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RArgsValuesAndNamesMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..25e3ce0587e89f50085131b797e42aa94f99992f
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RArgsValuesAndNamesMRTest.java
@@ -0,0 +1,161 @@
+/*
+ * 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.KeyInfo;
+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.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.ArgumentsSignature;
+import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
+import com.oracle.truffle.r.runtime.data.RFunction;
+import com.oracle.truffle.r.runtime.data.RNull;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import org.junit.Test;
+
+public class RArgsValuesAndNamesMRTest extends AbstractMRTest {
+
+    @Test
+    public void testReadWriteIdx() throws Exception {
+        TruffleObject args = createTruffleObjects()[0];
+
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), args, 1f), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), args, 1d), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), args, -1), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), args, 100), UnknownIdentifierException.class);
+
+        assertEquals("abc", ForeignAccess.sendRead(Message.READ.createNode(), args, 0));
+        assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), args, 1));
+        assertEquals(1.1, ForeignAccess.sendRead(Message.READ.createNode(), args, 2));
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), args, 3));
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), args, 4) instanceof RFunction);
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), args, 5) instanceof RNull);
+
+        TruffleObject emptyargs = RArgsValuesAndNames.EMPTY;
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), emptyargs, 0), UnknownIdentifierException.class);
+
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), args, 0, 321), UnsupportedMessageException.class);
+    }
+
+    @Test
+    public void testReadWriteName() throws Exception {
+        TruffleObject args = createTruffleObjects()[0];
+
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), args, "nnnnooooonnnneee"), UnknownIdentifierException.class);
+
+        assertEquals("abc", ForeignAccess.sendRead(Message.READ.createNode(), args, "s"));
+        assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), args, "i"));
+        assertEquals(1.1, ForeignAccess.sendRead(Message.READ.createNode(), args, "d"));
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), args, "b"));
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), args, "fn") instanceof RFunction);
+        assertTrue(ForeignAccess.sendRead(Message.READ.createNode(), args, "n") instanceof RNull);
+
+        TruffleObject emptyargs = RArgsValuesAndNames.EMPTY;
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), emptyargs, "s"), UnknownIdentifierException.class);
+
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), args, "s", "aaa"), UnsupportedMessageException.class);
+    }
+
+    @Test
+    public void testKeysInfo() throws Exception {
+        TruffleObject e = createTruffleObjects()[0];
+        int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "nnoonnee");
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, 1f);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, 0);
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "s");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "b");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "fn");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "n");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+    }
+
+    private String[] names = {"s", "i", "d", "b", "fn", "n"};
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        Source src = Source.newBuilder("f=function() {}").mimeType("text/x-r").name("test.R").build();
+        PolyglotEngine.Value result = engine.eval(src);
+        RFunction fn = result.as(RFunction.class);
+        Object[] values = {"abc", 123, 1.1, RRuntime.asLogical(true), fn, RNull.instance};
+        return new TruffleObject[]{new RArgsValuesAndNames(values, ArgumentsSignature.get(names))};
+    }
+
+    @Override
+    protected String[] getKeys() {
+        return names;
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return RArgsValuesAndNames.EMPTY;
+    }
+
+    @Override
+    protected boolean hasSize(TruffleObject obj) {
+        return true;
+    }
+
+    @Override
+    protected int getSize(TruffleObject obj) {
+        return ((RArgsValuesAndNames) obj).getLength();
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RDoubleMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RDoubleMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..887f384fbb2b4b1c578934ca3717de357a6bf08f
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RDoubleMRTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.TruffleObject;
+import com.oracle.truffle.r.runtime.data.RDouble;
+
+public class RDoubleMRTest extends AbstractMRTest {
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{RDouble.valueOf(1.1)};
+    }
+
+    @Override
+    protected boolean isBoxed(TruffleObject obj) {
+        return true;
+    }
+
+    @Override
+    protected Object getUnboxed(TruffleObject obj) {
+        return ((RDouble) obj).getValue();
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REmptyMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REmptyMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1ec6184661511c474fd2d3944a65e3e2254971c3
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REmptyMRTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.TruffleObject;
+import com.oracle.truffle.r.runtime.data.REmpty;
+
+public class REmptyMRTest extends AbstractMRTest {
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{REmpty.instance};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REnvironmentMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REnvironmentMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..60ef430454923816291d01c501fe5e5bfed195d8
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REnvironmentMRTest.java
@@ -0,0 +1,150 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.KeyInfo;
+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.java.JavaInterop;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+
+public class REnvironmentMRTest extends AbstractMRTest {
+
+    @Test
+    public void testReadWrite() throws Exception {
+        REnvironment e = (REnvironment) createTruffleObjects()[0];
+
+        assertEquals("aaa", ForeignAccess.sendRead(Message.READ.createNode(), e, "s"));
+        assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), e, "i"));
+        assertEquals(123.1, ForeignAccess.sendRead(Message.READ.createNode(), e, "d"));
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), e, "b"));
+
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), e, "nnnoooonnne"), UnknownIdentifierException.class);
+
+        TruffleObject obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), e, "s", "abc");
+        Object value = ForeignAccess.sendRead(Message.READ.createNode(), obj, "s");
+        assertEquals("abc", value);
+
+        obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), e, "b", false);
+        REnvironment env = JavaInterop.asJavaObject(REnvironment.class, obj);
+        assertEquals((byte) 0, env.get("b"));
+        value = ForeignAccess.sendRead(Message.READ.createNode(), obj, "b");
+        assertEquals(false, value);
+
+        obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), e, "i", (short) 1234);
+        value = ForeignAccess.sendRead(Message.READ.createNode(), obj, "i");
+        assertTrue(value instanceof Integer);
+        assertEquals(1234, value);
+
+        obj = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), e, "newnew", "nneeww");
+        value = ForeignAccess.sendRead(Message.READ.createNode(), obj, "newnew");
+        assertEquals("nneeww", value);
+
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), e, "l", 667), UnsupportedMessageException.class);
+
+        e.lock(true);
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), e, "newnew2", "nneeww"), UnsupportedMessageException.class);
+        e.lock(false);
+
+        // can't read/write via index
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), e, 0), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), e, 1f), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), e, 1, 321), UnknownIdentifierException.class);
+    }
+
+    @Test
+    public void testKeysInfo() throws Exception {
+        TruffleObject e = createTruffleObjects()[0];
+        int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "nnoonnee");
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, 0);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, 1f);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "s");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "b");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "fn");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "n");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), e, "l");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+    }
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        Source src = Source.newBuilder("e <- new.env(); e$s <- 'aaa'; e$i <- 123L; e$d <- 123.1; e$b <- TRUE; e$fn <- function() {}; e$n <- NULL; e$l <- 666; lockBinding('l', e); e").mimeType(
+                        "text/x-r").name("test.R").build();
+        return new TruffleObject[]{engine.eval(src).as(REnvironment.class)};
+    }
+
+    @Override
+    protected String[] getKeys() {
+        return new String[]{"s", "i", "d", "b", "fn", "n", "l"};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        Source src = Source.newBuilder("new.env()").mimeType("text/x-r").name("test.R").build();
+        return engine.eval(src).as(REnvironment.class);
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RFunctionMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RFunctionMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1397ae9de207297a1faf9def422db37185be7b54
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RFunctionMRTest.java
@@ -0,0 +1,90 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.oracle.truffle.api.interop.ArityException;
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.Message;
+import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.data.RFunction;
+
+public class RFunctionMRTest extends AbstractMRTest {
+
+    @Test
+    public void testExecute() throws UnsupportedTypeException, ArityException, UnsupportedMessageException {
+        RFunction f = create("function() {}");
+        assertTrue(ForeignAccess.sendIsExecutable(Message.IS_EXECUTABLE.createNode(), f));
+
+        TruffleObject result = (TruffleObject) ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f);
+        assertTrue(ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), result));
+
+        f = create("function() {1L}");
+        assertEquals(1, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
+
+        f = create("function() {1}");
+        assertEquals(1.0, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
+
+        f = create("function() {TRUE}");
+        assertEquals(true, ForeignAccess.sendExecute(Message.createExecute(0).createNode(), f));
+
+        f = create("function(a) {a}");
+        assertEquals("abc", ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, "abc"));
+
+        f = create("function(a) { is.logical(a) }");
+        assertEquals(true, ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, true));
+
+        f = create("function(a) { as.external.short(a) }");
+        assertTrue(ForeignAccess.sendExecute(Message.createExecute(1).createNode(), f, 123) instanceof Short);
+
+    }
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() {
+        return new TruffleObject[]{create("function() {}")};
+    }
+
+    private static RFunction create(String fun) {
+        Source src = Source.newBuilder(fun).mimeType("text/x-r").name("test.R").build();
+        PolyglotEngine.Value result = engine.eval(src);
+        return result.as(RFunction.class);
+    }
+
+    @Override
+    protected boolean isExecutable(TruffleObject obj) {
+        return true;
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RIntegerMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RIntegerMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..b44b1e1505ac661845551f16366558ff23957003
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RIntegerMRTest.java
@@ -0,0 +1,49 @@
+/*
+ * 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.TruffleObject;
+import com.oracle.truffle.r.runtime.data.RInteger;
+
+public class RIntegerMRTest extends AbstractMRTest {
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{RInteger.valueOf(123)};
+    }
+
+    @Override
+    protected boolean isBoxed(TruffleObject obj) {
+        return true;
+    }
+
+    @Override
+    protected Object getUnboxed(TruffleObject obj) {
+        return ((RInteger) obj).getValue();
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+}
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
index e216b0d234ace50a4797da899c09b5a9b0c77035..fbbcd375cc9765f0ccca69862527eacc5a4cc9d0 100644
--- 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
@@ -22,47 +22,64 @@
  */
 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 {
+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.r.runtime.data.RInteropScalar;
+import org.junit.Assert;
+
+public class RInteropScalarMRTest extends AbstractMRTest {
 
     @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);
+    public void testRInteroptScalar() throws Exception {
+        for (TruffleObject obj : createTruffleObjects()) {
+            RInteropScalar is = (RInteropScalar) obj;
+            testRIS(obj, is.getJavaType());
+        }
     }
 
-    private void testRIS(String toInteropScalarBuiltin, String value, Class<?> unboxedType) throws UnsupportedMessageException {
-        TruffleObject l = createRInteroptScalarTO(toInteropScalarBuiltin, value);
+    private static void testRIS(TruffleObject obj, Class<?> unboxedType) throws Exception {
+        assertFalse(ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), obj));
+        assertFalse(ForeignAccess.sendHasSize(Message.HAS_SIZE.createNode(), obj));
 
-        assertFalse(ForeignAccess.sendIsNull(Message.IS_NULL.createNode(), l));
-        assertFalse(ForeignAccess.sendHasSize(Message.HAS_SIZE.createNode(), l));
+        assertTrue(ForeignAccess.sendIsBoxed(Message.IS_BOXED.createNode(), obj));
+        Object ub = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), obj);
+        assertEquals(unboxedType, ub.getClass().getField("TYPE").get(null));
+    }
 
-        assertTrue(ForeignAccess.sendIsBoxed(Message.IS_BOXED.createNode(), l));
-        Object ub = ForeignAccess.sendUnbox(Message.UNBOX.createNode(), l);
-        assertEquals(unboxedType, ub.getClass());
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{RInteropScalar.RInteropByte.valueOf(Byte.MAX_VALUE),
+                        RInteropScalar.RInteropChar.valueOf('a'),
+                        RInteropScalar.RInteropFloat.valueOf(Float.MAX_VALUE),
+                        RInteropScalar.RInteropLong.valueOf(Long.MAX_VALUE),
+                        RInteropScalar.RInteropShort.valueOf(Short.MAX_VALUE)};
     }
 
-    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);
+    @Override
+    protected boolean isBoxed(TruffleObject arg0) {
+        return true;
     }
 
+    @Override
+    protected Object getUnboxed(TruffleObject obj) {
+        RInteropScalar is = (RInteropScalar) obj;
+        try {
+            return is.getClass().getDeclaredMethod("getValue").invoke(is);
+        } catch (Exception ex) {
+            Assert.fail("can't read interop scalar value " + ex);
+        }
+        return null;
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RLanguageMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RLanguageMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..df5d8d6aca9215edb9f4697f71ebd74e37fd753c
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RLanguageMRTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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 static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.KeyInfo;
+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.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.data.RLanguage;
+
+public class RLanguageMRTest extends AbstractMRTest {
+
+    @Test
+    public void testKeysInfo() throws Exception {
+        RLanguage rl = (RLanguage) createTruffleObjects()[0];
+        int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, "nnoonnee");
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, 1f);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, rl.getLength());
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, 0);
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, 1);
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), rl, 2);
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+    }
+
+    @Test
+    public void testReadWrite() throws Exception {
+        RLanguage rl = (RLanguage) createTruffleObjects()[0];
+
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), rl, "nnnoooonnne"), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), rl, rl.getLength()), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), rl, 0d), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), rl, 0f), UnknownIdentifierException.class);
+
+        // TODO add some meaningfull read tests
+        Assert.assertNotNull(ForeignAccess.sendRead(Message.READ.createNode(), rl, 0));
+
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), rl, "aaa", "abc"), UnsupportedMessageException.class);
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), rl, 0, "abc"), UnsupportedMessageException.class);
+
+    }
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() {
+        // TODO any simpler way to create a RLanguage ?
+        String srcTxt = "ne <- new.env(); delayedAssign('x', 1 + 2, assign.env = ne); substitute(x, ne)";
+        Source src = Source.newBuilder(srcTxt).mimeType("text/x-r").name("test.R").build();
+        PolyglotEngine.Value result = engine.eval(src);
+        return new TruffleObject[]{result.as(RLanguage.class)};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+
+    @Override
+    protected boolean hasSize(TruffleObject obj) {
+        return true;
+    }
+
+    @Override
+    protected int getSize(TruffleObject obj) {
+        return ((RLanguage) obj).getLength();
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java
deleted file mode 100644
index a1af763c7576321ec53e89030ecfa14f34125a5b..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RListMRTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.KeyInfo;
-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 org.junit.Test;
-
-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;
-
-public class RListMRTest {
-
-    @Test
-    public void testKeysReadWrite() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
-        TruffleObject l = createRListTruffleObject("n1=1L, n2=2L, 3, 4");
-
-        TruffleObject keys = ForeignAccess.sendKeys(Message.KEYS.createNode(), l);
-        assertEquals("n1", ForeignAccess.sendRead(Message.READ.createNode(), keys, 0));
-        assertEquals("n2", ForeignAccess.sendRead(Message.READ.createNode(), keys, 1));
-        assertEquals("", ForeignAccess.sendRead(Message.READ.createNode(), keys, 2));
-        assertEquals("", ForeignAccess.sendRead(Message.READ.createNode(), keys, 3));
-
-        assertEquals(4, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), keys));
-        assertEquals(1, ForeignAccess.sendRead(Message.READ.createNode(), l, "n1"));
-        assertEquals(2, ForeignAccess.sendRead(Message.READ.createNode(), l, "n2"));
-
-        // TODO fails - should this return NULL as in l[""] or 3 as in l$""
-        // ElementAccessMode.FIELD_SUBSCRIPT vs .SUBSCRIPT doesn't seem to have any effect
-        // assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), l, ""));
-
-        // TODO - more tests for NA, ... ?
-
-        l = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), l, "n2", 123);
-        assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), l, "n2"));
-    }
-
-    @Test
-    public void testKeysInfo() throws UnsupportedMessageException, UnknownIdentifierException, UnsupportedTypeException {
-        TruffleObject l = createRListTruffleObject("n1=1, n2=2");
-        int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "nnoonnee");
-        assertFalse(KeyInfo.isExisting(info));
-        assertFalse(KeyInfo.isReadable(info));
-        assertFalse(KeyInfo.isWritable(info));
-        assertFalse(KeyInfo.isInvocable(info));
-        assertFalse(KeyInfo.isInternal(info));
-
-        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "n2");
-        assertTrue(KeyInfo.isExisting(info));
-        assertTrue(KeyInfo.isReadable(info));
-        assertTrue(KeyInfo.isWritable(info));
-        assertFalse(KeyInfo.isInvocable(info));
-        assertFalse(KeyInfo.isInternal(info));
-
-        l = createRListTruffleObject("f=function() {}");
-        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), l, "f");
-        assertTrue(KeyInfo.isExisting(info));
-        assertTrue(KeyInfo.isReadable(info));
-        assertTrue(KeyInfo.isWritable(info));
-        assertTrue(KeyInfo.isInvocable(info));
-        assertFalse(KeyInfo.isInternal(info));
-    }
-
-    private TruffleObject createRListTruffleObject(String values) {
-        PolyglotEngine engine = PolyglotEngine.newBuilder().build();
-        Source src = Source.newBuilder("list(" + values + ")").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/interop/RMissingMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RMissingMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c0a39b78a89784dc48f690c0547d928f831a693f
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RMissingMRTest.java
@@ -0,0 +1,39 @@
+/*
+ * 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.TruffleObject;
+import com.oracle.truffle.r.runtime.data.RMissing;
+
+public class RMissingMRTest extends AbstractMRTest {
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{RMissing.instance};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RNullMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RNullMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c9c943090466aa6330051dcad113c8b61c947d45
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RNullMRTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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.TruffleObject;
+
+import com.oracle.truffle.r.runtime.data.RNull;
+
+public class RNullMRTest extends AbstractMRTest {
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{RNull.instance};
+    }
+
+    @Override
+    protected boolean isNull(TruffleObject obj) {
+        return true;
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RS4ObjectMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RS4ObjectMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..70b314fae9714478492a7001768a2f1b9224b3f1
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RS4ObjectMRTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.KeyInfo;
+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.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.runtime.data.RS4Object;
+
+public class RS4ObjectMRTest extends AbstractMRTest {
+
+    @Test
+    public void testKeysInfo() throws Exception {
+        TruffleObject s4 = createTruffleObjects()[0];
+        int info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), s4, "nnoonnee");
+        assertFalse(KeyInfo.isExisting(info));
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), s4, 0);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), s4, 1f);
+        assertFalse(KeyInfo.isExisting(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), s4, "s");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), s4, "b");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), s4, "fn");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertTrue(KeyInfo.isWritable(info));
+        assertTrue(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+
+        info = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), s4, "class");
+        assertTrue(KeyInfo.isExisting(info));
+        assertTrue(KeyInfo.isReadable(info));
+        assertFalse(KeyInfo.isWritable(info));
+        assertFalse(KeyInfo.isInvocable(info));
+        assertFalse(KeyInfo.isInternal(info));
+    }
+
+    @Test
+    public void testReadWrite() throws Exception {
+        TruffleObject s4 = createTruffleObjects()[0];
+
+        assertEquals("aaa", ForeignAccess.sendRead(Message.READ.createNode(), s4, "s"));
+        assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), s4, "i"));
+        assertEquals(1.1, ForeignAccess.sendRead(Message.READ.createNode(), s4, "d"));
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), s4, "b"));
+
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), s4, "nnnoooonnne"), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), s4, 0), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), s4, 1d), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), s4, 1f), UnknownIdentifierException.class);
+
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), s4, "class", "cantchangeclass"), UnsupportedMessageException.class);
+        // TODO this should fail !!!
+        // assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), s4, "i",
+        // "cant write string into int slot"), UnsupportedMessageException.class);
+
+        ForeignAccess.sendWrite(Message.WRITE.createNode(), s4, "s", "abc");
+        Object value = ForeignAccess.sendRead(Message.READ.createNode(), s4, "s");
+        assertEquals("abc", value);
+
+        ForeignAccess.sendWrite(Message.WRITE.createNode(), s4, "b", false);
+        value = ForeignAccess.sendRead(Message.READ.createNode(), s4, "b");
+        assertEquals(false, value);
+
+        ForeignAccess.sendWrite(Message.WRITE.createNode(), s4, "i", (short) 1234);
+        value = ForeignAccess.sendRead(Message.READ.createNode(), s4, "i");
+        assertTrue(value instanceof Integer);
+        assertEquals(1234, value);
+
+    }
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() {
+        String srcTxt = "setClass('test', representation(s = 'character', d = 'numeric', i = 'integer', b = 'logical', fn = 'function'));" +
+                        "new('test', s = 'aaa', d = 1.1, i=123L, b = TRUE, fn = function() {})";
+        Source src = Source.newBuilder(srcTxt).mimeType("text/x-r").name("test.R").build();
+        PolyglotEngine.Value result = engine.eval(src);
+        RS4Object s4 = result.as(RS4Object.class);
+        return new TruffleObject[]{s4};
+    }
+
+    @Override
+    protected String[] getKeys() {
+        return new String[]{"s", "d", "i", "b", "fn", "class"};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RUboundValueMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RUboundValueMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..baa61ec385903879fc2583e334d6a9e19c63eeeb
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/RUboundValueMRTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.TruffleObject;
+import com.oracle.truffle.r.runtime.data.RUnboundValue;
+
+public class RUboundValueMRTest extends AbstractMRTest {
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{RUnboundValue.instance};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return null;
+    }
+
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/VectorMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/VectorMRTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd2e5d803965878979f4e5a17da958b69f6c7feb
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/VectorMRTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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 static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.KeyInfo;
+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.java.JavaInterop;
+import com.oracle.truffle.api.source.Source;
+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 class VectorMRTest extends AbstractMRTest {
+
+    @Test
+    public void testReadWrite() throws Exception {
+        final TruffleObject vi = create("1L:10L");
+        assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), vi, 2));
+        assertEquals(3, ForeignAccess.sendRead(Message.READ.createNode(), vi, 2L));
+
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), vi, "a"), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), vi, 100), UnknownIdentifierException.class);
+        assertInteropException(() -> ForeignAccess.sendWrite(Message.WRITE.createNode(), vi, "s", "abc"), UnknownIdentifierException.class);
+
+        TruffleObject vd = create("1.1:10.1");
+        assertEquals(1.1, ForeignAccess.sendRead(Message.READ.createNode(), vd, 0));
+
+        TruffleObject vb = create("c(TRUE, FALSE, TRUE)");
+        assertEquals(true, ForeignAccess.sendRead(Message.READ.createNode(), vb, 0));
+
+        TruffleObject nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), vi, 0, 123);
+        RAbstractIntVector returnedVec = JavaInterop.asJavaObject(RAbstractIntVector.class, nvi);
+        assertEquals(123, returnedVec.getDataAt(0));
+        assertEquals(123, ForeignAccess.sendRead(Message.READ.createNode(), nvi, 0));
+
+        assertEquals(10, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), nvi));
+        nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), nvi, 100, 321);
+        assertEquals(101, ForeignAccess.sendGetSize(Message.GET_SIZE.createNode(), nvi));
+        assertEquals(321, ForeignAccess.sendRead(Message.READ.createNode(), nvi, 100));
+
+        nvi = (TruffleObject) ForeignAccess.sendWrite(Message.WRITE.createNode(), nvi, 0, "abc");
+        RAbstractVector vec = JavaInterop.asJavaObject(RAbstractVector.class, nvi);
+        assertTrue(vec instanceof RAbstractStringVector);
+        assertEquals("abc", ForeignAccess.sendRead(Message.READ.createNode(), nvi, 0));
+    }
+
+    @Test
+    public void testKeyInfo() throws Exception {
+        TruffleObject v = create("c(TRUE, FALSE, TRUE)");
+        assertInteropException(() -> ForeignAccess.sendKeys(Message.KEYS.createNode(), v), UnsupportedMessageException.class);
+
+        int keyInfo = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), v, 0);
+        assertTrue(KeyInfo.isExisting(keyInfo));
+        assertTrue(KeyInfo.isReadable(keyInfo));
+        assertTrue(KeyInfo.isWritable(keyInfo));
+        assertFalse(KeyInfo.isInvocable(keyInfo));
+        assertFalse(KeyInfo.isInternal(keyInfo));
+
+        keyInfo = ForeignAccess.sendKeyInfo(Message.KEY_INFO.createNode(), v, 100);
+        assertFalse(KeyInfo.isExisting(keyInfo));
+    }
+
+    @Override
+    protected TruffleObject[] createTruffleObjects() throws Exception {
+        return new TruffleObject[]{create("1:10"), create("as.numeric()")};
+    }
+
+    @Override
+    protected TruffleObject createEmptyTruffleObject() throws Exception {
+        return create("as.numeric()");
+    }
+
+    @Override
+    protected boolean isBoxed(TruffleObject obj) {
+        return ((RAbstractVector) obj).getLength() == 1;
+    }
+
+    @Override
+    protected boolean hasSize(TruffleObject obj) {
+        return true;
+    }
+
+    @Override
+    protected int getSize(TruffleObject obj) {
+        return ((RAbstractVector) obj).getLength();
+    }
+
+    private static TruffleObject create(String createTxt) throws Exception {
+        Source src = Source.newBuilder(createTxt).mimeType("text/x-r").name("test.R").build();
+        return engine.eval(src).as(RAbstractVector.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 015fa4ff405ce362e1a4378cbb4b82877f07e0e0..eaabb32efebf6e106e3d3b75a0b94911d2edf486 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
@@ -22,44 +22,42 @@
  */
 package com.oracle.truffle.r.test.engine.shell;
 
-import com.oracle.truffle.api.vm.PolyglotEngine;
-import com.oracle.truffle.r.engine.shell.JLineConsoleCompleter;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
-import com.oracle.truffle.r.runtime.context.RContext;
-import java.io.File;
-import org.junit.Test;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
+import java.io.File;
 import java.util.LinkedList;
+
+import org.graalvm.polyglot.Context;
 import org.junit.After;
 import org.junit.Assert;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
 import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.oracle.truffle.r.launcher.JLineConsoleCompleter;
 
 public class TestJLineConsoleCompleter {
 
-    private PolyglotEngine engine;
-    private ConsoleHandler consoleHandler;
+    private Context context;
     private JLineConsoleCompleter consoleCompleter;
 
     @Before
     public void before() {
-        consoleHandler = new DummyConsoleHandler();
-        consoleCompleter = new JLineConsoleCompleter(consoleHandler);
         JLineConsoleCompleter.testingMode();
-        ContextInfo info = ContextInfo.createNoRestore(RCmdOptions.Client.R, null, RContext.ContextKind.SHARE_NOTHING, null, consoleHandler);
-        engine = info.createVM(PolyglotEngine.newBuilder());
+        context = Context.create();
+        consoleCompleter = new JLineConsoleCompleter(context);
     }
 
     @After
     public void dispose() {
-        if (engine != null) {
-            engine.dispose();
+        if (context != null) {
+            context.close();
         }
     }
 
+    // disabled because it uses Engine, which clashes with other tests that use PolyglotEngine
+    @Ignore
     @Test
     public void testCompl() {
         assertCompl("", 0);
@@ -117,47 +115,4 @@ public class TestJLineConsoleCompleter {
             Assert.assertArrayEquals(expected, l.toArray(new CharSequence[l.size()]));
         }
     }
-
-    private class DummyConsoleHandler extends ConsoleHandler {
-
-        @Override
-        public void println(String s) {
-        }
-
-        @Override
-        public void print(String s) {
-        }
-
-        @Override
-        public void printErrorln(String s) {
-        }
-
-        @Override
-        public void printError(String s) {
-        }
-
-        @Override
-        public String readLine() {
-            return "";
-        }
-
-        @Override
-        public boolean isInteractive() {
-            return false;
-        }
-
-        @Override
-        public String getPrompt() {
-            return "";
-        }
-
-        @Override
-        public void setPrompt(String prompt) {
-        }
-
-        @Override
-        public String getInputDescription() {
-            return "";
-        }
-    }
 }
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 19068de2cbd7721c7c16ebf3b64365df6616c799..7d74661025fe370f943e80489953f329edecdd05 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
@@ -76,7 +76,9 @@ public class TestFunctions extends TestBase {
 
         assertEval("{ matrix(x=1) }");
         assertEval("{ set.seed(4357); round( rnorm(1,), digits = 5 ) }");
-        assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ max(1,2,) }");
+        // FIXME UnsupportedSpecializationException: Unexpected values provided for
+        // PrecedenceNodeGen@7c078bf0: [empty, false], [REmpty,Boolean]
+        assertEval(Ignored.ImplementationError, "{ max(1,2,) }");
     }
 
     @Test
@@ -147,11 +149,16 @@ public class TestFunctions extends TestBase {
         assertEval("{ x<-function(){1} ; x(y=1) }");
         assertEval("{ f <- function(a,b,c,d) { a + b } ; f(1,x=1,2,3,4) }");
 
-        assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ x<-function(y, b){1} ; x(y=1, 2, 3, z = 5) }");
+        // FIXME GnuR's error message more precise
+        // Expected output: Error in x(y = 1, 2, 3, z = 5) : unused arguments (3, z = 5)
+        // FastR output: Error in x(y = 1, 2, 3, z = 5) : unused argument (z = 5)
+        assertEval(Ignored.ImplementationError, "{ x<-function(y, b){1} ; x(y=1, 2, 3, z = 5) }");
         assertEval("{ x<-function(a){1} ; x(1,) }");
 
-        // note exactly GNU-R message
-        assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(a,a) {1} }");
+        // FIXME error message missing
+        // Expected output: Error: repeated formal argument 'a' on line 1
+        // FastR output:
+        assertEval(Ignored.ImplementationError, Output.IgnoreErrorContext, "{ f <- function(a,a) {1} }");
     }
 
     @Test
@@ -188,9 +195,8 @@ public class TestFunctions extends TestBase {
         assertEval("{ f<-function(i) { if(i==1) { 1 } else { f(i-1) } } ; f(10) }");
         assertEval("{ f<-function(i) { if(i<=1) 1 else i*f(i-1) } ; f(10) }"); // factorial
         assertEval("{ f<-function(i) { if(i<=1L) 1L else i*f(i-1L) } ; f(10L) }"); // factorial
-        // 100 times calculate factorial of 120
-        // the GNU R outputs 6.689503e+198
-        assertEval("{ f<-function(i) { if(i<=1) 1 else i*f(i-1) } ; g<-function(n, f, a) { if (n==1) { f(a) } else { f(a) ; g(n-1, f, a) } } ; g(100,f,120) }");
+        // 100 times calculate factorial of 100
+        assertEval("{ f<-function(i) { if(i<=1) 1 else i*f(i-1) } ; g<-function(n, f, a) { if (n==1) { f(a) } else { f(a) ; g(n-1, f, a) } } ; g(100,f,100) }");
 
         // Fibonacci numbers
         assertEval("{ f<-function(i) { if (i==1) { 1 } else if (i==2) { 1 } else { f(i-1) + f(i-2) } } ; f(10) }");
@@ -206,8 +212,15 @@ public class TestFunctions extends TestBase {
         assertEval("{ f <- function(a) { g <- function(b) { x <<- 2; b } ; g(a) } ; x <- 1 ; f(x) }");
         assertEval("{ f <- function(a) { g <- function(b) { a <<- 3; b } ; g(a) } ; x <- 1 ; f(x) }");
         assertEval("{ f <- function(x) { function() {x} } ; a <- 1 ; b <- f(a) ; a <- 10 ; b() }");
-
         assertEval("{ f <- function(x = y, y = x) { y } ; f() }");
+        assertEval("foo <- function(a,b) { x<<-4; b; }; x <- 0; foo(2, x > 2);");
+        // FIXME eager promises bug
+        // Note: following test fails on the first invocation only, consequent invocations produce
+        // correct result. The problem is that OptForcedEagerPromiseNode is not creating assumptions
+        // that variables involved in the eagerly evaluated expression are no being updated in the
+        // meantime as side effect of evaluation of some other argument.
+        assertEval(Ignored.ImplementationError, "foo <- function(x,z) x + z; x <- 4; bar <- function() { x <<- 10; 1; }; foo(bar(), x);");
+        assertEval(Ignored.ImplementationError, "foo <- function(x,z) list(x,z); x <- 4; bar <- function() { x <<- 10; 1; }; foo(bar(), x > 5);");
     }
 
     @Test
@@ -215,6 +228,11 @@ public class TestFunctions extends TestBase {
         assertEval("g <- function(e) get(\"ex\", e);f <- function(e, en) {  exports <- g(e);  unlist(lapply(en, get, envir = exports, inherits = FALSE))}; " +
                         "e1 <- new.env(); e1n <- new.env(); assign(\"a\", \"isa\", e1n); assign(\"ex\", e1n, e1); " +
                         "e2 <- new.env(); e2n <- new.env(); assign(\"b\", \"isb\", e2n); assign(\"ex\", e2n, e2); ex1 <- c(\"a\"); ex2 <- c(\"b\"); f(e1, ex1); f(e2, ex2) == \"isb\"");
+        assertEval("rule <- 1; stopifnot((lenR <- length(rule)) >= 1L, lenR <= 2L)");
+        assertEval("{ x <- 3; stopifnot((x <- 5) < 10, x == 5); }");
+        // assignment in arguments + function that has a fast path
+        assertEval("{ seq((abc <- 1), length.out = abc + 1) }");
+        assertEval("{ seq((abc <- 1), abc + 10) }");
     }
 
     @Test
@@ -335,13 +353,26 @@ public class TestFunctions extends TestBase {
         assertEval("{ `-.foo` <- function(...) 123; v <- 1; class(v) <- 'foo'; sapply(1,`-`,v); sapply(v,`-`,1); sapply(v,`-`,v) }");
 
         assertEval("{ f <- function(...) { substitute(..1) } ;  f(x+y) }");
-
-        assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ lapply(1:3, \"dummy\") }");
-
-        assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ..., x=2,z=3) } ; g(1) }");
+        // Error messages differ
+        // Expected output: Error in get(as.character(FUN), mode = "function", envir = envir) :
+        // object 'dummy' of mode 'function' was not found
+        // FastR output: Error in match.fun(FUN) : could not find function "dummy"
+        assertEval(Output.IgnoreErrorMessage, "{ lapply(1:3, \"dummy\") }");
+
+        // Error messages differ
+        // Expected output: Error in f(a = 1, ..., x = 2, z = 3) : unused arguments (x = 2, z = 3)
+        // FastR output: Error in f(a = 1, ..., x = 2, z = 3) : unused argument (x = 2)
+        assertEval(Output.IgnoreErrorMessage, "{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ..., x=2,z=3) } ; g(1) }");
         assertEval("{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ...,,,) } ; g(1) }");
-        assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(...) { ..2 + ..2 } ; f(1,,2) }");
-        assertEval(Ignored.Unknown, Output.IgnoreErrorContext, "{ f <- function(...) { ..1 + ..2 } ; f(1,,3) }");
+        // Error messages differ
+        // Expected output: Error in ..2 + ..2 : non-numeric argument to binary operator
+        // FastR output: Error in ..2 + ..2 : invalid argument to unary operator
+        assertEval(Output.IgnoreErrorMessage, "{ f <- function(...) { ..2 + ..2 } ; f(1,,2) }");
+        // FIXME GnuR's probably better approach since missing(..n) could be used
+        // for arg presence so using ImplementationError for now.
+        // Expected output: Error in ..1 + ..2 : non-numeric argument to binary operator
+        // FastR output: [1] 1
+        assertEval(Ignored.ImplementationError, "{ f <- function(...) { ..1 + ..2 } ; f(1,,3) }");
 
         assertEval("{ f1 <- function(...) { subst <- substitute(list(...))[-1L]; eval(subst[[1]]) }; f2 <- function(a, ...) TRUE; f3 <- function(a, ...) { cat(\"Here:\"); f1(f2(a, ...)) }; f1(f3(\"aaa\")) }");
     }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestS3Dispatch.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestS3Dispatch.java
index 2c8c4652b6eb1dbf082f1eb985e0e62b2237d67c..f5e23cfbfddf04db9d96648da153695fcd09b575 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestS3Dispatch.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestS3Dispatch.java
@@ -35,7 +35,9 @@ public class TestS3Dispatch extends TestRBase {
     public void testUseMethodLocalVars() {
         // The variables defined before call to UseMethod should be
         // accessible to target function.
-        assertEval(Ignored.Unknown,
+        // Expected output: f second 1local
+        // FastR output: f second 1Error in f.second(obj) : could not find function "locFun"
+        assertEval(Ignored.ImplementationError,
                         "{f <- function(x){ y<-2;locFun <- function(){cat(\"local\")}; UseMethod(\"f\"); }; f.second <- function(x){cat(\"f second\",x);locFun();}; obj <-1; attr(obj,\"class\")  <- \"second\"; f(obj);}");
     }
 
@@ -144,6 +146,6 @@ public class TestS3Dispatch extends TestRBase {
 
     @Override
     public String getTestDir() {
-        return "functions/S3";
+        return "S3";
     }
 }
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 6f213a4cefec5593582bcc8e8f176261cd83dd20..e3311fb6481737378c6d2f478032e554e08fd14b 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
@@ -22,29 +22,33 @@
  */
 package com.oracle.truffle.r.test.generate;
 
-import java.util.ArrayDeque;
-import java.util.Arrays;
-import java.util.Deque;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.UnsupportedEncodingException;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+import java.nio.charset.StandardCharsets;
 import java.util.TimeZone;
 import java.util.Timer;
 import java.util.TimerTask;
 
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.debug.Debugger;
 import com.oracle.truffle.api.debug.SuspendedCallback;
 import com.oracle.truffle.api.debug.SuspendedEvent;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
+import com.oracle.truffle.r.launcher.RCmdOptions;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RStartParams;
 import com.oracle.truffle.r.runtime.ExitException;
+import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.JumpToTopLevelException;
-import com.oracle.truffle.r.runtime.RCmdOptions;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.RStartParams;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.ChildContextInfo;
 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;
@@ -53,8 +57,7 @@ import com.oracle.truffle.r.test.TestBase;
 
 public final class FastRSession implements RSession {
 
-    private static final String TEST_TIMEOUT_PROPERTY = "FastRTestTimeout";
-    private static final String DISABLE_TIMEOUT_PROPERTY = "DisableTestTimeout"; // legacy
+    private static final String TEST_TIMEOUT_PROPERTY = "fastr.test.timeout";
     private static int timeoutValue = 10000;
     /**
      * The long timeout is used for package installation and currently needs to be 5 mins for the
@@ -62,83 +65,34 @@ public final class FastRSession implements RSession {
      */
     private static int longTimeoutValue = 300000;
 
-    /**
-     * 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 extends ConsoleHandler {
-        private final StringBuilder buffer = new StringBuilder();
-        private final Deque<String> input = new ArrayDeque<>();
-
-        public void setInput(String[] lines) {
-            input.clear();
-            input.addAll(Arrays.asList(lines));
-        }
-
-        @Override
-        @TruffleBoundary
-        public void println(String s) {
-            buffer.append(s);
-            buffer.append('\n');
-        }
-
-        @Override
-        @TruffleBoundary
-        public void print(String s) {
-            buffer.append(s);
-        }
-
-        @Override
-        public String readLine() {
-            return input.pollFirst();
-        }
+    private static final class TestByteArrayInputStream extends ByteArrayInputStream {
 
-        @Override
-        public boolean isInteractive() {
-            return false;
+        TestByteArrayInputStream() {
+            super(new byte[0]);
         }
 
-        @Override
-        @TruffleBoundary
-        public void printErrorln(String s) {
-            println(s);
+        public void setContents(String data) {
+            this.buf = data.getBytes(StandardCharsets.UTF_8);
+            this.count = this.buf.length;
+            this.pos = 0;
         }
 
         @Override
-        @TruffleBoundary
-        public void printError(String s) {
-            print(s);
-        }
-
-        @Override
-        public String getPrompt() {
-            return null;
-        }
-
-        @Override
-        public void setPrompt(String prompt) {
-            // ignore
-        }
-
-        @TruffleBoundary
-        void reset() {
-            buffer.delete(0, buffer.length());
-        }
-
-        @Override
-        public String getInputDescription() {
-            return "<test input>";
+        public synchronized int read() {
+            return super.read();
         }
     }
 
     private static FastRSession singleton;
 
-    private final TestConsoleHandler consoleHandler;
+    private final ByteArrayOutputStream output = new ByteArrayOutputStream();
+    private final TestByteArrayInputStream input = new TestByteArrayInputStream();
     private final PolyglotEngine main;
     private final RContext mainContext;
 
     public static FastRSession create() {
         if (singleton == null) {
+            FastROptions.setValue("SpawnUsesPolyglot", true);
             singleton = new FastRSession();
         }
         return singleton;
@@ -146,9 +100,9 @@ public final class FastRSession implements RSession {
 
     public static final Source GET_CONTEXT = RSource.fromTextInternal("invisible(.fastr.context.get())", RSource.Internal.GET_CONTEXT);
 
-    public ContextInfo checkContext(ContextInfo contextInfoArg) {
+    public ChildContextInfo checkContext(ChildContextInfo contextInfoArg) {
         create();
-        ContextInfo contextInfo;
+        ChildContextInfo contextInfo;
         if (contextInfoArg == null) {
             contextInfo = createContextInfo(ContextKind.SHARE_PARENT_RW);
         } else {
@@ -157,37 +111,88 @@ public final class FastRSession implements RSession {
         return contextInfo;
     }
 
-    public ContextInfo createContextInfo(ContextKind contextKind) {
-        RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.RSCRIPT, new String[]{"--no-restore"}, false), false);
-        return ContextInfo.create(params, null, contextKind, mainContext, consoleHandler, TimeZone.getTimeZone("GMT"));
+    public ChildContextInfo createContextInfo(ContextKind contextKind) {
+        RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false);
+        return ChildContextInfo.create(params, null, contextKind, mainContext, input, output, output, TimeZone.getTimeZone("GMT"));
     }
 
     private FastRSession() {
-        if (System.getProperty(DISABLE_TIMEOUT_PROPERTY) != null) {
-            timeoutValue = Integer.MAX_VALUE;
-            longTimeoutValue = Integer.MAX_VALUE;
-        } else if (System.getProperty(TEST_TIMEOUT_PROPERTY) != null) {
-            int timeoutGiven = Integer.parseInt(System.getProperty(TEST_TIMEOUT_PROPERTY));
-            timeoutValue = timeoutGiven * 1000;
-            // no need to scale longTimeoutValue
+        String timeOutProp = System.getProperty(TEST_TIMEOUT_PROPERTY);
+        if (timeOutProp != null) {
+            if (timeOutProp.length() == 0) {
+                timeoutValue = Integer.MAX_VALUE;
+                longTimeoutValue = Integer.MAX_VALUE;
+            } else {
+                int timeoutGiven = Integer.parseInt(timeOutProp);
+                timeoutValue = timeoutGiven * 1000;
+                // no need to scale longTimeoutValue
+            }
         }
-        consoleHandler = new TestConsoleHandler();
         try {
-            RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.RSCRIPT, new String[]{"--no-restore"}, false), false);
-            ContextInfo info = ContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, consoleHandler);
+            RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false);
+            ChildContextInfo info = ChildContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, input, output, output);
             main = info.createVM();
             mainContext = main.eval(GET_CONTEXT).as(RContext.class);
         } finally {
-            System.out.print(consoleHandler.buffer.toString());
+            try {
+                System.out.print(output.toString("UTF-8"));
+            } catch (UnsupportedEncodingException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private final CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder();
+
+    {
+        decoder.onMalformedInput(CodingErrorAction.IGNORE);
+        decoder.onUnmappableCharacter(CodingErrorAction.IGNORE);
+    }
+
+    public RContext getContext() {
+        return mainContext;
+    }
+
+    private String readLine() {
+        /*
+         * We cannot use an InputStreamReader because it buffers characters internally, whereas
+         * readLine() should not buffer across newlines.
+         */
+
+        ByteBuffer bytes = ByteBuffer.allocate(16);
+        CharBuffer chars = CharBuffer.allocate(16);
+        StringBuilder str = new StringBuilder();
+        decoder.reset();
+        boolean initial = true;
+        while (true) {
+            int inputByte = input.read();
+            if (inputByte == -1) {
+                return initial ? null : str.toString();
+            }
+            initial = false;
+            bytes.put((byte) inputByte);
+            bytes.flip();
+            decoder.decode(bytes, chars, false);
+            chars.flip();
+            while (chars.hasRemaining()) {
+                char c = chars.get();
+                if (c == '\n' || c == '\r') {
+                    return str.toString();
+                }
+                str.append(c);
+            }
+            bytes.compact();
+            chars.clear();
         }
     }
 
     @Override
-    public String eval(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable {
+    public String eval(TestBase testClass, String expression, ChildContextInfo contextInfo, boolean longTimeout) throws Throwable {
         Timer timer = null;
-        consoleHandler.reset();
+        output.reset();
+        input.setContents(expression);
         try {
-            ContextInfo actualContextInfo = checkContext(contextInfo);
+            ChildContextInfo actualContextInfo = checkContext(contextInfo);
             // set up some interop objects used by fastr-specific tests:
             PolyglotEngine.Builder builder = PolyglotEngine.newBuilder();
             if (testClass != null) {
@@ -195,11 +200,10 @@ public final class FastRSession implements RSession {
             }
             PolyglotEngine vm = actualContextInfo.createVM(builder);
             timer = scheduleTimeBoxing(vm, longTimeout ? longTimeoutValue : timeoutValue);
-            consoleHandler.setInput(expression.split("\n"));
             try {
-                String input = consoleHandler.readLine();
-                while (input != null) {
-                    Source source = RSource.fromTextInternal(input, RSource.Internal.UNIT_TEST);
+                String consoleInput = readLine();
+                while (consoleInput != null) {
+                    Source source = RSource.fromTextInternal(consoleInput, RSource.Internal.UNIT_TEST);
                     try {
                         try {
                             vm.eval(source);
@@ -211,20 +215,20 @@ public final class FastRSession implements RSession {
                                 throw e;
                             }
                         }
-                        input = consoleHandler.readLine();
+                        consoleInput = readLine();
                     } catch (IncompleteSourceException e) {
-                        String additionalInput = consoleHandler.readLine();
+                        String additionalInput = readLine();
                         if (additionalInput == null) {
                             throw e;
                         }
-                        input += "\n" + additionalInput;
+                        consoleInput += "\n" + additionalInput;
                     }
                 }
             } finally {
                 vm.dispose();
             }
         } catch (ParseException e) {
-            e.report(consoleHandler);
+            e.report(output);
         } catch (ExitException | JumpToTopLevelException e) {
             // exit and jumpToTopLevel exceptions are legitimate if a test case calls "q()" or "Q"
             // during debugging
@@ -243,7 +247,12 @@ public final class FastRSession implements RSession {
                 timer.cancel();
             }
         }
-        return consoleHandler.buffer.toString();
+        try {
+            return output.toString("UTF-8");
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return "<exception>";
+        }
     }
 
     private static Timer scheduleTimeBoxing(PolyglotEngine engine, long timeout) {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java
index 5771c2814c844a5c8bc20b1fcc0a35393c59b397..8c6ba569e21b2e0d0dde22e63cefc4b910037fa3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java
@@ -29,10 +29,10 @@ import java.nio.file.FileSystems;
 import java.nio.file.Path;
 import java.util.concurrent.TimeUnit;
 
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.runtime.ProcessOutputManager;
 import com.oracle.truffle.r.runtime.REnvVars;
-import com.oracle.truffle.r.runtime.RVersionNumber;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.ChildContextInfo;
 import com.oracle.truffle.r.test.TestBase;
 
 /**
@@ -93,7 +93,7 @@ public class GnuROneShotRSession implements RSession {
     }
 
     @Override
-    public String eval(TestBase testBase, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable {
+    public String eval(TestBase testBase, String expression, ChildContextInfo contextInfo, boolean longTimeout) throws Throwable {
         if (expression.contains("library(") && !TestBase.generatingExpected()) {
             System.out.println("==============================================");
             System.out.println("LIBRARY LOADING WHEN NOT GENERATING EXPECTED OUTPUT");
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java
index a1596b25bb0679a326947af47f88b037b0c0e501..6783accf7580181e9765119ce13e118424d5a2ba 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.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
@@ -22,7 +22,7 @@
  */
 package com.oracle.truffle.r.test.generate;
 
-import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.ChildContextInfo;
 import com.oracle.truffle.r.test.TestBase;
 
 /**
@@ -41,9 +41,8 @@ public interface RSession {
      *
      * This result will always be non-null or an exception will be thrown in, say, a timeout
      * occurring.
-     *
      */
-    String eval(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable;
+    String eval(TestBase testClass, String expression, ChildContextInfo contextInfo, boolean longTimeout) throws Throwable;
 
     /**
      * A name to identify the session.
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java
index 11ea45697778de78a859b17f36047f90dc0d5660..dc89e288590de4dbb6572e13a827a4ff692be717 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/TestOutputManager.java
@@ -25,12 +25,15 @@ package com.oracle.truffle.r.test.generate;
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
 import java.io.File;
-import java.io.FileReader;
+import java.io.FileInputStream;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.io.Reader;
 import java.io.StringWriter;
+import java.net.URL;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -141,8 +144,16 @@ public class TestOutputManager {
      */
     public final File outputFile;
 
+    private final URL urlOutput;
+
     public TestOutputManager(File outputFile) {
         this.outputFile = outputFile;
+        this.urlOutput = null;
+    }
+
+    public TestOutputManager(URL urlOutput) {
+        this.urlOutput = urlOutput;
+        this.outputFile = null;
     }
 
     protected void setRSession(RSession session) {
@@ -214,11 +225,18 @@ public class TestOutputManager {
     }
 
     public String readTestOutputFile() throws IOException {
-        if (!outputFile.exists()) {
+        if (outputFile != null && !outputFile.exists()) {
             return null;
         }
+        InputStream is;
+        if (outputFile != null) {
+            is = new FileInputStream(outputFile);
+        } else {
+            assert urlOutput != null;
+            is = urlOutput.openStream();
+        }
         StringBuilder content = new StringBuilder();
-        try (SaveBufferedReader in = new SaveBufferedReader(new FileReader(outputFile), content)) {
+        try (SaveBufferedReader in = new SaveBufferedReader(new InputStreamReader(is), content)) {
             // line format for element name: ##elementName
             // line format for input lines: #input
             // output lines do not start with ##
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
index bafe789b1f0c79c3df1f66ff23cf74008bb65861..985245c14c8517c7812c839b97bd8ec4b1156a80 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConditionHandling.java
@@ -30,7 +30,7 @@ public class TestConditionHandling extends TestRBase {
 
     @Override
     public String getTestDir() {
-        return "library/base/condition";
+        return "condition";
     }
 
     @Test
@@ -46,10 +46,12 @@ public class TestConditionHandling extends TestRBase {
         // <simpleError in doTryCatch(return(expr), name, parentenv, handler): fred>
         // FastR output: [1] "Hello"
         // <simpleError: fred>
-        assertEval(Ignored.ImplementationError, "{ tryCatch(stop(\"fred\"), error = function(e) e, finally = print(\"Hello\"))}");
+        assertEval(Ignored.ImplementationError, "{ tryCatch(stop('fred'), error = function(e) e, finally = print('Hello'))}");
+        assertEval("x <- { tryCatch(stop('fred'), error = function(e) e, finally = print('Hello'))}; x$call <- NULL; x");
         assertEval("{ f <- function() { tryCatch(1, error = function(e) print(\"Hello\")); stop(\"fred\")}; f() }");
         assertEval("{ f <- function() { tryCatch(stop(\"fred\"), error = function(e) print(\"Hello\"))}; f() }");
         assertEval("{ tryCatch(stop(\"xyz\"), error=function(e) { cat(\"<error>\");123L }, finally=function() { cat(\"<finally>\")}) }");
+        assertEval("my.error <- function(war) cat('my.error:', war$message, '\\n'); f <- function() print(g); tryCatch({f()}, error=my.error)");
     }
 
     @Test
@@ -72,4 +74,10 @@ public class TestConditionHandling extends TestRBase {
         assertEval(Output.IgnoreErrorContext, "withCallingHandlers(stop('error message'), error=function(e) {})");
         assertEval(Output.IgnoreErrorMessage, "withCallingHandlers(unknownSymbol(), condition = function(e) {})");
     }
+
+    @Test
+    public void testWarning() {
+        assertEval("tryCatch(warning('some warning text'), warning = function(w) {print('WARNING')})");
+        assertEval("my.warning <- function(war) cat('my.warning:', war$message, '\\n'); f <- function()  warning('from f'); tryCatch({f()}, warning=my.warning)");
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
index f1aeb3cf9e11661412dc09a88db57544465fb977..39ee482d5ffa163cc037841d43a8c5ba95b69071 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestConnections.java
@@ -57,7 +57,7 @@ public class TestConnections extends TestRBase {
 
     @Override
     protected String getTestDir() {
-        return "builtins/connection";
+        return "connections";
     }
 
     @BeforeClass
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
index 22c14a3b209d3193f91d206d4f692c246a569823..6d923bc76d87193005b99be997e4f982016973ea 100644
--- 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
@@ -31,7 +31,8 @@ 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("")));
+        assertEval(TestBase.template(
+                        "library(parallel); fun <- function(data) { cl <- makeCluster(%0, ifelse(exists('engine', where=R.version),'SHARED','PSOCK')); 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/base/TestSimpleAssignment.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAssignment.java
index fe48ffd5e21ce2303ac0682f1f4ea44c84b4f40c..b775649fd5aacf44a8ecb210ab33419fe40e2bee 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAssignment.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleAssignment.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -111,5 +111,14 @@ public class TestSimpleAssignment extends TestBase {
         assertEval("{ f <- function() { if (FALSE) { x <- 1 } ; g <- function() { x } ; g() } ; f() }");
         assertEval("{ f <- function() { if (FALSE) { c <- 1 } ; g <- function() { c } ; g() } ; typeof(f()) }");
         assertEval("{ `f<-` <- function(x, y=42, value) { x[1]<-value+y; x }; y<-1:10; f(y)<-7; y }");
+
+        assertEval("proto <- c(11,11); f <- function() { for (i in 1:2) proto[[i]] <- i; proto }; f()");
+        assertEval("proto <- c(11,11); f <- function() { for (i in 1:2) print(proto[[i]] <- i); proto }; f()");
+        assertEval("proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) proto[[i]] <- i; proto }; f()");
+        assertEval("proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) print(proto[[i]] <- i); proto }; f()");
+        assertEval("proto <- c(11,11); f <- function() { for (i in 1:2) proto[[i]] <<- i; proto }; f()");
+        assertEval("proto <- c(11,11); f <- function() { for (i in 1:2) print(proto[[i]] <<- i); proto }; f()");
+        assertEval("proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) proto[[i]] <<- i; proto }; f()");
+        assertEval("proto <- c(11,11); f <- function() { proto <- c(4,5); for (i in 1:2) print(proto[[i]] <<- i); proto }; f()");
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleSequences.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleSequences.java
index dc4f1bdb0eade007de69ea3e2e28451cddeddc05..dda6158cb7604e1193f49c88d630f0b26fed4900 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleSequences.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleSequences.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
@@ -53,6 +53,16 @@ public class TestSimpleSequences extends TestBase {
         assertEval("{ 1:(1:3) }");
         assertEval("{ (1:3):3 }");
         assertEval("{ (1:3):(1:3) }");
+        assertEval("{ 0L:Inf }");
+        assertEval("{ 0L:-Inf }");
+        assertEval("{ -Inf:0L }");
+        assertEval("{ -Inf:Inf }");
+        assertEval("{ 0:Inf }");
+        assertEval("{ 0:-Inf }");
+        assertEval("{ -Inf:0 }");
+        assertEval("{ 1L:(0/0) }");
+        assertEval("{ (0/0):1L }");
+        assertEval("{ (0/0):(0/0) }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
index 4e95a79254c9b05192b6beecbf72e31b2b77f024..12fcf8471a70b6c76502e3a88c596c2f8c138723 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleVectors.java
@@ -2186,7 +2186,7 @@ public class TestSimpleVectors extends TestBase {
         assertEval(Output.IgnoreErrorMessage, "{ x <- NULL; x[[c(1,0)]] <- c(1,5); x; }");
         assertEval(Output.IgnoreErrorMessage, "{ x <- NULL; x[[c(1,2)]] <- c(1,5); x; }");
 
-        assertEval(Ignored.Unimplemented, "{ x <- NULL; x[[1]] <- c(1,5); x; }");
+        assertEval("{ x <- NULL; x[[1]] <- c(1,5); x; }");
     }
 
     @Test
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/fifo_GnuR_example.R
similarity index 100%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/fifo_GnuR_example.R
rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/fifo_GnuR_example.R
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/rawConnection_readBin.R
similarity index 100%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readBin.R
rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/rawConnection_readBin.R
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/rawConnection_readWriteBin.R
similarity index 100%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_readWriteBin.R
rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/rawConnection_readWriteBin.R
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/rawConnection_seek.R
similarity index 100%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_seek.R
rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/rawConnection_seek.R
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/rawConnection_writeBin.R
similarity index 100%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/rawConnection_writeBin.R
rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/rawConnection_writeBin.R
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/readLines_GnuR_example.R
similarity index 100%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/readLines_GnuR_example.R
rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/readLines_GnuR_example.R
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/textConnection.R
similarity index 100%
rename from com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/connection/R/textConnection.R
rename to com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/connections/R/textConnection.R
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 6ce8c916abceface6107b8994e53e785f0abc5f7..67b034176b752e634594d2dfcb7b027effbfc7fa 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
@@ -51,41 +51,61 @@ public class TestInterop extends TestBase {
 
     @Test
     public void testInteropEval() {
-        assertEvalFastR(".fastr.interop.eval('application/x-r', '14 + 2')", "16");
-        assertEvalFastR(".fastr.interop.eval('application/x-r', '1')", "1");
-        assertEvalFastR(".fastr.interop.eval('application/x-r', '1L')", "1L");
-        assertEvalFastR(".fastr.interop.eval('application/x-r', 'TRUE')", "TRUE");
-        assertEvalFastR(".fastr.interop.eval('application/x-r', 'as.character(123)')", "as.character(123)");
+        assertEvalFastR("eval.external('application/x-r', '14 + 2')", "16");
+        assertEvalFastR("eval.external('application/x-r', '1')", "1");
+        assertEvalFastR("eval.external('application/x-r', '1L')", "1L");
+        assertEvalFastR("eval.external('application/x-r', 'TRUE')", "TRUE");
+        assertEvalFastR("eval.external('application/x-r', 'as.character(123)')", "as.character(123)");
     }
 
     @Test
     public void testInteropExport() {
-        assertEvalFastR(".fastr.interop.export('foo', 14 + 2)", "invisible()");
-        assertEvalFastR(".fastr.interop.export('foo', 'foo')", "invisible()");
-        assertEvalFastR(".fastr.interop.export('foo', 1:100)", "invisible()");
-        assertEvalFastR(".fastr.interop.export('foo', new.env())", "invisible()");
+        assertEvalFastR("export('foo', 14 + 2)", "invisible()");
+        assertEvalFastR("export('foo', 'foo')", "invisible()");
+        assertEvalFastR("export('foo', 1:100)", "invisible()");
+        assertEvalFastR("export('foo', new.env())", "invisible()");
+    }
+
+    @Test
+    public void testIsExternalExecutable() {
+        assertEvalFastR("is.external.executable(sum)", "TRUE");
+        assertEvalFastR("is.external.executable(NULL)", "FALSE");
+        assertEvalFastR("is.external.executable(c(1))", "FALSE");
+        assertEvalFastR("is.external.executable(list(1))", "FALSE");
+        assertEvalFastR("is.external.executable()", "FALSE");
+    }
+
+    @Test
+    public void testIsExternalNull() {
+        assertEvalFastR("is.external.null(NULL)", "TRUE");
+        assertEvalFastR("is.external.null(c(1))", "FALSE");
+        assertEvalFastR("is.external.null(list(1))", "FALSE");
+        assertEvalFastR("is.external.null()", "FALSE");
     }
 
     @Test
     public void testInteropEvalFile() {
-        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\")",
+        assertEvalFastR("fileConn<-file(\"" + TEST_EVAL_FILE + "\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);eval.external(mimeType=\"application/x-r\", path=\"" +
+                        TEST_EVAL_FILE + "\")",
                         "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 + "\")",
+        assertEvalFastR("fileConn<-file(\"" + TEST_EVAL_FILE + "\");writeLines(c(\"x<-c(1)\",\"cat(x)\"), fileConn);close(fileConn);eval.external(path=\"" + TEST_EVAL_FILE + "\")",
                         "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')");
+        assertEvalFastR("tryCatch(eval.external(path=\"/a/b.R\"),  error = function(e) e$message)", "cat('[1] \"Error reading file: /a/b.R\"\\n')");
+
+        assertEvalFastR("eval.external()", "cat('Error in eval.external() : invalid \\'source\\' or \\'path\\' argument\\n')");
+        assertEvalFastR("eval.external(,'abc',)", "cat('Error in eval.external(, \"abc\", ) : invalid mimeType argument\\n')");
     }
 
     /**
      * Used for testing interop functionality.
      */
     public static final class POJO {
-        public int intValue = 1;
-        public long longValue = 123412341234L;
+        public String stringValue = "foo";
         public char charValue = 'R';
+        public int intValue = 1;
         public short shortValue = -100;
         public boolean booleanValue = true;
-        public String stringValue = "foo";
+        public long longValue = 123412341234L;
     }
 
     private static final class TestJavaObject {
@@ -111,28 +131,28 @@ public class TestInterop extends TestBase {
 
     @Test
     public void testPrinting() {
-        assertEvalFastR("v <- .fastr.interop.import('testPOJO'); print(v)", "cat('[external object]\\n" +
-                        "$intValue\\n" +
-                        "[1] 1\\n" +
-                        "\\n" +
-                        "$longValue\\n" +
-                        "[1] 123412341234\\n" +
+        assertEvalFastR("v <- import('testPOJO'); print(v)", "cat('[external object]\\n" +
+                        "$stringValue\\n" +
+                        "[1] \"foo\"\\n" +
                         "\\n" +
                         "$charValue\\n" +
                         "[1] \"R\"\\n" +
                         "\\n" +
+                        "$intValue\\n" +
+                        "[1] 1\\n" +
+                        "\\n" +
                         "$shortValue\\n" +
                         "[1] -100\\n" +
                         "\\n" +
                         "$booleanValue\\n" +
                         "[1] TRUE\\n" +
                         "\\n" +
-                        "$stringValue\\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')");
+                        "$longValue\\n" +
+                        "[1] 123412341234\\n\\n')");
+        assertEvalFastR("v <- import('testStringArray'); print(v)", "cat('[external object]\\n[1] \"a\"   \"\"    \"foo\"\\n')");
+        assertEvalFastR("v <- import('testIntArray'); print(v)", "cat('[external object]\\n[1]   1  -5 199\\n')");
+        assertEvalFastR("v <- import('testIntArray'); v", "cat('[external object]\\n[1]   1  -5 199\\n')");
+        assertEvalFastR("v <- import('testPOJO'); names(v)", "c('stringValue', 'charValue', 'intValue', 'shortValue', 'booleanValue', 'longValue')");
     }
 
     @Test
@@ -144,7 +164,7 @@ public class TestInterop extends TestBase {
         CHANNEL.write(line1.getBytes());
         long oldPos = CHANNEL.position();
         CHANNEL.position(0);
-        assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res",
+        assertEvalFastR(String.format("v <- import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); res <- readLines(zz); close(zz); res",
                         CHANNEL_NAME),
                         "c('Hello, World!', 'second line')");
 
@@ -158,7 +178,7 @@ public class TestInterop extends TestBase {
         }
 
         final String response = "hi there";
-        assertEvalFastR(String.format("v <- .fastr.interop.import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('%s', zz); close(zz); NULL ", CHANNEL_NAME, response),
+        assertEvalFastR(String.format("v <- import('%s'); zz <- .fastr.channelConnection(v, 'r+', 'native.enc'); writeLines('%s', zz); close(zz); NULL ", CHANNEL_NAME, response),
                         "NULL");
 
         if (!generatingExpected()) {
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 557545ba6e3be4cf0ae958db0bcbc3b97d03b1f3..6c62351cee58b76edf2d5d784269bc68e1e485e7 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
@@ -22,23 +22,30 @@
  */
 package com.oracle.truffle.r.test.library.fastr;
 
-import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop;
-import com.oracle.truffle.r.runtime.RType;
-import org.junit.Test;
-
-import com.oracle.truffle.r.test.TestBase;
 import java.lang.reflect.Array;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
+
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Test;
+
+import com.oracle.truffle.r.nodes.builtin.base.printer.DoubleVectorPrinter;
+import com.oracle.truffle.r.nodes.builtin.fastr.FastRInterop;
+import com.oracle.truffle.r.runtime.RType;
+import com.oracle.truffle.r.test.TestBase;
 
 public class TestJavaInterop extends TestBase {
 
     private static final String TEST_CLASS = TestClass.class.getName();
+    private static final String CREATE_TRUFFLE_OBJECT = "to <- new.external(new.java.class('" + TEST_CLASS + "'));";
 
     @Before
     public void testInit() {
@@ -47,196 +54,330 @@ public class TestJavaInterop extends TestBase {
 
     @Test
     public void testToByte() {
-        assertEvalFastR("v <- .fastr.interop.toByte(1L); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toByte(1.1); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toByte(as.raw(1)); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toByte(1.1); class(v);", "'" + RType.RInteropByte.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toByte(1.1); typeof(v);", "'" + RType.RInteropByte.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toByte(" + Byte.MAX_VALUE + "); v;", "" + Byte.MAX_VALUE);
-        assertEvalFastR("v <- .fastr.interop.toByte(" + Byte.MIN_VALUE + "); v;", "" + Byte.MIN_VALUE);
-        assertEvalFastR("v <- .fastr.interop.toByte(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).byteValue());
-        assertEvalFastR("v <- .fastr.interop.toByte(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).byteValue());
-        assertEvalFastR("v <- .fastr.interop.toByte(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).byteValue());
-        assertEvalFastR("v <- .fastr.interop.toByte(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).byteValue());
+        assertEvalFastR("v <- as.external.byte(1L); v;", "1");
+        assertEvalFastR("v <- as.external.byte(1.1); v;", "1");
+        assertEvalFastR("v <- as.external.byte(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- as.external.byte(1.1); class(v);", "'" + RType.RInteropByte.getName() + "'");
+        assertEvalFastR("v <- as.external.byte(1.1); typeof(v);", "'" + RType.RInteropByte.getName() + "'");
+        assertEvalFastR("v <- as.external.byte(" + Byte.MAX_VALUE + "); v;", "" + Byte.MAX_VALUE);
+        assertEvalFastR("v <- as.external.byte(" + Byte.MIN_VALUE + "); v;", "" + Byte.MIN_VALUE);
+        assertEvalFastR("v <- as.external.byte(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).byteValue());
+        assertEvalFastR("v <- as.external.byte(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).byteValue());
+        assertEvalFastR("v <- as.external.byte(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).byteValue());
+        assertEvalFastR("v <- as.external.byte(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).byteValue());
     }
 
     @Test
     public void testToFloat() {
-        assertEvalFastR("v <- .fastr.interop.toFloat(1L); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); v;", "1.1");
-        assertEvalFastR("v <- .fastr.interop.toFloat(as.raw(1)); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); class(v);", "'" + RType.RInteropFloat.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toFloat(1.1); typeof(v);", "'" + RType.RInteropFloat.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toFloat(1L); class(v);", "'" + RType.RInteropFloat.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toFloat(1L); typeof(v);", "'" + RType.RInteropFloat.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toFloat(" + Float.MAX_VALUE + "); v;", "" + Float.MAX_VALUE);
-        assertEvalFastR("v <- .fastr.interop.toFloat(" + Float.MIN_VALUE + "); v;", "" + (double) Float.MIN_VALUE);
-        assertEvalFastR("v <- .fastr.interop.toFloat(" + Double.MAX_VALUE + "); v;", "Inf");
-        assertEvalFastR("v <- .fastr.interop.toFloat(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).floatValue());
+        assertEvalFastR("v <- as.external.float(1L); v;", "1");
+        assertEvalFastR("v <- as.external.float(1.1); v;", "1.1");
+        assertEvalFastR("v <- as.external.float(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- as.external.float(1.1); class(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- as.external.float(1.1); typeof(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- as.external.float(1L); class(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- as.external.float(1L); typeof(v);", "'" + RType.RInteropFloat.getName() + "'");
+        assertEvalFastR("v <- as.external.float(" + Float.MAX_VALUE + "); v;", "" + Float.MAX_VALUE);
+        assertEvalFastR("v <- as.external.float(" + Float.MIN_VALUE + "); v;", "" + (double) Float.MIN_VALUE);
+        assertEvalFastR("v <- as.external.float(" + Double.MAX_VALUE + "); v;", "Inf");
+        assertEvalFastR("v <- as.external.float(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).floatValue());
     }
 
     @Test
     public void testToLong() {
-        assertEvalFastR("v <- .fastr.interop.toLong(1L); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toLong(1.1); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toLong(as.raw(1)); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toLong(1.1); class(v);", "'" + RType.RInteropLong.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toLong(1.1); typeof(v);", "'" + RType.RInteropLong.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toLong(1L); class(v);", "'" + RType.RInteropLong.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toLong(1L); typeof(v);", "'" + RType.RInteropLong.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toLong(" + Integer.MAX_VALUE + "); v;", "" + Integer.MAX_VALUE);
-        assertEvalFastR("v <- .fastr.interop.toLong(" + Integer.MIN_VALUE + "); v;", "" + Integer.MIN_VALUE);
-        assertEvalFastR("v <- .fastr.interop.toLong(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).longValue());
-        assertEvalFastR("v <- .fastr.interop.toLong(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).longValue());
+        assertEvalFastR("v <- as.external.long(1L); v;", "1");
+        assertEvalFastR("v <- as.external.long(1.1); v;", "1");
+        assertEvalFastR("v <- as.external.long(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- as.external.long(1.1); class(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- as.external.long(1.1); typeof(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- as.external.long(1L); class(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- as.external.long(1L); typeof(v);", "'" + RType.RInteropLong.getName() + "'");
+        assertEvalFastR("v <- as.external.long(" + Integer.MAX_VALUE + "); v;", "" + Integer.MAX_VALUE);
+        assertEvalFastR("v <- as.external.long(" + Integer.MIN_VALUE + "); v;", "" + Integer.MIN_VALUE);
+        assertEvalFastR("v <- as.external.long(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).longValue());
+        assertEvalFastR("v <- as.external.long(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).longValue());
     }
 
     @Test
     public void testToShort() {
-        assertEvalFastR("v <- .fastr.interop.toShort(1L); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toShort(1.1); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toShort(as.raw(1)); v;", "1");
-        assertEvalFastR("v <- .fastr.interop.toShort(1.1); class(v);", "'" + RType.RInteropShort.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toShort(1.1); typeof(v);", "'" + RType.RInteropShort.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toShort(1L); class(v);", "'" + RType.RInteropShort.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toShort(1L); typeof(v);", "'" + RType.RInteropShort.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toShort(" + Short.MAX_VALUE + "); v;", "" + Short.MAX_VALUE);
-        assertEvalFastR("v <- .fastr.interop.toShort(" + Short.MIN_VALUE + "); v;", "" + Short.MIN_VALUE);
-        assertEvalFastR("v <- .fastr.interop.toShort(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).shortValue());
-        assertEvalFastR("v <- .fastr.interop.toShort(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).shortValue());
-        assertEvalFastR("v <- .fastr.interop.toShort(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).shortValue());
-        assertEvalFastR("v <- .fastr.interop.toShort(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).shortValue());
+        assertEvalFastR("v <- as.external.short(1L); v;", "1");
+        assertEvalFastR("v <- as.external.short(1.1); v;", "1");
+        assertEvalFastR("v <- as.external.short(as.raw(1)); v;", "1");
+        assertEvalFastR("v <- as.external.short(1.1); class(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- as.external.short(1.1); typeof(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- as.external.short(1L); class(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- as.external.short(1L); typeof(v);", "'" + RType.RInteropShort.getName() + "'");
+        assertEvalFastR("v <- as.external.short(" + Short.MAX_VALUE + "); v;", "" + Short.MAX_VALUE);
+        assertEvalFastR("v <- as.external.short(" + Short.MIN_VALUE + "); v;", "" + Short.MIN_VALUE);
+        assertEvalFastR("v <- as.external.short(" + Integer.MAX_VALUE + "); v;", "" + new Integer(Integer.MAX_VALUE).shortValue());
+        assertEvalFastR("v <- as.external.short(" + Integer.MIN_VALUE + "); v;", "" + new Integer(Integer.MIN_VALUE).shortValue());
+        assertEvalFastR("v <- as.external.short(" + Double.MAX_VALUE + "); v;", "" + new Double(Double.MAX_VALUE).shortValue());
+        assertEvalFastR("v <- as.external.short(" + Double.MIN_VALUE + "); v;", "" + new Double(Double.MIN_VALUE).shortValue());
     }
 
     @Test
     public void testToChar() {
-        assertEvalFastR("v <- .fastr.interop.toChar(97L); v;", "'a'");
-        assertEvalFastR("v <- .fastr.interop.toChar(97.1); v;", "'a'");
-        assertEvalFastR("v <- .fastr.interop.toChar(97.1, 1); v;", "cat('Error in .fastr.interop.toChar(97.1, 1) : ', '\n', ' pos argument not allowed with a numeric value', '\n')");
-        assertEvalFastR("v <- .fastr.interop.toChar(97L, 1); v;", "cat('Error in .fastr.interop.toChar(97L, 1) : ','\n',' pos argument not allowed with a numeric value', '\n')");
-        assertEvalFastR("v <- .fastr.interop.toChar('abc', 1); v;", "'b'");
-        assertEvalFastR("v <- .fastr.interop.toChar('abc', 1.1); v;", "'b'");
-        assertEvalFastR("v <- .fastr.interop.toChar(97.1); class(v);", "'" + RType.RInteropChar.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toChar(97.1); typeof(v);", "'" + RType.RInteropChar.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toChar(97L); class(v);", "'" + RType.RInteropChar.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toChar(97L); typeof(v);", "'" + RType.RInteropChar.getName() + "'");
-        assertEvalFastR("v <- .fastr.interop.toChar('a'); v;", "'a'");
+        assertEvalFastR("v <- as.external.char(97L); v;", "'a'");
+        assertEvalFastR("v <- as.external.char(97.1); v;", "'a'");
+        assertEvalFastR("v <- as.external.char(97.1, 1); v;", errorIn("as.external.char(97.1, 1)", "pos argument not allowed with a numeric value"));
+        assertEvalFastR("v <- as.external.char(97L, 1); v;", errorIn("as.external.char(97L, 1)", "pos argument not allowed with a numeric value"));
+        assertEvalFastR("v <- as.external.char('abc', 1); v;", "'b'");
+        assertEvalFastR("v <- as.external.char('abc', 1.1); v;", "'b'");
+        assertEvalFastR("v <- as.external.char(97.1); class(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- as.external.char(97.1); typeof(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- as.external.char(97L); class(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- as.external.char(97L); typeof(v);", "'" + RType.RInteropChar.getName() + "'");
+        assertEvalFastR("v <- as.external.char('a'); v;", "'a'");
     }
 
     @Test
     public void testToArray() {
-        assertEvalFastR("a <- .fastr.java.toArray(1L); a;", getRValue(new int[]{1}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(1L, 2L)); a;", getRValue(new int[]{1, 2}));
-        assertEvalFastR("a <- .fastr.java.toArray(1L,,T); a;", getRValue(new int[]{1}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(1L, 2L),,T); a;", getRValue(new int[]{1, 2}));
-
-        assertEvalFastR("a <- .fastr.java.toArray(1.1); a;", getRValue(new double[]{1.1}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(1.1, 1.2)); a;", getRValue(new double[]{1.1, 1.2}));
-        assertEvalFastR("a <- .fastr.java.toArray(1.1,,T); a;", getRValue(new double[]{1.1}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(1.1, 1.2),,T); a;", getRValue(new double[]{1.1, 1.2}));
-
-        assertEvalFastR("a <- .fastr.java.toArray(T); a;", getRValue(new boolean[]{true}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(T, F)); a;", getRValue(new boolean[]{true, false}));
-        assertEvalFastR("a <- .fastr.java.toArray(T,,T); a;", getRValue(new boolean[]{true}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(T, F),,T); a;", getRValue(new boolean[]{true, false}));
-
-        assertEvalFastR("a <- .fastr.java.toArray('a'); a;", getRValue(new String[]{"a"}));
-        assertEvalFastR("a <- .fastr.java.toArray(c('a', 'b')); a;", getRValue(new String[]{"a", "b"}));
-        assertEvalFastR("a <- .fastr.java.toArray('a',,T); a;", getRValue(new String[]{"a"}));
-        assertEvalFastR("a <- .fastr.java.toArray(c('a', 'b'),,T); a;", getRValue(new String[]{"a", "b"}));
-
-        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1)); a;", getRValue(new short[]{1}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2))); a;", getRValue(new short[]{1, 2}));
-        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1),,T); a;", getRValue(new short[]{1}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)),,T); a;", getRValue(new short[]{1, 2}));
+        assertEvalFastR("a <- as.java.array(1L); a;", getRValue(new int[]{1}));
+        assertEvalFastR("a <- as.java.array(1L); java.class(a);", "'[I'");
+        assertEvalFastR("a <- as.java.array(c(1L, 2L)); a;", getRValue(new int[]{1, 2}));
+        assertEvalFastR("a <- as.java.array(1L,,T); a;", getRValue(new int[]{1}));
+        assertEvalFastR("a <- as.java.array(c(1L, 2L),,T); a;", getRValue(new int[]{1, 2}));
+        assertEvalFastR("a <- as.java.array(c(1L, 2L),'double',T); a;", getRValue(new double[]{1, 2}));
+
+        assertEvalFastR("a <- as.java.array(1.1); a;", getRValue(new double[]{1.1}));
+        assertEvalFastR("a <- as.java.array(1.1); java.class(a);", "'[D'");
+        assertEvalFastR("a <- as.java.array(c(1.1, 1.2)); a;", getRValue(new double[]{1.1, 1.2}));
+        assertEvalFastR("a <- as.java.array(1.1,,T); a;", getRValue(new double[]{1.1}));
+        assertEvalFastR("a <- as.java.array(c(1.1, 1.2),,T); a;", getRValue(new double[]{1.1, 1.2}));
+        assertEvalFastR("a <- as.java.array(c(1.1, 1.2),'double',T); a;", getRValue(new double[]{1.1, 1.2}));
+
+        assertEvalFastR("a <- as.java.array(T); a;", getRValue(new boolean[]{true}));
+        assertEvalFastR("a <- as.java.array(T); java.class(a);", "'[Z'");
+        assertEvalFastR("a <- as.java.array(c(T, F)); a;", getRValue(new boolean[]{true, false}));
+        assertEvalFastR("a <- as.java.array(T,,T); a;", getRValue(new boolean[]{true}));
+        assertEvalFastR("a <- as.java.array(c(T, F),,T); a;", getRValue(new boolean[]{true, false}));
+        assertEvalFastR("a <- as.java.array(c(T, F),'boolean',T); a;", getRValue(new boolean[]{true, false}));
+
+        assertEvalFastR("a <- as.java.array('a'); a;", getRValue(new String[]{"a"}));
+        assertEvalFastR("a <- as.java.array('a'); java.class(a);", "'[Ljava.lang.String;'");
+        assertEvalFastR("a <- as.java.array(c('a', 'b')); a;", getRValue(new String[]{"a", "b"}));
+        assertEvalFastR("a <- as.java.array('a',,T); a;", getRValue(new String[]{"a"}));
+        assertEvalFastR("a <- as.java.array(c('a', 'b'),,T); a;", getRValue(new String[]{"a", "b"}));
+        assertEvalFastR("a <- as.java.array(c('a', 'b'),'java.lang.String',T); a;", getRValue(new String[]{"a", "b"}));
+
+        assertEvalFastR("a <- as.java.array(as.raw(1)); a", getRValue(new byte[]{1}));
+        assertEvalFastR("a <- as.java.array(as.raw(1)); java.class(a);", "'[B'");
+        assertEvalFastR("a <- as.java.array(as.raw(1)); length(a);", "1");
+        assertEvalFastR("a <- as.java.array(as.raw(c(1, 2, 3))); length(a);", "3");
+        assertEvalFastR("a <- as.java.array(as.raw(c(1, 2, 3))); java.class(a);", "'[B'");
+        assertEvalFastR("a <- as.java.array(as.raw(c(1, 2, 3)), 'int'); java.class(a);", "'[I'");
+
+        assertEvalFastR("a <- as.java.array(as.external.short(1)); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- as.java.array(as.external.short(1)); java.class(a);", "'[S'");
+        assertEvalFastR("a <- as.java.array(c(as.external.short(1), as.external.short(2))); a;", getRValue(new short[]{1, 2}));
+        assertEvalFastR("a <- as.java.array(as.external.short(1),,T); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- as.java.array(c(as.external.short(1), as.external.short(2)),,T); a;", getRValue(new short[]{1, 2}));
+        assertEvalFastR("a <- as.java.array(c(as.external.short(1), as.external.short(2)),'int',T); a;", getRValue(new int[]{1, 2}));
+
+        assertEvalFastR("a <- as.java.array(as.external.short(1), 'java.lang.Short'); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- as.java.array(c(as.external.short(1), as.external.short(2)), 'java.lang.Short'); a;", getRValue(new short[]{1, 2}));
+        assertEvalFastR("a <- as.java.array(as.external.short(1), 'java.lang.Short', T); a;", getRValue(new short[]{1}));
+        assertEvalFastR("a <- as.java.array(c(as.external.short(1), as.external.short(2)), 'java.lang.Short', T); a;", getRValue(new short[]{1, 2}));
+
+        assertEvalFastR("a <- as.java.array(c(as.external.short(1), as.external.short(2)), 'int'); a;", getRValue(new int[]{1, 2}));
+        assertEvalFastR("a <- as.java.array(c(1.123, 2.123), 'double'); a;", getRValue(new double[]{1.123, 2.123}));
+        assertEvalFastR("a <- as.java.array(as.external.short(1), 'double'); a;", getRValue(new double[]{1}));
+
+        assertEvalFastR("a <- as.java.array(1L); as.java.array(a);", getRValue(new int[]{1}));
+        assertEvalFastR("a <- as.java.array(1L); as.java.array(a,,T);", getRValue(new int[]{1}));
+
+        assertEvalFastR("a <- as.java.array(as.external.short(1)); as.java.array(a);", getRValue(new short[]{1}));
+
+        assertEvalFastR("tc <- new.java.class('" + TEST_CLASS + "'); to <- new.external(tc); a <- as.java.array(to); is.external.array(a)", "TRUE");
+        assertEvalFastR("tc <- new.java.class('" + TEST_CLASS + "'); to <- new.external(tc); a <- as.java.array(c(to, to)); is.external.array(a)", "TRUE");
+        assertEvalFastR("tc <- new.java.class('" + TEST_CLASS + "'); to <- new.external(tc); a <- as.java.array(c(to, to)); length(a)", "2");
+        assertEvalFastR("tc <- new.java.class('" + TEST_CLASS + "'); to <- new.external(tc); a <- as.java.array(c(to, to)); java.class(a);",
+                        "[Lcom.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass;");
+
+        assertEvalFastR("a <- as.java.array(1L,,F); a;", getRValue(new int[]{1}));
+    }
 
-        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short'); a;", getRValue(new short[]{1}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short'); a;", getRValue(new short[]{1, 2}));
-        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'java.lang.Short', T); a;", getRValue(new short[]{1}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'java.lang.Short', T); a;", getRValue(new short[]{1, 2}));
+    @Test
+    public void testArrayAsParameter() {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "ja <- as.java.array(c(1L, 2L, 3L), 'int'); to$isIntArray(ja)", "'" + (new int[1]).getClass().getName() + "'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "ja <- as.java.array(c(1L, 2L, 3L), 'java.lang.Integer'); to$isIntegerArray(ja)", "'" + (new Integer[1]).getClass().getName() + "'");
+    }
 
-        assertEvalFastR("a <- .fastr.java.toArray(c(.fastr.interop.toShort(1), .fastr.interop.toShort(2)), 'int'); a;", getRValue(new int[]{1, 2}));
-        assertEvalFastR("a <- .fastr.java.toArray(c(1.123, 2.123), 'double'); a;", getRValue(new double[]{1.123, 2.123}));
-        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1), 'double'); a;", getRValue(new double[]{1}));
+    @Test
+    public void testNewArray() {
+        testNewArray("java.lang.Boolean", true);
+        testNewArray("java.lang.Byte", true);
+        testNewArray("java.lang.Character", true);
+        testNewArray("java.lang.Double", true);
+        testNewArray("java.lang.Float", true);
+        testNewArray("java.lang.Integer", true);
+        testNewArray("java.lang.Long", true);
+        testNewArray("java.lang.Short", true);
+        testNewArray("java.lang.String", true);
+
+        testNewArray("boolean", true);
+        testNewArray("byte", true);
+        testNewArray("char", true);
+        testNewArray("double", true);
+        testNewArray("float", true);
+        testNewArray("int", true);
+        testNewArray("long", true);
+        testNewArray("short", true);
+
+        testNewArray("com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass", true);
+
+        // test also with double length/dimensions
+        testNewArray("java.lang.String", false);
+    }
 
-        assertEvalFastR("a <- .fastr.java.toArray(1L); .fastr.java.toArray(a);", getRValue(new int[]{1}));
-        assertEvalFastR("a <- .fastr.java.toArray(1L); .fastr.java.toArray(a,,T);", getRValue(new int[]{1}));
+    public void testNewArray(String className, boolean dimInt) {
+        String dim = dimInt ? "10L" : "10.9";
+        assertEvalFastR("a <- new.java.array('" + className + "', " + dim + "); is.external.array(a);", "TRUE");
+        assertEvalFastR("a <- new.java.array('" + className + "', " + dim + "); length(a);", "10");
+        assertEvalFastR("a <- new.java.array('" + className + "', " + dim + "); java.class(a);", toArrayClassName(className, 1));
+
+        dim = dimInt ? "c(2L, 3L)" : "c(2.9, 3.9)";
+        assertEvalFastR("a <- new.java.array('" + className + "', " + dim + "); is.external.array(a);", "TRUE");
+        assertEvalFastR("a <- new.java.array('" + className + "', " + dim + "); length(a);", "2L");
+        assertEvalFastR("a <- new.java.array('" + className + "', " + dim + "); length(a[1]);", "3L");
+        assertEvalFastR("a <- new.java.array('" + className + "', " + dim + "); java.class(a);", toArrayClassName(className, 2));
+    }
 
-        assertEvalFastR("a <- .fastr.java.toArray(.fastr.interop.toShort(1)); .fastr.java.toArray(a);", getRValue(new short[]{1}));
+    @Test
+    public void testGetClass() {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "java.class(to)", "'com.oracle.truffle.r.test.library.fastr.TestJavaInterop$TestClass'");
 
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(to); .fastr.java.isArray(a)", "TRUE");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- .fastr.interop.new(tc); a <- .fastr.java.toArray(c(to, to)); .fastr.java.isArray(a)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "java.class(to$methodReturnsNull())", errorIn("java.class(to$methodReturnsNull())", "unsupported type"));
+        assertEvalFastR("java.class(NULL)", errorIn("java.class(NULL)", "unsupported type"));
+        assertEvalFastR("java.class(1)", errorIn("java.class(1)", "unsupported type"));
+    }
 
-        assertEvalFastR(Ignored.Unimplemented, "a <- .fastr.java.toArray(1L,,F); a;", getRValue(new int[]{1}));
+    @Test
+    public void testAsVectorFromArray() {
+        testAsVectorFromArray("fieldStaticBooleanArray", "logical");
+        testAsVectorFromArray("fieldStaticByteArray", "integer");
+        testAsVectorFromArray("fieldStaticCharArray", "character");
+        testAsVectorFromArray("fieldStaticDoubleArray", "double");
+        testAsVectorFromArray("fieldStaticFloatArray", "double");
+        testAsVectorFromArray("fieldStaticIntegerArray", "integer");
+        testAsVectorFromArray("fieldStaticLongArray", "double");
+        testAsVectorFromArray("fieldStaticShortArray", "integer");
+        testAsVectorFromArray("fieldStaticStringArray", "character");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- as.vector(to$objectArray); is.list(v)", "TRUE");
+        testAsVectorFromArray("objectIntArray", "integer");
+        testAsVectorFromArray("objectDoubleArray", "double");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- as.vector(to$mixedTypesArray); is.list(v)", "TRUE");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- as.vector(to$hasNullIntArray); is.list(v)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- as.vector(to$hasNullIntArray); v[1]", "list(1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- as.vector(to$hasNullIntArray); v[2]", "list(NULL)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- as.vector(to$hasNullIntArray); v[3]", "list(3)");
     }
 
     @Test
     public void testFromArray() {
-        testFromArray("fieldStaticBooleanArray", "logical");
-        testFromArray("fieldStaticByteArray", "integer");
-        testFromArray("fieldStaticCharArray", "character");
-        testFromArray("fieldStaticDoubleArray", "double");
-        testFromArray("fieldStaticFloatArray", "double");
-        testFromArray("fieldStaticIntArray", "integer");
-        testFromArray("fieldStaticLongArray", "double");
-        testFromArray("fieldStaticShortArray", "integer");
-        testFromArray("fieldStaticStringArray", "character");
-
-        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$objectArray); is.list(v)", "TRUE");
-        testFromArray("objectIntArray", "integer");
-        testFromArray("objectDoubleArray", "double");
-        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$mixedTypesArray); is.list(v)", "TRUE");
-
-        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); is.list(v)", "TRUE");
-        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[1]", "list(1)");
-        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[2]", "list(NULL)");
-        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$hasNullIntArray); v[3]", "list(3)");
+        testAsVectorFromArray("fieldStaticBooleanArray", "logical");
+        testAsVectorFromArray("fieldStaticByteArray", "integer");
+        testAsVectorFromArray("fieldStaticCharArray", "character");
+        testAsVectorFromArray("fieldStaticDoubleArray", "double");
+        testAsVectorFromArray("fieldStaticFloatArray", "double");
+        testAsVectorFromArray("fieldStaticIntegerArray", "integer");
+        testAsVectorFromArray("fieldStaticLongArray", "double");
+        testAsVectorFromArray("fieldStaticShortArray", "integer");
+        testAsVectorFromArray("fieldStaticStringArray", "character");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- .fastr.interop.fromArray(to$objectArray); is.list(v)", "TRUE");
+        testAsVectorFromArray("objectIntArray", "integer");
+        testAsVectorFromArray("objectDoubleArray", "double");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- .fastr.interop.fromArray(to$mixedTypesArray); is.list(v)", "TRUE");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- .fastr.interop.fromArray(to$hasNullIntArray); is.list(v)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- .fastr.interop.fromArray(to$hasNullIntArray); v[1]", "list(1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- .fastr.interop.fromArray(to$hasNullIntArray); v[2]", "list(NULL)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- .fastr.interop.fromArray(to$hasNullIntArray); v[3]", "list(3)");
+
+        assertEvalFastR("ja <- new.java.array('java.lang.String', 0L); .fastr.interop.fromArray(ja)", "list()");
     }
 
-    public void testFromArray(String field, String type) {
-        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$" + field + "); is.vector(v)", "TRUE");
-        assertEvalFastR("t <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); v <- .fastr.java.fromArray(t$" + field + "); typeof(v)", getRValue(type));
+    public void testAsVectorFromArray(String field, String type) {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- as.vector(to$" + field + "); is.vector(v)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " v <- as.vector(to$" + field + "); typeof(v)", getRValue(type));
     }
 
     @Test
     public void testInteroptNew() {
-        assertEvalFastR("tc <- .fastr.java.class('" + Boolean.class.getName() + "'); t <- .fastr.interop.new(tc, TRUE); t", "TRUE");
-        assertEvalFastR("tc <- .fastr.java.class('java/lang/Boolean'); t <- new(tc, TRUE); t", "TRUE");
-        assertEvalFastR("tc <- .fastr.java.class('" + Byte.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toByte(1)); t", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + Character.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toChar(97)); t", "'a'");
-        assertEvalFastR("tc <- .fastr.java.class('" + Double.class.getName() + "'); t <- .fastr.interop.new(tc, 1.1); t", "1.1");
-        assertEvalFastR("tc <- .fastr.java.class('" + Float.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toFloat(1.1)); t", "1.1");
-        assertEvalFastR("tc <- .fastr.java.class('" + Integer.class.getName() + "'); t <- .fastr.interop.new(tc, 1L); t", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + Long.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toLong(1)); t", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + Short.class.getName() + "'); t <- .fastr.interop.new(tc, .fastr.interop.toShort(1)); t", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + String.class.getName() + "'); t <- .fastr.interop.new(tc, 'abc'); t", "'abc'");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestNullClass.class.getName() + "'); t <- .fastr.interop.new(tc, NULL); class(t)", "'" + RType.TruffleObject.getName() + "'");
+        assertEvalFastR("tc <- new.java.class('" + Boolean.class.getName() + "'); t <- new.external(tc, TRUE); t", "TRUE");
+        assertEvalFastR("tc <- new.java.class('java/lang/Boolean'); t <- new(tc, TRUE); t", "TRUE");
+        assertEvalFastR("tc <- new.java.class('" + Byte.class.getName() + "'); t <- new.external(tc, as.external.byte(1)); t", "1");
+        assertEvalFastR("tc <- new.java.class('" + Character.class.getName() + "'); t <- new.external(tc, as.external.char(97)); t", "'a'");
+        assertEvalFastR("tc <- new.java.class('" + Double.class.getName() + "'); t <- new.external(tc, 1.1); t", "1.1");
+        assertEvalFastR("tc <- new.java.class('" + Float.class.getName() + "'); t <- new.external(tc, as.external.float(1.1)); t", "1.1");
+        assertEvalFastR("tc <- new.java.class('" + Integer.class.getName() + "'); t <- new.external(tc, 1L); t", "1");
+        assertEvalFastR("tc <- new.java.class('" + Long.class.getName() + "'); t <- new.external(tc, as.external.long(1)); t", "1");
+        assertEvalFastR("tc <- new.java.class('" + Short.class.getName() + "'); t <- new.external(tc, as.external.short(1)); t", "1");
+        assertEvalFastR("tc <- new.java.class('" + String.class.getName() + "'); t <- new.external(tc, 'abc'); t", "'abc'");
+        assertEvalFastR("tc <- new.java.class('" + TestNullClass.class.getName() + "'); t <- new.external(tc, NULL); class(t)", "'" + RType.TruffleObject.getName() + "'");
     }
 
     @Test
     public void testNewWithJavaClass() {
-        assertEvalFastR("tc <- .fastr.java.class('" + Boolean.class.getName() + "'); to <- new(tc, TRUE); to", "TRUE");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); to <- new(tc); to$fieldInteger", getRValue(Integer.MAX_VALUE));
+        assertEvalFastR("tc <- new.java.class('" + Boolean.class.getName() + "'); to <- new(tc, TRUE); to", "TRUE");
+        assertEvalFastR("tc <- new.java.class('" + TEST_CLASS + "'); to <- new(tc); to$fieldInteger", getRValue(Integer.MAX_VALUE));
 
         assertEvalFastR("to <- new('" + Boolean.class.getName() + "', TRUE); to", "TRUE");
         assertEvalFastR("to <- new('java/lang/Boolean', TRUE); to", "TRUE");
         assertEvalFastR("to <- new('" + TEST_CLASS + "'); to$fieldStaticInteger", getRValue(Integer.MAX_VALUE));
 
-        assertEvalFastR("to <- new('" + TEST_CLASS + "'); new(to)", "cat('Error in .fastr.interop.new(Class, ...) : ', '\n', '  error during Java object instantiation\n', sep='')");
+        assertEvalFastR("to <- new('" + TEST_CLASS + "'); new(to)", errorIn("new.external(Class, ...)", "error during Java object instantiation"));
 
-        assertEvalFastR("to <- new('__bogus_class_name__');", "cat('Error in getClass(Class, where = topenv(parent.frame())) : ', '\n', '  “__bogus_class_name__” is not a defined class\n', sep='')");
+        assertEvalFastR("to <- new('__bogus_class_name__');", errorIn("getClass(Class, where = topenv(parent.frame()))", "“__bogus_class_name__” is not a defined class"));
     }
 
     @Test
     public void testCombineInteropTypes() {
-        assertEvalFastR("class(c(.fastr.interop.toByte(123)))", "'interopt.byte'");
-        assertEvalFastR("class(c(.fastr.interop.toByte(123), .fastr.interop.toByte(234)))", "'list'");
-        assertEvalFastR("class(c(.fastr.interop.toByte(123), 1))", "'list'");
-        assertEvalFastR("class(c(1, .fastr.interop.toByte(123)))", "'list'");
+        assertEvalFastR("class(c(as.external.byte(123)))", "'interopt.byte'");
+        assertEvalFastR("class(c(as.external.byte(123), as.external.byte(234)))", "'list'");
+        assertEvalFastR("class(c(as.external.byte(123), 1))", "'list'");
+        assertEvalFastR("class(c(1, as.external.byte(123)))", "'list'");
+    }
+
+    @Test
+    public void testCombineForeignObjects() throws IllegalAccessException, IllegalArgumentException {
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " class(c(to))", "'list'");
+        assertEvalFastR("tc <- new.java.class('" + TEST_CLASS + "'); t <- new.external(tc); t1 <- new.external(tc); class(c(t, t1))", "'list'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " class(c(1, t))", "'list'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " class(c(t, 1))", "'list'");
 
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(t))", "'truffle.object'");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t1 <- .fastr.interop.new(tc); class(c(t, t1))", "'list'");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(1, t))", "'list'");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); class(c(t, 1))", "'list'");
+        TestClass t = new TestClass();
+
+        testCombineForeignObjects("fieldBooleanArray", t.fieldBooleanArray);
+        testCombineForeignObjects("fieldByteArray", t.fieldByteArray);
+        testCombineForeignObjects("fieldCharArray", t.fieldCharArray);
+        testCombineForeignObjects("fieldDoubleArray", t.fieldDoubleArray);
+        testCombineForeignObjects("fieldFloatArray", t.fieldFloatArray);
+        testCombineForeignObjects("fieldIntegerArray", t.fieldIntegerArray);
+        testCombineForeignObjects("fieldLongArray", t.fieldLongArray);
+        testCombineForeignObjects("fieldShortArray", t.fieldShortArray);
+        testCombineForeignObjects("fieldStringArray", t.fieldStringArray);
+
+        testCombineForeignObjects("listBoolean", t.listBoolean);
+        testCombineForeignObjects("listByte", t.listByte);
+        testCombineForeignObjects("listChar", t.listChar);
+        testCombineForeignObjects("listDouble", t.listDouble);
+        testCombineForeignObjects("listFloat", t.listFloat);
+        testCombineForeignObjects("listInteger", t.listInteger);
+        testCombineForeignObjects("listLong", t.listLong);
+        testCombineForeignObjects("listShort", t.listShort);
+        testCombineForeignObjects("listString", t.listString);
+        testCombineForeignObjects("listStringInt", t.listStringInt);
+        testCombineForeignObjects("listStringBoolean", t.listStringBoolean);
+        testCombineForeignObjects("listEmpty", t.listEmpty);
+    }
+
+    private void testCombineForeignObjects(String field, Object fieldObject) {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " c(to$" + field + ")", toRVector(fieldObject, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " c(to$" + field + ", to$" + field + ")", c(fieldObject, fieldObject));
     }
 
     @Test
@@ -252,7 +393,7 @@ public class TestJavaInterop extends TestBase {
     }
 
     @Test
-    public void testMethods() throws IllegalAccessException, ClassNotFoundException, IllegalArgumentException, InvocationTargetException {
+    public void testMethods() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException {
         TestClass t = new TestClass();
         Method[] methods = t.getClass().getDeclaredMethods();
         for (Method m : methods) {
@@ -266,7 +407,7 @@ public class TestJavaInterop extends TestBase {
     }
 
     private void testForValue(String member, Object value) {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + member, getRValue(value));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$" + member, getRValue(value));
     }
 
     @Test
@@ -277,13 +418,13 @@ public class TestJavaInterop extends TestBase {
 
     @Test
     public void testNonPrimitiveParameter() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$equals(t)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$equals(to)", "TRUE");
     }
 
     @Test
     public void testClassAsParameter() {
         // fails in testdownstream
-        assertEvalFastR(Ignored.ImplementationError, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$classAsArg(tc)", getRValue(TEST_CLASS));
+        assertEvalFastR(Ignored.ImplementationError, CREATE_TRUFFLE_OBJECT + " to$classAsArg(new.java.class(" + TEST_CLASS + "))", getRValue(TEST_CLASS));
     }
 
     private void getValueForAllTypesMethod(String method) {
@@ -296,55 +437,103 @@ public class TestJavaInterop extends TestBase {
         double d = Double.MAX_VALUE;
         float f = Float.MAX_VALUE;
         String s = "testString";
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$" + method + "(" + getRValuesAsString(bo, bt, c, sh, i, l, d, f, s) + ")",
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$" + method + "(" + getRValuesAsString(bo, bt, c, sh, i, l, d, f, s) + ")",
                         getRValue("" + bo + bt + c + sh + i + l + d + f + s));
     }
 
     @Test
     public void testNullParameters() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$methodAcceptsOnlyNull(NULL)", "");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$methodAcceptsOnlyNull(NULL)", "");
 
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull('string')", "java.lang.String");
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isNull(1)", "java.lang.Long");
+        assertEvalFastR(Ignored.Unimplemented, CREATE_TRUFFLE_OBJECT + " to$isNull('string')", "java.lang.String");
+        assertEvalFastR(Ignored.Unimplemented, CREATE_TRUFFLE_OBJECT + " to$isNull(1)", "java.lang.Long");
     }
 
     @Test
     public void testOverloaded() {
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isOverloaded(TRUE)", "boolean");
-        assertEvalFastR(Ignored.Unimplemented, "tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$isOverloaded('string')", String.class.getName());
-        // TODO add remaining isOverloaded(...) calls once this is fixed
+        String className = TestOverload.class.getName();
+        String createClass = "toc <- new.java.class('" + className + "'); ";
+
+        assertEvalFastR(createClass + " toc$isOverloaded(TRUE)", "'boolean'");
+        assertEvalFastR(createClass + " toc$isOverloaded(as.external.byte(1))", "'byte'");
+        assertEvalFastR(createClass + " toc$isOverloaded(as.external.char('a'))", "'char'");
+        assertEvalFastR(createClass + " toc$isOverloaded(1)", "'double'");
+        assertEvalFastR(createClass + " toc$isOverloaded(as.external.float(1))", "'float'");
+        assertEvalFastR(createClass + " toc$isOverloaded(1L)", "'int'");
+        assertEvalFastR(createClass + " toc$isOverloaded(as.external.long(1))", "'long'");
+        assertEvalFastR(createClass + " toc$isOverloaded(as.external.short(1))", "'short'");
+        assertEvalFastR(createClass + " toc$isOverloaded('string')", getRValue(String.class.getName()));
+
+        assertEvalFastR("new('" + className + "', TRUE)$type", "'boolean'");
+        assertEvalFastR("new('" + className + "', as.external.byte(1))$type", "'byte'");
+        assertEvalFastR("new('" + className + "', as.external.char('a'))$type", "'char'");
+        assertEvalFastR("new('" + className + "', 1)$type", "'double'");
+        assertEvalFastR("new('" + className + "', as.external.float(1))$type", "'float'");
+        assertEvalFastR("new('" + className + "', 1L)$type", "'int'");
+        assertEvalFastR("new('" + className + "', as.external.long(1))$type", "'long'");
+        assertEvalFastR("new('" + className + "', as.external.short(1))$type", "'short'");
+        assertEvalFastR("new('" + className + "', 'string')$type", getRValue(String.class.getName()));
     }
 
     @Test
     public void testArrayReadWrite() {
-        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[1]", "1");
-        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[[1]]", "1");
+        assertEvalFastR("a <- as.java.array(c(1,2,3)); a[1]", "1");
+        assertEvalFastR("a <- as.java.array(c(1,2,3)); a[[1]]", "1");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$fieldIntegerArray[1];", "1");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$fieldIntegerArray[[1]];", "1");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$int2DimArray[1]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$int2DimArray[[1]]", getRValue(new int[]{1, 2, 3}));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$int2DimArray[1,2]", "2");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$int2DimArray[[1,2]]", "2");
 
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[1];", "1");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]];", "1");
+        assertEvalFastR("a <- as.java.array(c(1,2,3)); a[1] <- 123; a[1]", "123");
+        assertEvalFastR("a <- as.java.array(c(1,2,3)); a[[1]] <- 123; a[[1]]", "123");
 
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1]", getRValue(new int[]{1, 2, 3}));
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1]]", getRValue(new int[]{1, 2, 3}));
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2]", "2");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]]", "2");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$fieldIntegerArray[1] <- 123L; to$fieldIntegerArray[1]", "123");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$fieldIntegerArray[[1]] <- 1234L; to$fieldIntegerArray[[1]]", "1234");
 
-        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[1] <- 123; a[1]", "123");
-        assertEvalFastR("a <- .fastr.java.toArray(c(1,2,3)); a[[1]] <- 123; a[[1]]", "123");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$fieldStringArray[1] <- NULL; to$fieldStringArray[1]", "NULL");
 
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[1] <- 123L; t$fieldIntArray[1]", "123");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldIntArray[[1]] <- 1234L; t$fieldIntArray[[1]]", "1234");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$int2DimArray[1,2] <- 1234L; to$int2DimArray[1,2]", "1234");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$int2DimArray[[1,2]] <- 12345L; to$int2DimArray[[1,2]]", "12345");
+    }
+
+    @Test
+    public void testReadByVector() {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$fieldStringArray[c(1, 3)]", "c('a', 'c')");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to$map[c('one', 'three')]", "c('1', '3')");
+
+        TestClass tc = new TestClass();
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to[c('fieldStringObject', 'fieldChar')]", "c('" + tc.fieldStringObject + "', '" + tc.fieldChar + "')");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " to[c('fieldStringObject', 'fieldInteger')]", "list('" + tc.fieldStringObject + "', " + tc.fieldInteger + ")");
+    }
+
+    @Test
+    public void testLengthArray() {
+        TestArraysClass ta = new TestArraysClass();
+        assertEvalFastR(CREATE_TEST_ARRAYS + " length(ta$objectEmpty)", "" + ta.objectEmpty.length);
 
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$fieldStringArray[1] <- NULL; t$fieldStringArray[1]", "NULL");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " length(ta$booleanArray)", "" + ta.booleanArray.length);
+        assertEvalFastR(CREATE_TEST_ARRAYS + " length(ta$booleanArray2)", "" + ta.booleanArray2.length);
+        assertEvalFastR(CREATE_TEST_ARRAYS + " length(ta$booleanArray3)", "" + ta.booleanArray3.length);
+    }
 
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[1,2] <- 1234L; t$int2DimArray[1,2]", "1234");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); t$int2DimArray[[1,2]] <- 12345L; t$int2DimArray[[1,2]]", "12345");
+    @Test
+    public void testLengthIterable() {
+        String thisFQN = this.getClass().getName();
+        for (String s : new String[]{"Size", "GetSize", "Length", "GetLength", "NoSizeMethod"}) {
+            String clazz = thisFQN + "$TestIterable" + s;
+            assertEvalFastR("ti <- new('" + clazz + "', 123); length(ti)", "123");
+        }
     }
 
     public void testMap() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['one']", "'1'");
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['two']", "'2'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " m <- to$map; m['one']", "'1'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " m <- to$map; m['two']", "'2'");
 
-        assertEvalFastR("tc <- .fastr.java.class('" + TEST_CLASS + "'); t <- .fastr.interop.new(tc); m <- t$map; m['one']<-'11'; m['one']", "'11'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " m <- to$map; m['one']<-'11'; m['one']", "'11'");
 
         // truffle
         assertEvalFastR(Ignored.Unimplemented, "how to put into map?", "'11'");
@@ -352,14 +541,31 @@ public class TestJavaInterop extends TestBase {
 
     @Test
     public void testNamesForForeignObject() {
-        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassNoMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassNoPublicMembers.class.getName() + "'); t <- .fastr.interop.new(tc); names(t)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); sort(names(tc))", "c('staticField', 'staticMethod')");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticField)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticMethod)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClass.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t))", "c('field', 'method', 'staticField', 'staticMethod')");
-        assertEvalFastR("cl <- .fastr.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em)", "NULL");
-        assertEvalFastR("tc <- .fastr.java.class('" + TestNamesClassMap.class.getName() + "'); t <- .fastr.interop.new(tc); sort(names(t$m()))", "c('one', 'two')");
+        assertEvalFastR("tc <- new.java.class('" + TestNamesClassNoMembers.class.getName() + "'); t <- new.external(tc); names(t)", "NULL");
+        assertEvalFastR("tc <- new.java.class('" + TestNamesClassNoPublicMembers.class.getName() + "'); t <- new.external(tc); names(t)", "NULL");
+        assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); sort(names(tc))", "c('staticField', 'staticMethod')");
+        assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticField)", "NULL");
+        assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); names(tc$staticMethod)", "NULL");
+        assertEvalFastR("tc <- new.java.class('" + TestNamesClass.class.getName() + "'); t <- new.external(tc); sort(names(t))", "c('field', 'method', 'staticField', 'staticMethod')");
+        // Note: The following two tests fails on Solaris. It seems that the Java interop on
+        // Solaris treats the two inner classes SimpleImmutableEntry and SimpleEntry of
+        // java.util.AbstractMap as if they were members.
+        assertEvalFastR(Ignored.Unstable, "cl <- new.java.class('java.util.Collections'); em<-cl$EMPTY_MAP; names(em)", "NULL");
+        assertEvalFastR(Ignored.Unstable, "tc <- new.java.class('" + TestNamesClassMap.class.getName() + "'); to <- new.external(tc); sort(names(to$m()))", "c('one', 'two')");
+    }
+
+    @Test
+    public void testIsExternalExecutable() {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.executable(to)", "FALSE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.executable(to$methodBoolean)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.executable(to$fieldBoolean)", "FALSE");
+    }
+
+    @Test
+    public void testIsExternalNull() {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.null(to)", "FALSE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.null(to$methodReturnsNull)", "FALSE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "is.external.null(to$methodReturnsNull())", "TRUE");
     }
 
     @Test
@@ -409,30 +615,673 @@ public class TestJavaInterop extends TestBase {
         assertPassingForeighObjectToFunction("is.unsorted", "FALSE");
         assertPassingForeighObjectToFunction("is.vector", "FALSE");
 
-        assertPassingForeighObjectToFunction("is.nan", "cat('Error in is.nan(to) : ', '\n', '  default method not implemented for type \\'external object\\'\n', sep='')");
-        assertPassingForeighObjectToFunction("is.finite", "cat('Error in is.finite(to) : ', '\n', '  default method not implemented for type \\'external object\\'\n', sep='')");
-        assertPassingForeighObjectToFunction("is.infinite", "cat('Error in is.infinite(to) : ', '\n', '  default method not implemented for type \\'external object\\'\n', sep='')");
+        assertPassingForeighObjectToFunction("is.nan", errorIn("is.nan(to)", "default method not implemented for type 'external object'"));
+        assertPassingForeighObjectToFunction("is.finite", errorIn("is.finite(to)", "default method not implemented for type 'external object'"));
+        assertPassingForeighObjectToFunction("is.infinite", errorIn("is.infinite(to)", "default method not implemented for type 'external object'"));
 
     }
 
     private void assertPassingForeighObjectToFunction(String function, String expectedOutput) {
-        assertEvalFastR("to <- .fastr.interop.new(.fastr.java.class('" + TEST_CLASS + "')); " + function + "(to)", expectedOutput);
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " " + function + "(to)", expectedOutput);
+    }
+
+    @Test
+    public void testAddToList() {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l <- list(to); is.list(l)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l <- list();  l$foreignobject <- to; identical(to, l$foreignobject)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l <- list(1); l$foreignobject <- to; identical(to, l$foreignobject)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l <- list(1); l$foreignobject <- 1; l$foreignobject <- to; identical(to, l$foreignobject)", "TRUE");
     }
 
     @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')");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " attributes(to)", "NULL");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " attr(to, 'a')<-'a'", errorIn("attr(to, \"a\") <- \"a\"", "external object cannot be attributed"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " attr(to, which = 'a')", errorIn("attr(to, which = \"a\")", "external object cannot be attributed"));
     }
 
+    @Test
     public void testIdentical() {
-        assertEvalFastR("b1 <- .fastr.interop.toByte(1); identical(b1, b1)", "TRUE");
-        assertEvalFastR("b1 <- .fastr.interop.toByte(1); b2 <- .fastr.interop.toByte(1); identical(b1, b2)", "FALSE");
-        assertEvalFastR("b1 <- .fastr.interop.toByte(1); s1 <- .fastr.interop.toShort(1); identical(b1, s1)", "FALSE");
+        assertEvalFastR("b1 <- as.external.byte(1); identical(b1, b1)", "TRUE");
+        assertEvalFastR("b1 <- as.external.byte(1); b2 <- as.external.byte(1); identical(b1, b2)", "FALSE");
+        assertEvalFastR("b1 <- as.external.byte(1); s1 <- as.external.short(1); identical(b1, s1)", "FALSE");
+
+        assertEvalFastR("al <- new.external(new.java.class('java.util.ArrayList')); identical(t, t)", "TRUE");
+        assertEvalFastR("ll <- new.external(new.java.class('java.util.LinkedList')); al <- new.external(new.java.class('java.util.ArrayList')); identical(al, ll)", "FALSE");
+    }
+
+    @Test
+    public void testAsList() {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listString); is.list(l)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listString); l[[1]]", "'a'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listString); l[[2]]", "'b'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listString); length(l)", "3");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listObject); is.list(l)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listObject); l[[1]]$data", "'a'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listObject); l[[2]]$data", "'b'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listObject); length(l)", "4");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$listObject); l[[4]]$data", "NULL");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$fieldStringArray); is.list(l)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$fieldStringArray); l[[1]]", "'a'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$fieldStringArray); l[[2]]", "'b'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$fieldStringArray); length(l)", "3");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$arrayObject); is.list(l)", "TRUE");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$arrayObject); l[[1]]$data", "'a'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$arrayObject); l[[2]]$data", "'b'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$arrayObject); length(l)", "4");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " l<-as.list(to$arrayObject); l[[4]]$data", "NULL");
+
+        assertEvalFastR(Output.IgnoreErrorContext, CREATE_TRUFFLE_OBJECT + " l<-as.list(to);", errorIn("as.list(to)", "no method for coercing this external object to a list"));
+    }
+
+    private static final String CREATE_TEST_ARRAYS = "ta <- new('" + TestArraysClass.class.getName() + "');";
+
+    @Test
+    public void testUnlist() throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
+
+        assertEvalFastR(CREATE_TEST_ARRAYS + " tal <- unlist(ta); identical(ta, tal)", "TRUE");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " l<-list(ta, ta); ul <- unlist(l); identical(l, ul)", "TRUE");
+
+        // arrays
+        testUnlistByType("string", "'a', 'b', 'c'", "character");
+        testUnlistByType("boolean", "TRUE, FALSE, TRUE", "logical");
+        testUnlistByType("byte", "1, 2, 3", "integer");
+        testUnlistByType("char", "'a', 'b', 'c'", "character");
+        testUnlistByType("double", "1.1, 1.2, 1.3", "numeric");
+        testUnlistByType("float", "1.1, 1.2, 1.3", "numeric");
+        testUnlistByType("integer", "1, 2, 3", "integer");
+        testUnlistByType("long", "1, 2, 3", "numeric");
+        testUnlistByType("short", "1, 2, 3", "integer");
+
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$onlyIntegerObjectArray)", "c(1, 2, 3)");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(ta$onlyIntegerObjectArray))", "'integer'");
+
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$onlyLongObjectArray)", "c(1, 2, 3)");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(ta$onlyLongObjectArray))", "'numeric'");
+
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$mixedObjectArray)", "c('1', 'a', '1')");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(ta$mixedObjectArray))", "'character'");
+
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$mixedIntegerList)", "c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(ta$mixedIntegerList))", "'integer'");
+
+        testForeingObjectInListUnlist("byte", new String[]{"TRUE", "FALSE", "TRUE"}, "integer");
+        testForeingObjectInListUnlist("byte", new String[]{"1L", "2L", "3L"}, "integer");
+        testForeingObjectInListUnlist("byte", new String[]{"1.1", "2.1", "3.1"}, "numeric");
+        testForeingObjectInListUnlist("byte", new String[]{"'a'", "'aa'", "'aaa'"}, "character");
+
+        testForeingObjectInListUnlist("boolean", new String[]{"TRUE", "FALSE", "TRUE"}, "logical");
+        testForeingObjectInListUnlist("boolean", new String[]{"1L", "2L", "3L"}, "integer");
+        testForeingObjectInListUnlist("boolean", new String[]{"1.1", "1.2", "1.3"}, "numeric");
+        testForeingObjectInListUnlist("boolean", new String[]{"'a'", "'aa'", "'aaa'"}, "character");
+
+        testForeingObjectInListUnlist("double", new String[]{"TRUE", "FALSE", "TRUE"}, "numeric");
+        testForeingObjectInListUnlist("double", new String[]{"1L", "2L", "3L"}, "numeric");
+        testForeingObjectInListUnlist("double", new String[]{"1.1", "2.1", "3.1"}, "numeric");
+        testForeingObjectInListUnlist("double", new String[]{"'a'", "'aa'", "'aaa'"}, "character");
+
+        testForeingObjectInListUnlist("float", new String[]{"TRUE", "FALSE", "TRUE"}, "numeric");
+        testForeingObjectInListUnlist("float", new String[]{"1L", "2L", "3L"}, "numeric");
+        testForeingObjectInListUnlist("float", new String[]{"1.1", "2.1", "3.1"}, "numeric");
+        testForeingObjectInListUnlist("float", new String[]{"'a'", "'aa'", "'aaa'"}, "character");
+
+        testForeingObjectInListUnlist("integer", new String[]{"TRUE", "FALSE", "TRUE"}, "integer");
+        testForeingObjectInListUnlist("integer", new String[]{"1L", "2L", "3L"}, "integer");
+        testForeingObjectInListUnlist("integer", new String[]{"1.1", "1.2", "1.3"}, "numeric");
+        testForeingObjectInListUnlist("integer", new String[]{"'a'", "'aa'", "'aaa'"}, "character");
+
+        testForeingObjectInListUnlist("long", new String[]{"TRUE", "FALSE", "TRUE"}, "numeric");
+        testForeingObjectInListUnlist("long", new String[]{"1L", "2L", "3L"}, "numeric");
+        testForeingObjectInListUnlist("long", new String[]{"1.1", "1.2", "1.3"}, "numeric");
+        testForeingObjectInListUnlist("long", new String[]{"'a'", "'aa'", "'aaa'"}, "character");
+
+        testForeingObjectInListUnlist("short", new String[]{"TRUE", "FALSE", "TRUE"}, "integer");
+        testForeingObjectInListUnlist("short", new String[]{"1L", "2L", "3L"}, "integer");
+        testForeingObjectInListUnlist("short", new String[]{"1.1", "1.2", "1.3"}, "numeric");
+        testForeingObjectInListUnlist("short", new String[]{"'a'", "'aa'", "'aaa'"}, "character");
+
+        testForeingObjectInListUnlist("string", new String[]{"TRUE", "FALSE", "TRUE"}, "character");
+        testForeingObjectInListUnlist("string", new String[]{"1L", "2L", "3L"}, "character");
+        testForeingObjectInListUnlist("string", new String[]{"1.1", "1.2", "1.3"}, "character");
+        testForeingObjectInListUnlist("string", new String[]{"'a'", "'aa'", "'aaa'"}, "character");
+    }
+
+    private void testUnlistByType(String fieldType, String result, String clazz) {
+        testForeingObjectUnlist(fieldType + "Array", result, clazz);
+        if (!fieldType.equals("string")) {
+            testForeingObjectUnlist(fieldType + "ObjectArray", result, clazz);
+        }
+        testForeingObjectUnlist(fieldType + "List", result, clazz);
+    }
+
+    private void testForeingObjectUnlist(String fieldPrefix, String result, String clazz) {
+        String field = fieldPrefix;
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$" + field + ")", "c(" + result + ")");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(ta$" + field + "))", "'" + clazz + "'");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$" + field + ", recursive=FALSE)", "c(" + result + ")");
+
+        field = fieldPrefix + "2";
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$" + field + ")", "c(" + result + ", " + result + ")");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(ta$" + field + "))", "'" + clazz + "'");
+
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$" + field + ", recursive=FALSE)", "list(" + result + ", " + result + "))");
+
+        field = fieldPrefix + "3";
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$" + field + ")", "c(" + result + ", " + result + ", " + result + ", " + result + "))");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(ta$" + field + "))", "'" + clazz + "'");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(ta$" + field + ", recursive=FALSE)",
+                        "cat('[[1]]','\n','[external object]','\n\n','[[2]]','\n','[external object]','\n\n','[[3]]','\n','[external object]','\n\n','[[4]]','\n','[external object]','\n\n', sep='')");
 
-        assertEvalFastR("al <- .fastr.interop.new(.fastr.java.class('java.util.ArrayList')); identical(t, t)", "TRUE");
-        assertEvalFastR("ll <- .fastr.interop.new(.fastr.java.class('java.util.LinkedList')); al <- .fastr.interop.new(.fastr.java.class('java.util.ArrayList')); identical(al, ll)", "FALSE");
+    }
+
+    private void testForeingObjectInListUnlist(String field, String[] toMixWith, String clazz) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
+        StringBuilder sbToVector = new StringBuilder();
+        StringBuilder sbVector = new StringBuilder();
+        StringBuilder sbList = new StringBuilder();
+        int i = 0;
+        sbToVector.append("c(");
+        for (String s : toMixWith) {
+            sbVector.append(s);
+            String mwv = toMixWith[i];
+            if (mwv.endsWith("L")) {
+                mwv = mwv.replace("L", "");
+            }
+            mwv = mwv.replace("'", "\"");
+            sbList.append("'[[").append(++i).append("]]','\n','").append("[1] ").append(mwv).append("','\n\n',");
+            sbToVector.append(s);
+            if (i < toMixWith.length) {
+                sbVector.append(", ");
+                sbToVector.append(", ");
+            }
+        }
+        sbToVector.append(")");
+
+        String mixWithVector = sbToVector.toString();
+        String resultInVector = sbVector.toString();
+        String resultInList = sbList.toString();
+        String testFieldArrayResult = getTestFieldValuesAsResult(field + "Array");
+        String testFieldListResult = getTestFieldValuesAsResult(field + "List");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(list(" + mixWithVector + ", ta$" + field + "Array, ta$" + field + "List))",
+                        "c(" + resultInVector + ", " + testFieldArrayResult + ", " + testFieldListResult + ")");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(list(" + mixWithVector + ", ta$" + field + "Array, ta$" + field + "List)))", "'" + clazz + "'");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(list(" + mixWithVector + ", ta$" + field + "Array, ta$" + field + "List), recursive=FALSE)",
+                        "c(" + resultInVector + ", " + testFieldArrayResult + ", " + testFieldListResult + ")");
+
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(list(" + mixWithVector + ", ta$" + field + "Array2, ta$" + field + "List2))",
+                        "c(" + resultInVector + ", " + testFieldArrayResult + ", " + testFieldArrayResult + ", " + testFieldListResult + ", " + testFieldListResult + ")");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(list(" + mixWithVector + ", ta$" + field + "Array2, ta$" + field + "List2)))", "'" + clazz + "'");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(list(" + mixWithVector + ", ta$" + field + "Array2, ta$" + field + "List2), recursive=FALSE)",
+                        "cat(" + resultInList +
+                                        "'[[4]]','\n','[external object]','\n\n','[[5]]','\n','[external object]','\n\n','[[6]]','\n','[external object]','\n\n','[[7]]','\n','[external object]','\n\n', sep='')");
+
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(list(" + mixWithVector + ", ta$" + field + "Array3, ta$" + field + "List3))",
+                        "c(" + resultInVector + ", " + testFieldArrayResult + ", " + testFieldArrayResult + ", " + testFieldArrayResult + ", " + testFieldArrayResult + ", " + testFieldListResult +
+                                        ", " + testFieldListResult + ", " + testFieldListResult + ", " + testFieldListResult + ")");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " class(unlist(list(" + mixWithVector + ", ta$" + field + "Array3, ta$" + field + "List3)))", "'" + clazz + "'");
+        assertEvalFastR(CREATE_TEST_ARRAYS + " unlist(list(" + mixWithVector + ", ta$" + field + "Array3, ta$" + field + "List3), recursive=FALSE)",
+                        "cat(" + resultInList +
+                                        "'[[4]]','\n','[external object]','\n\n','[[5]]','\n','[external object]','\n\n','[[6]]','\n','[external object]','\n\n','[[7]]','\n','[external object]','\n\n', sep='')");
+    }
+
+    private static String getTestFieldValuesAsResult(String name) throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
+        TestArraysClass ta = new TestArraysClass();
+        Field f = ta.getClass().getDeclaredField(name);
+        Object value = f.get(ta);
+        if (value instanceof List) {
+            List<?> l = (List<?>) value;
+            value = l.toArray(new Object[l.size()]);
+        }
+        StringBuilder sb = new StringBuilder();
+        int length = Array.getLength(value);
+        for (int i = 0; i < length; i++) {
+            Object object = Array.get(value, i);
+            if (object instanceof String || object instanceof Character) {
+                sb.append("'");
+            }
+            if (object instanceof Boolean) {
+                sb.append(Boolean.toString((boolean) object).toUpperCase());
+            } else if (object instanceof Float) {
+                sb.append((double) ((float) object));
+            } else {
+                sb.append(object);
+            }
+            if (object instanceof String || object instanceof Character) {
+                sb.append("'");
+            }
+            if (i < length - 1) {
+                sb.append(", ");
+            }
+        }
+        return sb.toString();
+    }
+
+    @Test
+    public void testConvertEmptyList() throws IllegalArgumentException {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "as.character(to$listEmpty);", "as.character(list())");
+    }
+
+    @Test
+    public void testAsXXX() throws IllegalArgumentException, IllegalAccessException {
+        testAsXXX("as.character", "character");
+        testAsXXX("as.complex", "complex");
+        testAsXXX("as.double", "double");
+        testAsXXX("as.expression", "expression");
+        testAsXXX("as.integer", "integer");
+        testAsXXX("as.logical", "logical");
+        testAsXXX("as.raw", "raw");
+        testAsXXX("as.symbol", "symbol");
+        testAsXXX("as.vector", null);
+        // TODO more tests
+    }
+
+    public void testAsXXX(String asXXX, String type) throws IllegalArgumentException, IllegalAccessException {
+        TestClass t = new TestClass();
+
+        Field[] fields = t.getClass().getDeclaredFields();
+        for (Field f : fields) {
+            String name = f.getName();
+            String expr = CREATE_TRUFFLE_OBJECT + asXXX + "(to$" + name + ")";
+            // test for each primitive wrapper object and string
+            if (name.startsWith("fieldStatic") && name.endsWith("Object")) {
+                if (asXXX.equals("as.character") && name.contains("Long")) {
+                    assertEvalFastR(Ignored.ImplementationError, expr, getAsXXX(f.get(t), asXXX));
+                } else if (!(asXXX.equals("as.character") || asXXX.equals("as.expression") || asXXX.equals("as.logical") || asXXX.equals("as.symbol") || asXXX.equals("as.vector")) &&
+                                (name.contains("String") || name.contains("Char"))) {
+                    assertEvalFastR(Output.IgnoreWarningMessage, expr, getAsXXX(f.get(t), asXXX));
+                } else if (asXXX.equals("as.expression") && (name.contains("Long") || name.contains("Double"))) {
+                    assertEvalFastR(Ignored.ImplementationError, expr, getAsXXX(f.get(t), asXXX));
+                } else if (asXXX.equals("as.raw") && (name.contains("Short") || name.contains("Integer") || name.contains("Long") || name.contains("Double") || name.contains("NaN"))) {
+                    assertEvalFastR(Output.IgnoreWarningMessage, expr, getAsXXX(f.get(t), asXXX));
+                } else if (asXXX.equals("as.symbol") && (name.contains("Long") || name.contains("Double") || name.contains("Float"))) {
+                    assertEvalFastR(Ignored.ImplementationError, expr, getAsXXX(f.get(t), asXXX));
+                } else if (asXXX.equals("as.symbol") && (name.contains("Null"))) {
+                    assertEvalFastR(Output.IgnoreErrorContext, expr, getAsXXX(f.get(t), asXXX));
+                } else {
+                    assertEvalFastR(expr, getAsXXX(f.get(t), asXXX));
+                }
+            }
+        }
+
+        // test arrays
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldBooleanArray);", toRVector(t.fieldBooleanArray, asXXX));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldByteArray);", toRVector(t.fieldByteArray, asXXX));
+        if (!(asXXX.equals("as.character") || asXXX.equals("as.expression") || asXXX.equals("as.logical") || asXXX.equals("as.symbol") || asXXX.equals("as.vector"))) {
+            assertEvalFastR(Output.IgnoreWarningMessage, CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldCharArray);", toRVector(t.fieldCharArray, asXXX));
+        } else {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldCharArray);", toRVector(t.fieldCharArray, asXXX));
+        }
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldDoubleArray);", toRVector(t.fieldDoubleArray, asXXX));
+        if (asXXX.equals("as.symbol")) {
+            assertEvalFastR(Ignored.ImplementationError, CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldFloatArray);", toRVector(t.fieldFloatArray, asXXX));
+        } else {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldFloatArray);", toRVector(t.fieldFloatArray, asXXX));
+        }
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldIntegerArray);", toRVector(t.fieldIntegerArray, asXXX));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldLongArray);", toRVector(t.fieldLongArray, asXXX));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldShortArray);", toRVector(t.fieldShortArray, asXXX));
+        if (!(asXXX.equals("as.character") || asXXX.equals("as.expression") || asXXX.equals("as.logical") || asXXX.equals("as.symbol") || asXXX.equals("as.vector"))) {
+            assertEvalFastR(Output.IgnoreWarningMessage, CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldStringArray);", toRVector(t.fieldStringArray, asXXX));
+        } else {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldStringArray);", toRVector(t.fieldStringArray, asXXX));
+        }
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldStringIntArray);", toRVector(t.fieldStringIntArray, asXXX));
+        if (!(asXXX.equals("as.complex") || asXXX.equals("as.integer") || asXXX.equals("as.raw") || asXXX.equals("as.double"))) {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldStringBooleanArray);", toRVector(t.fieldStringBooleanArray, asXXX));
+        } else {
+            assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + asXXX + "(to$fieldStringBooleanArray);", toRVector(t.fieldStringBooleanArray, asXXX));
+        }
+
+        // tests lists
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listBoolean);", toRVector(t.listBoolean, asXXX));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listByte);", toRVector(t.listByte, asXXX));
+        if (!(asXXX.equals("as.character") || asXXX.equals("as.expression") || asXXX.equals("as.logical") || asXXX.equals("as.symbol") || asXXX.equals("as.vector"))) {
+            assertEvalFastR(Output.IgnoreWarningMessage, CREATE_TRUFFLE_OBJECT + asXXX + "(to$listChar);", toRVector(t.listChar, asXXX));
+        } else {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listChar);", toRVector(t.listChar, asXXX));
+        }
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listDouble);", toRVector(t.listDouble, asXXX));
+        if (asXXX.equals("as.symbol")) {
+            assertEvalFastR(Ignored.ImplementationError, CREATE_TRUFFLE_OBJECT + asXXX + "(to$listFloat);", toRVector(t.listFloat, asXXX));
+        } else {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listFloat);", toRVector(t.listFloat, asXXX));
+        }
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listInteger);", toRVector(t.listInteger, asXXX));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listLong);", toRVector(t.listLong, asXXX));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listShort);", toRVector(t.listShort, asXXX));
+        if (!(asXXX.equals("as.character") || asXXX.equals("as.expression") || asXXX.equals("as.logical") || asXXX.equals("as.symbol") || asXXX.equals("as.vector"))) {
+            assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + asXXX + "(to$listString);", toRVector(t.listString, asXXX));
+        } else {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listString);", toRVector(t.listString, asXXX));
+        }
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listStringInt);", toRVector(t.listStringInt, asXXX));
+        if (!(asXXX.equals("as.complex") || asXXX.equals("as.integer") || asXXX.equals("as.raw") || asXXX.equals("as.double"))) {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to$listStringBoolean);", toRVector(t.listStringBoolean, asXXX));
+        } else {
+            assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + asXXX + "(to$listStringBoolean);", toRVector(t.listStringBoolean, asXXX));
+        }
+
+        if (asXXX.equals("as.expression")) {
+            assertEvalFastR(Output.IgnoreErrorContext, CREATE_TRUFFLE_OBJECT + asXXX + "(to);", errorIn(asXXX + "(to)", "no method for coercing this external object to a vector"));
+        } else if (asXXX.equals("as.raw") || asXXX.equals("as.complex")) {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to);", errorIn(asXXX + "(to)", "cannot coerce type 'truffleobject' to vector of type '" + type + "'"));
+        } else {
+            assertEvalFastR(CREATE_TRUFFLE_OBJECT + asXXX + "(to);", errorIn(asXXX + "(to)", "no method for coercing this external object to a vector"));
+        }
+    }
+
+    @Test
+    public void testIf() throws IllegalArgumentException {
+        TestClass t = new TestClass();
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "if(to$fieldBoolean) print('OK')", "if(T) print('OK')");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "if(to$fieldInteger) print('OK')", "if(1) print('OK')");
+
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "if(to$fieldBooleanArray) print('OK')", "if(c(T, F)) print('OK')");
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "if(to$fieldIntegerArray) print('OK')", "if(c(T, F)) print('OK')");
+        assertEvalFastR(Output.IgnoreWarningContext, Output.IgnoreErrorContext, CREATE_TRUFFLE_OBJECT + "if(to$fieldStringArray) print('OK')", "if(c('a', 'b')) print('OK')");
+
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "if(to$fieldStringBooleanArray) print('OK')", "if(c('TRUE', 'TRUE', 'FALSE')) print('OK')");
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "if(to$listBoolean) print('OK')", "if(c(T, F)) print('OK')");
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "if(to$listInteger) print('OK')", "if(c(T, F)) print('OK')");
+        assertEvalFastR(Output.IgnoreErrorContext, CREATE_TRUFFLE_OBJECT + "if(to$listString) print('OK')", "if(c('A', 'B')) print('OK')");
+
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "if(to$listStringBoolean) print('OK')", "if(" + toRVector(t.listStringBoolean, null) + ") print('OK')");
+
+        assertEvalFastR(Output.IgnoreErrorContext, CREATE_TRUFFLE_OBJECT + "if(to) print('OK')", errorIn("if (T) print('OK')", " argument is not interpretable as logical"));
+    }
+
+    @Test
+    public void testWhile() throws IllegalArgumentException {
+        TestClass t = new TestClass();
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "while(to$fieldBoolean) {print('OK'); break;}", "while(T) {print('OK'); break;}");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "while(to$fieldInteger) {print('OK'); break;}", "while(1) {print('OK'); break;}");
+
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "while(to$fieldBooleanArray) {print('OK'); break;}", "while(c(T, F)) {print('OK'); break;}");
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "while(to$fieldIntegerArray) {print('OK'); break;}", "while(c(T, F)) {print('OK'); break;}");
+        assertEvalFastR(Output.IgnoreWarningContext, Output.IgnoreErrorContext, CREATE_TRUFFLE_OBJECT + "if(to$fieldStringArray) {print('OK'); break;}", "while(c('a', 'b')) {print('OK'); break;}");
+
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "while(to$fieldStringBooleanArray) {print('OK'); break;}", "while(c('TRUE', 'TRUE', 'FALSE')) {print('OK'); break;}");
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "while(to$listBoolean) {print('OK'); break;}", "while(c(T, F)) {print('OK'); break;}");
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "while(to$listInteger) {print('OK'); break;}", "while(c(T, F)) {print('OK'); break;}");
+        assertEvalFastR(Output.IgnoreErrorContext, CREATE_TRUFFLE_OBJECT + "while(to$listString) {print('OK'); break;}",
+                        "while(c('A', 'B')) {print('OK'); break;}");
+
+        assertEvalFastR(Output.IgnoreWarningContext, CREATE_TRUFFLE_OBJECT + "while(to$listStringBoolean) {print('OK'); break;}",
+                        "while(" + toRVector(t.listStringBoolean, null) + ") {print('OK'); break;}");
+
+        assertEvalFastR(Output.IgnoreErrorContext, CREATE_TRUFFLE_OBJECT + "while(to) print('OK')", errorIn("if (T) print('OK')", " argument is not interpretable as logical"));
+    }
+
+    @Test
+    public void testForeignVectorArithmeticOp() throws NoSuchFieldException,
+                    IllegalAccessException {
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldBooleanArray", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldByteArray", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldDoubleArray", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldFloatArray", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldIntegerArray", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldLongArray", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldShortArray", false);
+
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listBoolean", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listByte", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listDouble", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listFloat", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listInteger", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listLong", false);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listShort", false);
+
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldCharArray", true);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("fieldStringArray", true);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listString", true);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listStringInt", true);
+        TestJavaInterop.this.testForeignVectorArithmeticOp("listChar", true);
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to + 1", errorIn("to + 1", "non-numeric argument to binary operator"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "1 + to", errorIn("1 + to", "non-numeric argument to binary operator"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to + to", errorIn("to + to", "non-numeric argument to binary operator"));
+    }
+
+    private void testForeignVectorArithmeticOp(String vec, boolean fail) throws NoSuchFieldException, IllegalAccessException {
+        TestClass t = new TestClass();
+
+        String expectedOK;
+        String expectedKO;
+
+        expectedOK = toRVector(t, vec) + " + 1";
+        expectedKO = errorIn("to$" + vec + " + 1", "non-numeric argument to binary operator");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " + 1", fail ? expectedKO : expectedOK);
+
+        expectedOK = toRVector(t, vec) + " + c(1, 2, 3)";
+        expectedKO = errorIn("to$" + vec + " + c(1, 2, 3)", "non-numeric argument to binary operator");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " + c(1, 2, 3)", fail ? expectedKO : expectedOK);
+
+        expectedOK = "1 + " + toRVector(t, vec);
+        expectedKO = errorIn("1 + to$" + vec, "non-numeric argument to binary operator");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "1 + to$" + vec, fail ? expectedKO : expectedOK);
+
+        expectedOK = "c(1, 2, 3) + " + toRVector(t, vec);
+        expectedKO = errorIn("c(1, 2, 3) + to$" + vec + "", "non-numeric argument to binary operator");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " c(1, 2, 3) + to$" + vec, fail ? expectedKO : expectedOK);
+
+        expectedOK = toRVector(t, vec) + " + " + toRVector(t, vec);
+        expectedKO = errorIn("to$" + vec + " + to$" + vec + "", "non-numeric argument to binary operator");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " + to$" + vec, fail ? expectedKO : expectedOK);
+
+        expectedOK = "-" + toRVector(t, vec);
+        expectedKO = errorIn("-(to$" + vec + ")", "invalid argument to unary operator");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "-(to$" + vec + ")", fail ? expectedKO : expectedOK);
+
+        expectedOK = "numeric(0)";
+        expectedKO = errorIn("to$" + vec + " + NULL", "non-numeric argument to binary operator");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " + NULL", fail ? expectedKO : expectedOK);
+
+        expectedOK = "numeric(0)";
+        expectedKO = errorIn("NULL + to$" + vec, "non-numeric argument to binary operator");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "NULL + to$" + vec, fail ? expectedKO : expectedOK);
+    }
+
+    @Test
+    public void testForeignVectorBooleanOp() throws NoSuchFieldException,
+                    IllegalAccessException {
+        testForeignVectorBooleanOp("fieldBooleanArray", false);
+        testForeignVectorBooleanOp("fieldByteArray", false);
+        testForeignVectorBooleanOp("fieldDoubleArray", false);
+        testForeignVectorBooleanOp("fieldFloatArray", false);
+        testForeignVectorBooleanOp("fieldIntegerArray", false);
+        testForeignVectorBooleanOp("fieldLongArray", false);
+        testForeignVectorBooleanOp("fieldShortArray", false);
+
+        testForeignVectorBooleanOp("listBoolean", false);
+        testForeignVectorBooleanOp("listByte", false);
+        testForeignVectorBooleanOp("listDouble", false);
+        testForeignVectorBooleanOp("listFloat", false);
+        testForeignVectorBooleanOp("listInteger", false);
+        testForeignVectorBooleanOp("listLong", false);
+        testForeignVectorBooleanOp("listShort", false);
+
+        testForeignVectorBooleanOp("fieldCharArray", true);
+        testForeignVectorBooleanOp("fieldStringArray", true);
+        testForeignVectorBooleanOp("listString", true);
+        testForeignVectorBooleanOp("listStringInt", true);
+        testForeignVectorBooleanOp("listChar", true);
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to & T", errorIn("to & T", "operations are possible only for numeric, logical or complex types"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "T & to", errorIn("T & to", "operations are possible only for numeric, logical or complex types"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to & to", errorIn("to & to", "operations are possible only for numeric, logical or complex types"));
+    }
+
+    private void testForeignVectorBooleanOp(String vec, boolean fail) throws NoSuchFieldException, IllegalAccessException {
+        TestClass t = new TestClass();
+
+        String expectedOK;
+        String expectedKO;
+
+        expectedOK = toRVector(t, vec) + " & T";
+        expectedKO = errorIn("to$" + vec + " & T", "operations are possible only for numeric, logical or complex types");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " & T", fail ? expectedKO : expectedOK);
+
+        expectedOK = toRVector(t, vec) + " & c(T, T, F)";
+        expectedKO = errorIn("to$" + vec + " & c(T, T, F)", "operations are possible only for numeric, logical or complex types");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " & c(T, T, F)", fail ? expectedKO : expectedOK);
+
+        expectedOK = "T & " + toRVector(t, vec);
+        expectedKO = errorIn("T & to$" + vec, "operations are possible only for numeric, logical or complex types");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "T & to$" + vec, fail ? expectedKO : expectedOK);
+
+        expectedOK = "c(T, T, F) & " + toRVector(t, vec);
+        expectedKO = errorIn("c(T, T, F) & to$" + vec + "", "operations are possible only for numeric, logical or complex types");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " c(T, T, F) & to$" + vec, fail ? expectedKO : expectedOK);
+
+        expectedOK = toRVector(t, vec) + " & " + toRVector(t, vec);
+        expectedKO = errorIn("to$" + vec + " & to$" + vec + "", "operations are possible only for numeric, logical or complex types");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " & to$" + vec, fail ? expectedKO : expectedOK);
+
+        expectedOK = "!" + toRVector(t, vec);
+        expectedKO = errorIn("!(to$" + vec + ")", "invalid argument type");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "!(to$" + vec + ")", fail ? expectedKO : expectedOK);
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " & NULL", "logical(0)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "NULL & to$" + vec, "logical(0)");
+    }
+
+    @Test
+    public void testForeignVectorScalarBooleanOp() throws NoSuchFieldException,
+                    IllegalAccessException {
+        testForeignVectorScalarBooleanOp("||");
+        testForeignVectorScalarBooleanOp("&&");
+    }
+
+    private void testForeignVectorScalarBooleanOp(String operator) throws NoSuchFieldException,
+                    IllegalAccessException {
+        testForeignVectorScalarBooleanOp(operator, "fieldBooleanArray", false);
+        testForeignVectorScalarBooleanOp(operator, "fieldByteArray", false);
+        testForeignVectorScalarBooleanOp(operator, "fieldDoubleArray", false);
+        testForeignVectorScalarBooleanOp(operator, "fieldFloatArray", false);
+        testForeignVectorScalarBooleanOp(operator, "fieldIntegerArray", false);
+        testForeignVectorScalarBooleanOp(operator, "fieldLongArray", false);
+        testForeignVectorScalarBooleanOp(operator, "fieldShortArray", false);
+
+        testForeignVectorScalarBooleanOp(operator, "listBoolean", false);
+        testForeignVectorScalarBooleanOp(operator, "listByte", false);
+        testForeignVectorScalarBooleanOp(operator, "listDouble", false);
+        testForeignVectorScalarBooleanOp(operator, "listFloat", false);
+        testForeignVectorScalarBooleanOp(operator, "listInteger", false);
+        testForeignVectorScalarBooleanOp(operator, "listLong", false);
+        testForeignVectorScalarBooleanOp(operator, "listShort", false);
+
+        testForeignVectorScalarBooleanOp(operator, "fieldCharArray", true);
+        testForeignVectorScalarBooleanOp(operator, "fieldStringArray", true);
+        testForeignVectorScalarBooleanOp(operator, "listString", true);
+        testForeignVectorScalarBooleanOp(operator, "listStringInt", true);
+        testForeignVectorScalarBooleanOp(operator, "listChar", true);
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to " + operator + " T", errorIn("to " + operator + " T", "invalid 'x' type in 'x " + operator + " y'"));
+        String cmd = CREATE_TRUFFLE_OBJECT + "T " + operator + " to";
+        if (operator.equals("||")) {
+            assertEvalFastR(cmd, "TRUE");
+        } else {
+            assertEvalFastR(cmd, errorIn("T " + operator + " to", "invalid 'y' type in 'x " + operator + " y'"));
+        }
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to " + operator + " to", errorIn("to " + operator + " to", "invalid 'x' type in 'x " + operator + " y'"));
+    }
+
+    private void testForeignVectorScalarBooleanOp(String operator, String vec, boolean fail) throws NoSuchFieldException, IllegalAccessException {
+        TestClass t = new TestClass();
+
+        String expectedOK;
+        String expectedKO;
+
+        expectedOK = toRVector(t, vec) + operator + " T";
+        expectedKO = errorIn("to$" + vec + " " + operator + " T", "invalid 'x' type in 'x " + operator + " y'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " " + operator + " T", fail ? expectedKO : expectedOK);
+
+        expectedOK = toRVector(t, vec) + operator + " c(T, T, F)";
+        expectedKO = errorIn("to$" + vec + " " + operator + " c(T, T, F)", "invalid 'x' type in 'x " + operator + " y'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " " + operator + " c(T, T, F)", fail ? expectedKO : expectedOK);
+
+        expectedOK = "T " + operator + " " + toRVector(t, vec);
+        expectedKO = errorIn("T " + operator + " to$" + vec + "", "invalid 'y' type in 'x " + operator + " y'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "T " + operator + " to$" + vec, fail && !operator.equals("||") ? expectedKO : expectedOK);
+
+        expectedOK = "c(T, T, F) " + operator + " " + toRVector(t, vec);
+        expectedKO = errorIn("c(T, T, F) " + operator + " to$" + vec + "", "invalid 'y' type in 'x " + operator + " y'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + " c(T, T, F) " + operator + " to$" + vec, fail && !operator.equals("||") ? expectedKO : expectedOK);
+
+        expectedOK = toRVector(t, vec) + " " + operator + " " + toRVector(t, vec);
+        expectedKO = errorIn("to$" + vec + " " + operator + " to$" + vec, "invalid 'x' type in 'x " + operator + " y'");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "to$" + vec + " " + operator + " to$" + vec, fail ? expectedKO : expectedOK);
+
+        String cmd = CREATE_TRUFFLE_OBJECT + "to$" + vec + " " + operator + " NULL";
+        if (operator.equals("||") && !fail) {
+            assertEvalFastR(cmd, "TRUE");
+        } else {
+            assertEvalFastR(cmd, errorIn("to$" + vec + " " + operator + " NULL", "invalid " + (fail ? "'x'" : "'y'") + " type in 'x " + operator + " y'"));
+        }
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "NULL " + operator + " to$" + vec, errorIn("NULL " + operator + " to$" + vec, "invalid 'x' type in 'x " + operator + " y'"));
+    }
+
+    @Test
+    public void testForeignUnaryArithmeticOp() {
+
+        TestClass t = new TestClass();
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldBooleanArray)", "c(1, 0, 1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldByteArray)", toRVector(t.fieldByteArray, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldDoubleArray)", toRVector(t.fieldDoubleArray, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldFloatArray)", toRVector(t.fieldFloatArray, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldIntegerArray)", toRVector(t.fieldIntegerArray, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldLongArray)", toRVector(t.fieldLongArray, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldShortArray)", toRVector(t.fieldShortArray, null));
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listBoolean)", "c(1, 0, 1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listByte)", toRVector(t.listByte, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listDouble)", toRVector(t.listDouble, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listFloat)", toRVector(t.listFloat, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listInteger)", toRVector(t.listInteger, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listLong)", toRVector(t.listLong, null));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listShort)", toRVector(t.listShort, null));
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldCharArray)", errorIn("abs(to$fieldCharArray)", "non-numeric argument to mathematical function"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$fieldStringArray)", errorIn("abs(to$fieldStringArray)", "non-numeric argument to mathematical function"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listString)", errorIn("abs(to$listString)", "non-numeric argument to mathematical function"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listStringInt)", errorIn("abs(to$listStringInt)", "non-numeric argument to mathematical function"));
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to$listChar)", errorIn("abs(to$listChar)", "non-numeric argument to mathematical function"));
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "abs(to)", errorIn("abs(to)", "non-numeric argument to mathematical function"));
+    }
+
+    @Test
+    public void testForeignUnaryArithmeticReduceOp() {
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldBooleanArray)", "c(0, 1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldByteArray)", "c(1, 3)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldDoubleArray)", "c(1.1, 3.1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldFloatArray)", "c(1.1, 3.1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldIntegerArray)", "c(1, 3)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldLongArray)", "c(1, 3)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldShortArray)", "c(1, 3)");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listBoolean)", "c(0, 1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listByte)", "c(1, 3)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listDouble)", "c(1.1, 3.1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listFloat)", "c(1.1, 3.1)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listInteger)", "c(1, 3)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listLong)", "c(1, 3)");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listShort)", "c(1, 3)");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldCharArray)", "c('a', 'c')");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$fieldStringArray)", "c('a', 'c')");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listString)", "c('a', 'c')");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listStringInt)", "c('1', '3')");
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to$listChar)", "c('a', 'c')");
+
+        assertEvalFastR(CREATE_TRUFFLE_OBJECT + "range(to)", errorIn("min(x, na.rm = na.rm)", "invalid 'type' (list) of argument"));
     }
 
     private String getRValue(Object value) {
@@ -459,14 +1308,14 @@ public class TestJavaInterop extends TestBase {
         if (value.getClass().isArray()) {
             StringBuilder sb = new StringBuilder();
             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)) {
+            int length = Array.getLength(value);
+            for (int i = 0; i < length; i++) {
+                if (length > 1) {
                     // what the heck?
-                    sb.append(" ");
+                    sb.append(getBooleanPrefix(value, i));
                 }
                 sb.append(getRValue(Array.get(value, i)));
-                if (i < lenght - 1) {
+                if (i < length - 1) {
                     sb.append(" ");
                 }
             }
@@ -476,6 +1325,86 @@ public class TestJavaInterop extends TestBase {
         return value.toString();
     }
 
+    private String toRVector(TestClass t, String fieldName) throws NoSuchFieldException, IllegalAccessException {
+        Field fld = t.getClass().getDeclaredField(fieldName);
+        return toRVector(fld.get(t), null);
+    }
+
+    private String toRVector(Object o, String asXXX) {
+        return toRVector(list(o), asXXX);
+    }
+
+    private String toRVector(Object[] l, String asXXX) {
+        return toRVector(Arrays.asList(l), asXXX);
+    }
+
+    private String c(Object a1, Object a2) {
+        List<Object> l = new ArrayList<>();
+        List<?> l1 = list(a1);
+        List<?> l2 = list(a2);
+        l.addAll(l1);
+        l.addAll(l2);
+        return toRVector(l, null);
+    }
+
+    private List<?> list(Object o) {
+        if (o.getClass().isArray()) {
+            List<Object> l = new ArrayList<>();
+            for (int i = 0; i < Array.getLength(o); i++) {
+                l.add(Array.get(o, i));
+            }
+            return l;
+        } else if (o instanceof List) {
+            return (List<?>) o;
+        }
+        Assert.fail(o + " should have been an array or list");
+        return null;
+    }
+
+    private String toRVector(List<?> l, String asXXX) {
+        StringBuilder sb = new StringBuilder();
+        if (asXXX != null) {
+            sb.append(asXXX);
+            sb.append("(c(");
+        } else {
+            sb.append("c(");
+        }
+        Iterator<?> it = l.iterator();
+        while (it.hasNext()) {
+            Object o = it.next();
+            if (asXXX != null) {
+                if (asXXX.equals("as.character") && (o instanceof Double || o instanceof Float)) {
+                    o = DoubleVectorPrinter.encodeReal(((Number) o).doubleValue());
+                }
+                sb.append(getRValue(o));
+            } else {
+                sb.append(getRValue(o));
+            }
+            if (it.hasNext()) {
+                sb.append(',');
+            }
+        }
+        if (asXXX != null) {
+            sb.append("))");
+        } else {
+            sb.append(")");
+        }
+        return sb.toString();
+    }
+
+    private String getAsXXX(Object o, String asXXX) {
+        StringBuilder sb = new StringBuilder();
+        sb.append(asXXX);
+        sb.append("(");
+        Object val = o;
+        if (asXXX.equals("as.character") && (o instanceof Double || o instanceof Float)) {
+            val = DoubleVectorPrinter.encodeReal(((Number) o).doubleValue());
+        }
+        sb.append(getRValue(val));
+        sb.append(')');
+        return sb.toString();
+    }
+
     private String getRValuesAsString(Object... values) {
         StringBuilder sb = new StringBuilder();
         for (int i = 0; i < values.length; i++) {
@@ -488,6 +1417,75 @@ public class TestJavaInterop extends TestBase {
         return sb.toString();
     }
 
+    private static String getBooleanPrefix(Object value, int i) {
+        if (value.getClass().getComponentType() == Boolean.TYPE && (boolean) Array.get(value, i)) {
+            return " ";
+        }
+        if (i > 0 && value.getClass().getComponentType() == String.class &&
+                        (Array.get(value, i).equals("T") || Array.get(value, i).equals("F") || Array.get(value, i).equals("TRUE") || Array.get(value, i).equals("FALSE"))) {
+            return " ";
+        }
+        return "";
+    }
+
+    private static String toArrayClassName(String className, int dims) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("'");
+        for (int i = 0; i < dims; i++) {
+            sb.append("[");
+        }
+        switch (className) {
+            case "boolean":
+                sb.append("Z");
+                break;
+            case "byte":
+                sb.append("B");
+                break;
+            case "char":
+                sb.append("C");
+                break;
+            case "double":
+                sb.append("D");
+                break;
+            case "float":
+                sb.append("F");
+                break;
+            case "int":
+                sb.append("I");
+                break;
+            case "long":
+                sb.append("J");
+                break;
+            case "short":
+                sb.append("S");
+                break;
+            default:
+                sb.append('L');
+                sb.append(className);
+                sb.append(';');
+        }
+        sb.append('\'');
+        return sb.toString();
+    }
+
+    private String errorIn(String left, String right) {
+        String errorIn = "Error in ";
+        String delim = " :";
+
+        StringBuilder sb = new StringBuilder();
+        sb.append("cat('");
+        sb.append(errorIn);
+        sb.append(left.replaceAll("\\'", "\\\\\\'"));
+        sb.append(delim);
+        if (errorIn.length() + left.length() + delim.length() + 1 + right.length() >= 74) {
+            sb.append("', '\n', '");
+        }
+        sb.append(' ');
+        sb.append(right.replaceAll("\\'", "\\\\\\'"));
+        sb.append("', '\n')");
+        return sb.toString();
+    }
+
     public static class TestNamesClass {
         public Object field;
         public static Object staticField;
@@ -522,6 +1520,148 @@ public class TestJavaInterop extends TestBase {
         }
     }
 
+    @SuppressWarnings("unused")
+    public static class TestOverload {
+        public String type;
+
+        public TestOverload(boolean o) {
+            type = boolean.class.getName();
+        }
+
+        public TestOverload(Boolean o) {
+            type = o.getClass().getName();
+        }
+
+        public TestOverload(byte o) {
+            type = byte.class.getName();
+        }
+
+        public TestOverload(Byte o) {
+            type = o.getClass().getName();
+        }
+
+        public TestOverload(char o) {
+            type = char.class.getName();
+        }
+
+        public TestOverload(Character o) {
+            type = o.getClass().getName();
+        }
+
+        public TestOverload(double o) {
+            type = double.class.getName();
+        }
+
+        public TestOverload(Double o) {
+            type = o.getClass().getName();
+        }
+
+        public TestOverload(int o) {
+            type = int.class.getName();
+        }
+
+        public TestOverload(Integer o) {
+            type = o.getClass().getName();
+        }
+
+        public TestOverload(float o) {
+            type = float.class.getName();
+        }
+
+        public TestOverload(Float o) {
+            type = o.getClass().getName();
+        }
+
+        public TestOverload(long o) {
+            type = long.class.getName();
+        }
+
+        public TestOverload(Long o) {
+            type = o.getClass().getName();
+        }
+
+        public TestOverload(short o) {
+            type = short.class.getName();
+        }
+
+        public TestOverload(Short o) {
+            type = o.getClass().getName();
+        }
+
+        public TestOverload(String o) {
+            type = o.getClass().getName();
+        }
+
+        public static String isOverloaded(boolean b) {
+            return "boolean";
+        }
+
+        public static String isOverloaded(Boolean b) {
+            return Boolean.class.getName();
+        }
+
+        public static String isOverloaded(byte b) {
+            return "byte";
+        }
+
+        public static String isOverloaded(Byte b) {
+            return Byte.class.getName();
+        }
+
+        public static String isOverloaded(char c) {
+            return "char";
+        }
+
+        public static String isOverloaded(Character c) {
+            return Character.class.getName();
+        }
+
+        public static String isOverloaded(double l) {
+            return "double";
+        }
+
+        public static String isOverloaded(Double l) {
+            return Double.class.getName();
+        }
+
+        public static String isOverloaded(Float f) {
+            return Float.class.getName();
+        }
+
+        public static String isOverloaded(float f) {
+            return "float";
+        }
+
+        public static String isOverloaded(int c) {
+            return "int";
+        }
+
+        public static String isOverloaded(Integer c) {
+            return Integer.class.getName();
+        }
+
+        public static String isOverloaded(long l) {
+            return "long";
+        }
+
+        public static String isOverloaded(Long l) {
+            return Long.class.getName();
+        }
+
+        public static String isOverloaded(short c) {
+            return "short";
+        }
+
+        public static String isOverloaded(Short c) {
+            return Short.class.getName();
+        }
+
+        public static String isOverloaded(String s) {
+            return String.class.getName();
+        }
+    }
+
+    @SuppressWarnings("unused")
     public static class TestClass {
 
         public static boolean fieldStaticBoolean = true;
@@ -567,7 +1707,7 @@ public class TestJavaInterop extends TestBase {
         public static char[] fieldStaticCharArray;
         public static double[] fieldStaticDoubleArray;
         public static float[] fieldStaticFloatArray;
-        public static int[] fieldStaticIntArray;
+        public static int[] fieldStaticIntegerArray;
         public static long[] fieldStaticLongArray;
         public static short[] fieldStaticShortArray;
         public static String[] fieldStaticStringArray;
@@ -577,10 +1717,12 @@ public class TestJavaInterop extends TestBase {
         public char[] fieldCharArray = fieldStaticCharArray;
         public double[] fieldDoubleArray = fieldStaticDoubleArray;
         public float[] fieldFloatArray = fieldStaticFloatArray;
-        public int[] fieldIntArray = fieldStaticIntArray;
+        public int[] fieldIntegerArray = fieldStaticIntegerArray;
         public long[] fieldLongArray = fieldStaticLongArray;
         public short[] fieldShortArray = fieldStaticShortArray;
         public String[] fieldStringArray = fieldStaticStringArray;
+        public String[] fieldStringIntArray = new String[]{"1", "2", "3"};
+        public String[] fieldStringBooleanArray = new String[]{"TRUE", "TRUE", "FALSE"};
 
         public int[][] int2DimArray;
         public Object[] objectArray;
@@ -595,10 +1737,34 @@ public class TestJavaInterop extends TestBase {
         public static Object fieldStaticNullObject = null;
         public Object fieldNullObject = null;
 
+        public List<Boolean> listBoolean = new ArrayList<>(Arrays.asList(true, false, true));
+        public List<Byte> listByte = new ArrayList<>(Arrays.asList((byte) 1, (byte) 2, (byte) 3));
+        public List<Character> listChar = new ArrayList<>(Arrays.asList('a', 'b', 'c'));
+        public List<Double> listDouble = new ArrayList<>(Arrays.asList(1.1, 2.1, 3.1));
+        public List<Float> listFloat = new ArrayList<>(Arrays.asList(1.1f, 2.1f, 3.1f));
+        public List<Integer> listInteger = new ArrayList<>(Arrays.asList(1, 2, 3));
+        public List<Long> listLong = new ArrayList<>(Arrays.asList(1L, 2L, 3L));
+        public List<Short> listShort = new ArrayList<>(Arrays.asList((short) 1, (short) 2, (short) 3));
+        public List<String> listString = new ArrayList<>(Arrays.asList("a", "b", "c"));
+        public List<String> listStringInt = new ArrayList<>(Arrays.asList("1", "2", "3"));
+        public List<String> listStringBoolean = new ArrayList<>(Arrays.asList("TRUE", "TRUE", "FALSE"));
+        public List<String> listEmpty = new ArrayList<>();
+
+        public static class Element {
+            public final String data;
+
+            public Element(String data) {
+                this.data = data;
+            }
+        }
+
+        public List<Element> listObject = new ArrayList<>(Arrays.asList(new Element("a"), new Element("b"), new Element("c"), null));
+        public Element[] arrayObject = new Element[]{new Element("a"), new Element("b"), new Element("c"), null};
+
         public Map<String, String> map;
 
         public TestClass() {
-            this(true, Byte.MAX_VALUE, 'a', Double.MAX_VALUE, Float.MAX_VALUE, Integer.MAX_VALUE, Long.MAX_VALUE, Short.MAX_VALUE, "a string");
+            this(true, Byte.MAX_VALUE, 'a', Double.MAX_VALUE, 1.1f, Integer.MAX_VALUE, Long.MAX_VALUE, Short.MAX_VALUE, "a string");
         }
 
         public TestClass(boolean bo, byte bt, char c, double d, float f, int i, long l, short sh, String st) {
@@ -645,7 +1811,7 @@ public class TestJavaInterop extends TestBase {
             fieldStaticCharArray = new char[]{'a', 'b', 'c'};
             fieldStaticDoubleArray = new double[]{1.1, 2.1, 3.1};
             fieldStaticFloatArray = new float[]{1.1f, 2.1f, 3.1f};
-            fieldStaticIntArray = new int[]{1, 2, 3};
+            fieldStaticIntegerArray = new int[]{1, 2, 3};
             fieldStaticLongArray = new long[]{1, 2, 3};
             fieldStaticShortArray = new short[]{1, 2, 3};
             fieldStaticStringArray = new String[]{"a", "b", "c"};
@@ -655,7 +1821,7 @@ public class TestJavaInterop extends TestBase {
             fieldCharArray = fieldStaticCharArray;
             fieldDoubleArray = fieldStaticDoubleArray;
             fieldFloatArray = fieldStaticFloatArray;
-            fieldIntArray = fieldStaticIntArray;
+            fieldIntegerArray = fieldStaticIntegerArray;
             fieldLongArray = fieldStaticLongArray;
             fieldShortArray = fieldStaticShortArray;
             fieldStringArray = fieldStaticStringArray;
@@ -670,6 +1836,7 @@ public class TestJavaInterop extends TestBase {
             map = new HashMap<>();
             map.put("one", "1");
             map.put("two", "2");
+            map.put("three", "3");
         }
 
         public static boolean methodStaticBoolean() {
@@ -713,7 +1880,7 @@ public class TestJavaInterop extends TestBase {
         }
 
         public static int[] methodStaticIntArray() {
-            return fieldStaticIntArray;
+            return fieldStaticIntegerArray;
         }
 
         public boolean methodBoolean() {
@@ -757,7 +1924,7 @@ public class TestJavaInterop extends TestBase {
         }
 
         public int[] methodIntArray() {
-            return fieldIntArray;
+            return fieldIntegerArray;
         }
 
         public static Boolean methodStaticBooleanObject() {
@@ -927,11 +2094,212 @@ public class TestJavaInterop extends TestBase {
         public String isOverloaded(String s) {
             return String.class.getName();
         }
+
+        public String isIntArray(int[] a) {
+            return a.getClass().getName();
+        }
+
+        public String isIntegerArray(Integer[] a) {
+            return a.getClass().getName();
+        }
+    }
+
+    public static class TestArraysClass {
+        public Object[] objectEmpty = new Object[0];
+
+        public boolean[] booleanArray = {true, false, true};
+        public boolean[][] booleanArray2 = {{true, false, true}, {true, false, true}};
+        public boolean[][][] booleanArray3 = {{{true, false, true}, {true, false, true}}, {{true, false, true}, {true, false, true}}};
+
+        public byte[] byteArray = {1, 2, 3};
+        public byte[][] byteArray2 = {{1, 2, 3}, {1, 2, 3}};
+        public byte[][][] byteArray3 = {{{1, 2, 3}, {1, 2, 3}}, {{1, 2, 3}, {1, 2, 3}}};
+
+        public char[] charArray = {'a', 'b', 'c'};
+        public char[][] charArray2 = {{'a', 'b', 'c'}, {'a', 'b', 'c'}};
+        public char[][][] charArray3 = {{{'a', 'b', 'c'}, {'a', 'b', 'c'}}, {{'a', 'b', 'c'}, {'a', 'b', 'c'}}};
+
+        public double[] doubleArray = {1.1, 1.2, 1.3};
+        public double[][] doubleArray2 = {{1.1, 1.2, 1.3}, {1.1, 1.2, 1.3}};
+        public double[][][] doubleArray3 = {{{1.1, 1.2, 1.3}, {1.1, 1.2, 1.3}}, {{1.1, 1.2, 1.3}, {1.1, 1.2, 1.3}}};
+
+        public float[] floatArray = {1.1f, 1.2f, 1.3f};
+        public float[][] floatArray2 = {{1.1f, 1.2f, 1.3f}, {1.1f, 1.2f, 1.3f}};
+        public float[][][] floatArray3 = {{{1.1f, 1.2f, 1.3f}, {1.1f, 1.2f, 1.3f}}, {{1.1f, 1.2f, 1.3f}, {1.1f, 1.2f, 1.3f}}};
+
+        public int[] integerArray = {1, 2, 3};
+        public int[][] integerArray2 = {{1, 2, 3}, {1, 2, 3}};
+        public int[][][] integerArray3 = {{{1, 2, 3}, {1, 2, 3}}, {{1, 2, 3}, {1, 2, 3}}};
+
+        public long[] longArray = {1L, 2L, 3L};
+        public long[][] longArray2 = {{1L, 2L, 3L}, {1L, 2L, 3L}};
+        public long[][][] longArray3 = {{{1L, 2L, 3L}, {1L, 2L, 3L}}, {{1L, 2L, 3L}, {1L, 2L, 3L}}};
+
+        public short[] shortArray = {1, 2, 3};
+        public short[][] shortArray2 = {{1, 2, 3}, {1, 2, 3}};
+        public short[][][] shortArray3 = {{{1, 2, 3}, {1, 2, 3}}, {{1, 2, 3}, {1, 2, 3}}};
+
+        public Boolean[] booleanObjectArray = {true, false, true};
+        public Boolean[][] booleanObjectArray2 = {{true, false, true}, {true, false, true}};
+        public Boolean[][][] booleanObjectArray3 = {{{true, false, true}, {true, false, true}}, {{true, false, true}, {true, false, true}}};
+
+        public Byte[] byteObjectArray = {1, 2, 3};
+        public Byte[][] byteObjectArray2 = {{1, 2, 3}, {1, 2, 3}};
+        public Byte[][][] byteObjectArray3 = {{{1, 2, 3}, {1, 2, 3}}, {{1, 2, 3}, {1, 2, 3}}};
+
+        public Character[] charObjectArray = {'a', 'b', 'c'};
+        public Character[][] charObjectArray2 = {{'a', 'b', 'c'}, {'a', 'b', 'c'}};
+        public Character[][][] charObjectArray3 = {{{'a', 'b', 'c'}, {'a', 'b', 'c'}}, {{'a', 'b', 'c'}, {'a', 'b', 'c'}}};
+
+        public Double[] doubleObjectArray = {1.1, 1.2, 1.3};
+        public Double[][] doubleObjectArray2 = {{1.1, 1.2, 1.3}, {1.1, 1.2, 1.3}};
+        public Double[][][] doubleObjectArray3 = {{{1.1, 1.2, 1.3}, {1.1, 1.2, 1.3}}, {{1.1, 1.2, 1.3}, {1.1, 1.2, 1.3}}};
+
+        public Float[] floatObjectArray = {1.1f, 1.2f, 1.3f};
+        public Float[][] floatObjectArray2 = {{1.1f, 1.2f, 1.3f}, {1.1f, 1.2f, 1.3f}};
+        public Float[][][] floatObjectArray3 = {{{1.1f, 1.2f, 1.3f}, {1.1f, 1.2f, 1.3f}}, {{1.1f, 1.2f, 1.3f}, {1.1f, 1.2f, 1.3f}}};
+
+        public Integer[] integerObjectArray = {1, 2, 3};
+        public Integer[][] integerObjectArray2 = {{1, 2, 3}, {1, 2, 3}};
+        public Integer[][][] integerObjectArray3 = {{{1, 2, 3}, {1, 2, 3}}, {{1, 2, 3}, {1, 2, 3}}};
+
+        public Long[] longObjectArray = {1L, 2L, 3L};
+        public Long[][] longObjectArray2 = {{1L, 2L, 3L}, {1L, 2L, 3L}};
+        public Long[][][] longObjectArray3 = {{{1L, 2L, 3L}, {1L, 2L, 3L}}, {{1L, 2L, 3L}, {1L, 2L, 3L}}};
+
+        public Short[] shortObjectArray = {1, 2, 3};
+        public Short[][] shortObjectArray2 = {{1, 2, 3}, {1, 2, 3}};
+        public Short[][][] shortObjectArray3 = {{{1, 2, 3}, {1, 2, 3}}, {{1, 2, 3}, {1, 2, 3}}};
+
+        public String[] stringArray = {"a", "b", "c"};
+        public String[][] stringArray2 = {{"a", "b", "c"}, {"a", "b", "c"}};
+        public String[][][] stringArray3 = {{{"a", "b", "c"}, {"a", "b", "c"}}, {{"a", "b", "c"}, {"a", "b", "c"}}};
+
+        public Object[] onlyIntegerObjectArray = {1, 2, 3};
+        public Object[] onlyLongObjectArray = {1L, 2L, 3L};
+        public Object[] numericObjectArray = {1, 1L, 1.1};
+        public Object[] mixedObjectArray = {1, "a", "1"};
+
+        public List<Boolean> booleanList = Arrays.asList(booleanObjectArray);
+        public List<?> booleanList2 = Arrays.asList(new List<?>[]{booleanList, booleanList});
+        public List<?> booleanList3 = Arrays.asList(new List<?>[]{booleanList2, booleanList2});
+
+        public List<Byte> byteList = Arrays.asList(byteObjectArray);
+        public List<?> byteList2 = Arrays.asList(new List<?>[]{byteList, byteList});
+        public List<?> byteList3 = Arrays.asList(new List<?>[]{byteList2, byteList2});
+
+        public List<Character> charList = Arrays.asList(charObjectArray);
+        public List<?> charList2 = Arrays.asList(new List<?>[]{charList, charList});
+        public List<?> charList3 = Arrays.asList(new List<?>[]{charList2, charList2});
+
+        public List<Double> doubleList = Arrays.asList(doubleObjectArray);
+        public List<?> doubleList2 = Arrays.asList(new List<?>[]{doubleList, doubleList});
+        public List<?> doubleList3 = Arrays.asList(new List<?>[]{doubleList2, doubleList2});
+
+        public List<Float> floatList = Arrays.asList(floatObjectArray);
+        public List<?> floatList2 = Arrays.asList(new List<?>[]{floatList, floatList});
+        public List<?> floatList3 = Arrays.asList(new List<?>[]{floatList2, floatList2});
+
+        public List<Integer> integerList = Arrays.asList(integerObjectArray);
+        public List<?> integerList2 = Arrays.asList(new List<?>[]{integerList, integerList});
+        public List<?> integerList3 = Arrays.asList(new List<?>[]{integerList2, integerList2});
+
+        public List<Long> longList = Arrays.asList(longObjectArray);
+        public List<?> longList2 = Arrays.asList(new List<?>[]{longList, longList});
+        public List<?> longList3 = Arrays.asList(new List<?>[]{longList2, longList2});
+
+        public List<Short> shortList = Arrays.asList(shortObjectArray);
+        public List<?> shortList2 = Arrays.asList(new List<?>[]{shortList, shortList});
+        public List<?> shortList3 = Arrays.asList(new List<?>[]{shortList2, shortList2});
+
+        public List<String> stringList = Arrays.asList(stringArray);
+        public List<?> stringList2 = Arrays.asList(new List<?>[]{Arrays.asList(stringArray), Arrays.asList(stringArray)});
+        public List<?> stringList3 = Arrays.asList(new List<?>[]{stringList2, stringList2});
+
+        public List<?> mixedIntegerList = Arrays.asList(new Object[]{new Integer[]{1, 2, 3}, Arrays.asList(new int[]{4, 5, 6}), new int[]{7, 8, 9}, 10, 11, 12});
+    }
+
+    public static class TestIterableSize extends AbstractTestIterable {
+        public TestIterableSize(int size) {
+            super(size);
+        }
+
+        public int size() {
+            return size;
+        }
+    }
+
+    public static class TestIterableGetSize extends AbstractTestIterable {
+        public TestIterableGetSize(int size) {
+            super(size);
+        }
+
+        public int getSize() {
+            return size;
+        }
     }
 
-    public static class TestArrayClass {
-        public static TestArrayClass[] testArray = new TestArrayClass[]{new TestArrayClass(), new TestArrayClass(), new TestArrayClass()};
+    public static class TestIterableLength extends AbstractTestIterable {
+        public TestIterableLength(int size) {
+            super(size);
+        }
 
+        public int length() {
+            return size;
+        }
     }
 
+    public static class TestIterableGetLength extends AbstractTestIterable {
+        public TestIterableGetLength(int size) {
+            super(size);
+        }
+
+        public int getLength() {
+            return size;
+        }
+    }
+
+    public static class TestIterableNoSizeMethod implements Iterable<Integer> {
+        private final int size;
+
+        public TestIterableNoSizeMethod(int size) {
+            this.size = size;
+        }
+
+        private class I implements Iterator<Integer> {
+            private int size;
+
+            I() {
+                this.size = TestIterableNoSizeMethod.this.size;
+            }
+
+            @Override
+            public boolean hasNext() {
+                return size-- > 0;
+            }
+
+            @Override
+            public Integer next() {
+                throw new UnsupportedOperationException("Should not reach here.");
+            }
+        }
+
+        @Override
+        public Iterator<Integer> iterator() {
+            return new I();
+        }
+    }
+
+    private static class AbstractTestIterable implements Iterable<Object> {
+        protected final int size;
+
+        AbstractTestIterable(int size) {
+            this.size = size;
+        }
+
+        @Override
+        public Iterator<Object> iterator() {
+            throw new UnsupportedOperationException("Should not reach here.");
+        }
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/methods/TestSubstituteDirect.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/methods/TestSubstituteDirect.java
index 4ab7f98157a5087cf473adfec54580e8095dfe32..b2bf9a4f4bebbd51ed75bd8154b8ec8e58a29cae 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/methods/TestSubstituteDirect.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/methods/TestSubstituteDirect.java
@@ -71,5 +71,4 @@ public class TestSubstituteDirect extends TestBase {
         assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=c(1))");
         assertEval("substituteDirect(quote(x+1), list(x=1), cleanFunction=environment())");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_completecases.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_completecases.java
new file mode 100644
index 0000000000000000000000000000000000000000..a29b4977a7cc88634d440b2c2f75487c23256900
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestExternal_completecases.java
@@ -0,0 +1,43 @@
+/*
+ * 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.test.library.stats;
+
+import org.junit.Test;
+
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestExternal_completecases extends TestBase {
+    @Test
+    public void testCompleteCases() {
+        assertEval("stats::complete.cases(data.frame(col1=c(1,2,NA), col2=c(1,2,3)))");
+        assertEval("stats::complete.cases(data.frame(col1=c(1,2,NA), col2=c(1,2,3)), data.frame(col1=c(1,NA,3), col2=c(1,2,3)))");
+        assertEval("stats::complete.cases(data.frame(col1=c(1,2,NA), col2=c(1,2,3)), c(1,NA,2))");
+        assertEval("stats::complete.cases(data.frame(col1=c(1,NA), col2=c(2,3)), matrix(c(1,NA,2,NA), nrow=2))");
+    }
+
+    @Test
+    public void testCompleteCasesArgsValidation() {
+        assertEval(Output.IgnoreErrorContext, "stats::complete.cases(data.frame(col1=c(1,2,NA), col2=c(1,2,3)), list(NA,2,2))");
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
index 69ce1013d43d5ffdd579fdbd037b74d7e8c27e6d..56ff6bd83d9b39bc643fd66d3b1dab532d5d6a85 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/stats/TestRandGenerationFunctions.java
@@ -101,5 +101,4 @@ public class TestRandGenerationFunctions extends TestBase {
     public void testGenerators() {
         assertEval("for(gen in c(\"Buggy Kinderman-Ramage\", \"Ahrens-Dieter\", \"Box-Muller\", \"Inversion\", \"Kinderman-Ramage\", \"default\")) { print(paste0(gen, \":\")); RNGkind(NULL,gen); set.seed(42); print(rnorm(30)); }");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
index 0d5d1b076f0246c735de9e0f352deeefa0c75d38..f497f3ba318efdbf94ae0bf006d6bc58000d4d58 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestInteractiveDebug.java
@@ -22,15 +22,29 @@
  */
 package com.oracle.truffle.r.test.library.utils;
 
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardOpenOption;
+
+import org.junit.After;
+import org.junit.BeforeClass;
 import org.junit.Test;
 
+import com.oracle.truffle.r.nodes.builtin.helpers.DebugHandling;
 import com.oracle.truffle.r.test.TestBase;
 
 // Checkstyle: stop line length check
 public class TestInteractiveDebug extends TestBase {
+    @After
+    public void cleanupDebugListeners() {
+        DebugHandling.dispose();
+    }
+
     @Test
     public void testSimple() {
         assertEval("f <- function(x) {\n  t <- x + 1\n  print(t)\n  t}\ndebug(f)\nf(5)\nx\nn\nn\nt\nn\nn");
+        assertEval("f <- function(x) {\n  t <- x + 1\n  print(t)\n  t}\ndebug(f)\nf(5)\nx\nn\nn\nt\nn\nn\nundebug(f)\nf(3)\ndebug(f)\nf(5)\nx\nn\nn\nt\nn\nn");
     }
 
     @Test
@@ -88,4 +102,31 @@ public class TestInteractiveDebug extends TestBase {
         assertEval("fun0 <- function() { print('fun0') }; fun1 <- function() { print('en'); fun0(); fun0(); print('ex') }; debugonce(fun0); fun1()\nc\n");
         assertEval("fun0 <- function() { print('fun0') }; debugonce(fun0); fun0()\nc\n");
     }
+
+    @Test
+    public void testBrowser() {
+        assertEval("foo <- function() { stop('error msg') }; tryCatch(foo(), error=browser)\nprint(msg)\nc\n");
+        assertEval("do.call('browser', list())\nc\n");
+        assertEval("browser()\nwhere\nc\n");
+        assertEval("options(error=browser); prod('a')\nwhere\nc\n");
+    }
+
+    private static Path debugFile;
+
+    @BeforeClass
+    public static void setup() throws IOException {
+        Path testDir = TestBase.createTestDir("com.oracle.truffle.r.test.library.utils.rsrc");
+        String content = "bar <- function(x) print(x)\n\nfun <- function(x) {\nprint('Hello')\nfor(i in seq(3)) print(i)\nbar('World')\nprint(x)\n}";
+        debugFile = testDir.resolve("debug.r");
+        Files.write(debugFile, content.getBytes(), StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
+    }
+
+    @Test
+    public void testSetBreakpoint() {
+        assertEval(Output.IgnoreDebugCallString, Output.IgnoreDebugPath, String.format("source('%s'); setBreakpoint('%s', 4, verbose=F); fun(10)\n\n\n\n\n\n\n\n", debugFile, debugFile));
+        assertEval(String.format("source('%s'); setBreakpoint('%s', 4, verbose=F); setBreakpoint('%s', 4, verbose=F, clear=T); fun(10)\n", debugFile, debugFile, debugFile));
+        assertEval(Output.IgnoreDebugCallString, Output.IgnoreDebugPath, String.format(
+                        "source('%s'); setBreakpoint('%s', 4, verbose=F); fun(10)\n\n\n\n\n\n\n\n\nsetBreakpoint('%s', 4, verbose=F, clear=T); fun(10)\nsetBreakpoint('%s', 4, verbose=F); invisible(fun(10))\n\n\n\n\n\n\n\n\n",
+                        debugFile, debugFile, debugFile, debugFile));
+    }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java
index ddce0a78c9ad2ed54db3d583a302cd776d8557cb..20317fef5ee7a72ea9fcfac2cddc0ab79623f45c 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTypeConvert.java
@@ -93,5 +93,4 @@ public class TestTypeConvert extends TestBase {
         assertEval(".External2(utils:::C_typeconvert, environment(), 'NA', FALSE, '.', 'allow.loss')");
         assertEval(".External2(utils:::C_typeconvert, c('1'), environment(), FALSE, '.', 'allow.loss')");
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
index 9f4562761fefaee3fadc06f56cb08e1c1cb54aa8..8dd0021279f5c625ccf18e4a945682a4dd27c662 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/parser/TestParser.java
@@ -142,6 +142,14 @@ public class TestParser extends TestBase {
         assertEval(Output.IgnoreErrorMessage, "%0");
     }
 
+    @Test
+    public void testDotIdentifiers() {
+        assertEval("{ .. <- 42; cat(..); }");
+        assertEval("{ .... <- 42; cat(....); }");
+        assertEval("{ ....x <- 42; cat(....x); }");
+        assertEval("{ ...... <- 42; cat(......); }");
+    }
+
     /**
      * Recursively look for .r source files in the args[0] directory and parse them.
      */
@@ -165,7 +173,7 @@ public class TestParser extends TestBase {
                 RParserFactory.Parser<RSyntaxNode> parser = RParserFactory.getParser();
                 try {
                     source = RSource.fromFile(file);
-                    parser.script(source, new RASTBuilder());
+                    parser.script(source, new RASTBuilder(), null);
                 } catch (Throwable e) {
                     errorCount++;
                     Throwable t = e;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestUserRNG.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestUserRNG.java
index 087722ae5f5701a6944ddad2732d191b904f1bbb..6475e412c8128f6f1fa5e38498c1516f2a4ff2d3 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestUserRNG.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/rffi/TestUserRNG.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
@@ -22,9 +22,8 @@
  */
 package com.oracle.truffle.r.test.rffi;
 
+import java.io.IOException;
 import java.nio.file.Path;
-import java.nio.file.Paths;
-
 import org.junit.Test;
 
 import com.oracle.truffle.r.runtime.ffi.UserRngRFFI;
@@ -32,13 +31,26 @@ import com.oracle.truffle.r.test.TestBase;
 
 /**
  * Test for a user-defined random number generator. Implicitly tests {@code dyn.load} as well as the
- * {@link UserRngRFFI} interface. We take care to use relative paths so the expected output file is
- * portable.
+ * {@link UserRngRFFI} interface. The actual library is stored in a tar file, the location of which
+ * we can get from the {@code fastr.test.native} system property.
  */
 public class TestUserRNG extends TestBase {
     @Test
     public void testUserRNG() {
-        Path libPath = TestBase.getNativeProjectFile(Paths.get("urand", "lib", "liburand.so"));
-        assertEval(TestBase.template("{ dyn.load(\"%0\"); RNGkind(\"user\"); print(RNGkind()); set.seed(4567); runif(10) }", new String[]{libPath.toString()}));
+        Path dir = createTestDir("userrng");
+        String tarFile = System.getProperty("fastr.test.native");
+        assert tarFile != null;
+        String[] tarC = new String[]{"tar", "xf", tarFile};
+        ProcessBuilder pb = new ProcessBuilder(tarC);
+        pb.directory(dir.toFile());
+        try {
+            Process p = pb.start();
+            int rc = p.waitFor();
+            assert rc == 0;
+            assertEval(TestBase.template("{ dyn.load(\"%0\"); RNGkind(\"user\"); print(RNGkind()); set.seed(4567); runif(10) }", new String[]{dir.toString() + "/liburand.so"}));
+        } catch (IOException ex) {
+            assert false;
+        } catch (InterruptedException ex) {
+        }
     }
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/runtime/TestRSerialize.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/runtime/TestRSerialize.java
new file mode 100644
index 0000000000000000000000000000000000000000..43049190807e20a4da78030a1f77655cc8462298
--- /dev/null
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/runtime/TestRSerialize.java
@@ -0,0 +1,115 @@
+/*
+ * 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.runtime;
+
+import java.util.Arrays;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.oracle.truffle.r.runtime.RSerialize;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
+import com.oracle.truffle.r.runtime.data.RStringVector;
+import com.oracle.truffle.r.test.TestBase;
+
+public class TestRSerialize extends TestBase {
+
+    // Buffer enlargement tests
+
+    @Test
+    public void testDeserializeLongString() {
+        char[] chars = new char[1000000];
+        Arrays.fill(chars, 'x');
+        String longString = new String(chars);
+        RStringVector longStringVec = RDataFactory.createStringVector(longString);
+        byte[] serialized = RSerialize.serialize(longStringVec, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null);
+        Object unserialized = RSerialize.unserialize(RDataFactory.createRawVector(serialized));
+
+        Assert.assertTrue(unserialized instanceof RStringVector);
+        Assert.assertEquals(1, ((RStringVector) unserialized).getLength());
+        Assert.assertEquals(longString, ((RStringVector) unserialized).getDataAt(0));
+    }
+
+    @Test
+    public void testDeserializeShortLongStrings() {
+        char[] chars = new char[1000000];
+        Arrays.fill(chars, 'x');
+        String longString = new String(chars);
+        RStringVector longStringVec = RDataFactory.createStringVector(new String[]{"abc", longString}, true);
+        byte[] serialized = RSerialize.serialize(longStringVec, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null);
+        Object unserialized = RSerialize.unserialize(RDataFactory.createRawVector(serialized));
+
+        Assert.assertTrue(unserialized instanceof RStringVector);
+        Assert.assertEquals(2, ((RStringVector) unserialized).getLength());
+        Assert.assertEquals("abc", ((RStringVector) unserialized).getDataAt(0));
+        Assert.assertEquals(longString, ((RStringVector) unserialized).getDataAt(1));
+    }
+
+    @Test
+    public void testDeserializeLongShortStrings() {
+        char[] chars = new char[1000000];
+        Arrays.fill(chars, 'x');
+        String longString = new String(chars);
+        RStringVector longStringVec = RDataFactory.createStringVector(new String[]{longString, "abc"}, true);
+        byte[] serialized = RSerialize.serialize(longStringVec, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null);
+        Object unserialized = RSerialize.unserialize(RDataFactory.createRawVector(serialized));
+
+        Assert.assertTrue(unserialized instanceof RStringVector);
+        Assert.assertEquals(2, ((RStringVector) unserialized).getLength());
+        Assert.assertEquals(longString, ((RStringVector) unserialized).getDataAt(0));
+        Assert.assertEquals("abc", ((RStringVector) unserialized).getDataAt(1));
+    }
+
+    @Test
+    public void testDeserializeShortLongShortStrings() {
+        char[] chars = new char[1000000];
+        Arrays.fill(chars, 'x');
+        String longString = new String(chars);
+        RStringVector longStringVec = RDataFactory.createStringVector(new String[]{"abc", longString, "abc"}, true);
+        byte[] serialized = RSerialize.serialize(longStringVec, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null);
+        Object unserialized = RSerialize.unserialize(RDataFactory.createRawVector(serialized));
+
+        Assert.assertTrue(unserialized instanceof RStringVector);
+        Assert.assertEquals(3, ((RStringVector) unserialized).getLength());
+        Assert.assertEquals("abc", ((RStringVector) unserialized).getDataAt(0));
+        Assert.assertEquals(longString, ((RStringVector) unserialized).getDataAt(1));
+        Assert.assertEquals("abc", ((RStringVector) unserialized).getDataAt(2));
+    }
+
+    @Test
+    public void testDeserializeShortLongShortLongStrings() {
+        char[] chars = new char[1000000];
+        Arrays.fill(chars, 'x');
+        String longString = new String(chars);
+        RStringVector longStringVec = RDataFactory.createStringVector(new String[]{"abc", longString, "abc", longString}, true);
+        byte[] serialized = RSerialize.serialize(longStringVec, RSerialize.XDR, RSerialize.DEFAULT_VERSION, null);
+        Object unserialized = RSerialize.unserialize(RDataFactory.createRawVector(serialized));
+
+        Assert.assertTrue(unserialized instanceof RStringVector);
+        Assert.assertEquals(4, ((RStringVector) unserialized).getLength());
+        Assert.assertEquals("abc", ((RStringVector) unserialized).getDataAt(0));
+        Assert.assertEquals(longString, ((RStringVector) unserialized).getDataAt(1));
+        Assert.assertEquals("abc", ((RStringVector) unserialized).getDataAt(2));
+        Assert.assertEquals(longString, ((RStringVector) unserialized).getDataAt(3));
+    }
+}
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
index 134b0b01d3aeaa3f7ebe0ea709c59639fd178f46..a419f8ff22805537f4df67539b1f2b4e7cfd2fb4 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java
@@ -38,6 +38,7 @@ import java.util.concurrent.atomic.AtomicInteger;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 
 import com.oracle.truffle.api.debug.Breakpoint;
@@ -51,11 +52,9 @@ import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.api.vm.PolyglotEngine.Value;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
+import com.oracle.truffle.r.launcher.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RSource;
-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.ChildContextInfo;
 import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
 import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -75,8 +74,7 @@ public class FastRDebugTest {
     public void before() {
         suspendedEvent = null;
 
-        ConsoleHandler consoleHandler = new DefaultConsoleHandler(System.in, out);
-        ContextInfo info = ContextInfo.createNoRestore(Client.R, null, ContextKind.SHARE_NOTHING, null, consoleHandler);
+        ChildContextInfo info = ChildContextInfo.createNoRestore(Client.R, null, ContextKind.SHARE_NOTHING, null, System.in, out, err);
         engine = info.createVM(PolyglotEngine.newBuilder().setOut(out).setErr(err));
         debugger = Debugger.find(engine);
         debuggerSession = debugger.startSession(event -> {
@@ -154,6 +152,39 @@ public class FastRDebugTest {
         assertEquals("Factorial computed OK", 2, n.intValue());
     }
 
+    /**
+     * Test is currently ignored because of missing functionality in Truffle.
+     */
+    @Test
+    @Ignore
+    public void testConditionalBreakpoint() throws Throwable {
+        final Source source = RSource.fromTextInternal("main <- function() {\n" +
+                        "  for(i in seq(10)) {\n" +
+                        "    print(i)\n" +
+                        "  }\n" +
+                        "}\n",
+                        RSource.Internal.DEBUGTEST_DEBUG);
+        engine.eval(source);
+
+        run.addLast(() -> {
+            assertNull(suspendedEvent);
+            assertNotNull(debuggerSession);
+            Breakpoint breakpoint = Breakpoint.newBuilder(source).lineIs(3).build();
+            breakpoint.setCondition("i == 5");
+            debuggerSession.install(breakpoint);
+        });
+
+        assertLocation(3, "print(i)", "i", "5");
+        continueExecution();
+
+        // Init before eval:
+        performWork();
+
+        final Source evalSrc = RSource.fromTextInternal("main()\n", RSource.Internal.DEBUGTEST_DEBUG);
+        engine.eval(evalSrc);
+        assertExecutedOK();
+    }
+
     @Test
     public void stepInStepOver() throws Throwable {
         final Source factorial = createFactorial();
@@ -610,5 +641,4 @@ public class FastRDebugTest {
             run.removeFirst().run();
         });
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
index 15ec247889d6c0b2bcdd40c0e010583daff30c58..363accb8c931dbb8a2654bd0d5687037f1fa666b 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
@@ -29,12 +29,7 @@ import org.junit.Test;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.api.vm.PolyglotEngine.Builder;
-import com.oracle.truffle.r.runtime.RCmdOptions.Client;
 import com.oracle.truffle.r.runtime.RSource;
-import com.oracle.truffle.r.runtime.context.ConsoleHandler;
-import com.oracle.truffle.r.runtime.context.ContextInfo;
-import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
-import com.oracle.truffle.r.test.generate.FastRSession.TestConsoleHandler;
 import com.oracle.truffle.tck.TruffleTCK;
 
 public class FastRTckTest extends TruffleTCK {
@@ -131,13 +126,13 @@ public class FastRTckTest extends TruffleTCK {
         "  length(o)\n" +
         "}\n" +
         "isNullOfForeign <- function(o) {\n" +
-        "  .fastr.interop.toBoolean(.fastr.interop.isNull(o))\n" +
+        "  .fastr.interop.toBoolean(is.external.null(o))\n" +
         "}\n" +
         "hasSizeOfForeign <- function(o) {\n" +
-        "  .fastr.interop.toBoolean(.fastr.interop.hasSize(o))\n" +
+        "  .fastr.interop.toBoolean(is.external.array(o))\n" +
         "}\n" +
         "isExecutableOfForeign <- function(o) {\n" +
-        "  .fastr.interop.toBoolean(.fastr.interop.isExecutable(o))\n" +
+        "  .fastr.interop.toBoolean(is.external.executable(o))\n" +
         "}\n" +
         "intValue <- function() 42L\n" +
         "intVectorValue <- function() c(42L, 40L)\n" +
@@ -153,18 +148,16 @@ public class FastRTckTest extends TruffleTCK {
         "builtinFunctionType <- function() 'builtin'\n" +
         "valueWithSource <- function() intValue\n" +
         "objectWithKeyInfoAttributes <- function() { list(rw=1, invocable=function(){ 'invoked' }) }\n" +
-        "for (name in ls()) .fastr.interop.export(name, get(name))\n",
+        "for (name in ls()) export(name, get(name))\n",
         RSource.Internal.TCK_INIT
     );
     // @formatter:on
 
     @Override
     protected PolyglotEngine prepareVM(Builder builder) throws Exception {
-        ConsoleHandler consoleHandler = new TestConsoleHandler();
-        ContextInfo info = ContextInfo.createNoRestore(Client.R, null, ContextKind.SHARE_NOTHING, null, consoleHandler);
-        PolyglotEngine vm = info.createVM(builder);
-        vm.eval(INITIALIZATION);
-        return vm;
+        PolyglotEngine engine = builder.build();
+        engine.eval(INITIALIZATION).get();
+        return engine;
     }
 
     @Override
@@ -219,10 +212,7 @@ public class FastRTckTest extends TruffleTCK {
 
     @Override
     protected String invalidCode() {
-        // @formatter:off
-        return
-            "main <- function() {\n";
-        // @formatter:on
+        return "main <- function() {\n";
     }
 
     @Override
@@ -510,5 +500,4 @@ public class FastRTckTest extends TruffleTCK {
     protected String objectWithKeyInfoAttributes() {
         return "objectWithKeyInfoAttributes";
     }
-
 }
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java
index cfacee313efc9f28ef9e23ec75dd7b4e9585d6b0..bc922bc30ec184e30a7417afbb5b182ca0e4e9fe 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RBuiltinCheck.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,9 +39,9 @@ import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
+import com.oracle.truffle.r.launcher.RVersionNumber;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinFactory;
 import com.oracle.truffle.r.nodes.builtin.base.BasePackage;
-import com.oracle.truffle.r.runtime.RVersionNumber;
 import com.oracle.truffle.r.runtime.RVisibility;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
@@ -269,7 +269,7 @@ public final class RBuiltinCheck {
         BasePackage base = new BasePackage();
         Map<String, BuiltinInfo> result = new TreeMap<>();
         for (Map.Entry<String, RBuiltinFactory> builtin : base.getBuiltins().entrySet()) {
-            Class<?> clazz = builtin.getValue().getBuiltinNodeClass();
+            Class<?> clazz = builtin.getValue().getBuiltinMetaClass();
             RBuiltin annotation = clazz.getAnnotation(RBuiltin.class);
             result.put(builtin.getKey(), new BuiltinInfo(
                             builtin.getValue().getVisibility(),
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
deleted file mode 100644
index 425f866eadf01fc9692976e6c412df6dfdca39c2..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tools/RFFIUpCallMethodGenerate.java
+++ /dev/null
@@ -1,133 +0,0 @@
-/*
- * Copyright (c) 2017, 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.tools;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.Arrays;
-import java.util.Comparator;
-
-import com.oracle.truffle.r.nodes.ffi.RFFIUpCallMethod;
-import com.oracle.truffle.r.runtime.ffi.RFFICstring;
-
-/**
- * Generates the entries for {@link RFFIUpCallMethod}.
- */
-public class RFFIUpCallMethodGenerate {
-
-    public static void main(String[] args) throws Exception {
-        String klassName = "com.oracle.truffle.r.runtime.ffi.UpCallsRFFI";
-        boolean klassArg = false;
-
-        int i = 0;
-        while (i < args.length) {
-            String arg = args[i];
-            if (arg.equals("--class")) {
-                i++;
-                klassName = args[i];
-                klassArg = true;
-            }
-            i++;
-        }
-
-        Class<?> klass = Class.forName(klassName);
-        Method[] methods = klassArg ? klass.getDeclaredMethods() : klass.getMethods();
-
-        Arrays.sort(methods, new Comparator<Method>() {
-
-            @Override
-            public int compare(Method a, Method b) {
-                return a.getName().compareTo(b.getName());
-            }
-
-        });
-        for (i = 0; i < methods.length; i++) {
-            Method m = methods[i];
-            if (klassArg && (Modifier.isStatic(m.getModifiers()))) {
-                continue;
-            }
-            String sig = getNFISignature(m);
-            System.out.printf("%s(\"%s\")%s%n", m.getName(), sig, i == methods.length - 1 ? ";" : ",");
-        }
-
-    }
-
-    private static String getNFISignature(Method m) {
-        Class<?>[] paramTypes = m.getParameterTypes();
-        Annotation[][] annotations = m.getParameterAnnotations();
-        StringBuilder sb = new StringBuilder();
-        sb.append('(');
-        for (int i = 0; i < paramTypes.length; i++) {
-            Class<?> paramType = paramTypes[i];
-            String nfiParam = nfiParamName(paramType, annotations[i]);
-            sb.append(nfiParam);
-            if (i != paramTypes.length - 1) {
-                sb.append(", ");
-            }
-        }
-        sb.append(')');
-        sb.append(" : ");
-        sb.append(nfiParamName(m.getReturnType(), new Annotation[0]));
-        return sb.toString();
-    }
-
-    static String nfiParamName(Class<?> paramType, Annotation[] annotations) {
-        String paramName = paramType.getSimpleName();
-        RFFICstring rffiCstring = null;
-        if (annotations.length > 0) {
-            for (Annotation annotation : annotations) {
-                if (annotation instanceof RFFICstring) {
-                    rffiCstring = (RFFICstring) annotation;
-                    break;
-                }
-            }
-        }
-        switch (paramName) {
-            case "Object":
-                if (rffiCstring == null) {
-                    return "object";
-                } else {
-                    return rffiCstring.convert() ? "string" : "pointer";
-                }
-            case "char":
-                return "uint8";
-            case "int":
-                return "sint32";
-            case "double":
-                return "double";
-            case "void":
-                return "void";
-            case "int[]":
-                return "[sint32]";
-            case "double[]":
-                return "[double]";
-            case "byte[]":
-                return "[uint8]";
-            default:
-                return "object";
-        }
-
-    }
-
-}
diff --git a/documentation/Index.md b/documentation/Index.md
index c98e248efef019be1db7917eab74484fd939a41a..393dcd24acb72e76d2e3f3c05b408a00b2986d3d 100644
--- a/documentation/Index.md
+++ b/documentation/Index.md
@@ -7,3 +7,5 @@
 [For Developers](dev/Index.md)
 
 [Debugging](debugging.md)
+
+[Graphics support](graphics.md)
diff --git a/documentation/allocprof.md b/documentation/allocprof.md
new file mode 100644
index 0000000000000000000000000000000000000000..3358da8b7721e521e009fbb2aa4a2127d47e951d
--- /dev/null
+++ b/documentation/allocprof.md
@@ -0,0 +1,83 @@
+# FastR Allocation Profiler - Getting Started 
+
+The basic usage is illustrated by the following examples:
+
+* Activating the profiling instrument
+```
+.fastr.profmem(TRUE)
+```
+
+* Actual profiling 
+```
+example(glm)
+```
+* Creating a snapshot
+```
+s1 <- .fastr.profmem.snapshot("s1")
+```
+* Displaying the result
+```
+.fastr.profmem.show(snapshot=s1)
+```
+producing:
+```
+/<main>[id=0] { size: 35155856, count: 140515 }
+/<main>[id=0]/example[id=2788] { size: 17197400, count: 87422 }
+/<main>[id=0]/example[id=2788]/source[id=2987] { size: 16747568, count: 82327 }
+/<main>[id=0]/example[id=2788]/source[id=2987]/source[id=3107] { size: 14999312, count: 76365 }
+/<main>[id=0]/example[id=2788]/source[id=2987]/source[id=3107]/source[id=3108] { size: 10815880, count: 56889 }
+/<main>[id=0]/example[id=2788]/source[id=2987]/source[id=3107]/source[id=3108]/eval[id=3109] { size: 10784176, count: 56823 }
+/<main>[id=0]/example[id=2788]/source[id=2987]/source[id=3107]/source[id=3108]/eval[id=3109]/<no source>[id=8056] { size: 4317704, count: 684 }
+/<main>[id=0]/example[id=2788]/source[id=2987]/source[id=3107]/source[id=3108]/eval[id=3109]/<no source>[id=8056]/<no source>[id=8058] { size: 4317704, count: 684 }
+```
+
+* Displaying the result, 3 top levels only
+```
+.fastr.profmem.show(3, snapshot=s1)
+```
+producing:
+```
+/<main>[id=0] { size: 35140384, count: 140294 }
+/<main>[id=0]/example[id=2788] { size: 17197400, count: 87422 }
+/<main>[id=0]/example[id=2788]/source[id=2987] { size: 16747568, count: 82327 }
+/<main>[id=0]/example[id=2788]/source[id=2803] { size: 292256, count: 3114 }
+/<main>[id=0]/example[id=2788]/source[id=2969] { size: 5456, count: 47 }
+/<main>[id=0]/example[id=2788]/source[id=2978] { size: 3024, count: 26 }
+/<main>[id=0]/example[id=2788]/source[id=2789] { size: 824, count: 15 }
+/<main>[id=0]/example[id=2788]/source[id=2796] { size: 112, count: 2 }
+/<main>[id=0]/example[id=2788]/source[id=2973] { size: 88, count: 2 }
+/<main>[id=0]/example[id=2788]/source[id=2986] { size: 56, count: 1 }
+/<main>[id=0]/example[id=2788]/source[id=2795] { size: 32, count: 1 }
+/<main>[id=0]/example[id=2788]/source[id=2977] { size: 0, count: 0 }
+```
+* Showing the source associated with a stack entry
+```
+# stack entry id = 2630
+.fastr.profmem.source(2630, snapshot=s1)
+```
+producing:
+```
+<<<  at 53:9
+txt <- unlist(x)
+>>>  at 53:24
+```
+* Showing the hot-spots
+```
+# single-level hospot view
+.fastr.profmem.show(2, snapshot=s1, view = "hotspots")
+# unlimited hostspot view
+.fastr.profmem.show(snapshot=s1, view = "hotspots")
+# show the source of the entry 2630 from the hostspot view on the snapshot s1
+.fastr.profmem.source(2630, view="hotspots", snapshot=s1)
+```
+* Deactivating the profilinig instrument
+```
+.fastr.profmem(FALSE)
+```
+
+The `.fastr.profmem.show` builtin offers several arguments for controlling the output:
+
+* `levels`: determines the maximum number of levels displayed
+* `desc`: specifies the sorting order, which is TRUE by default, ie. descending
+* `id`: displays only the sub tree of the specified stack entry
+* `printParents`: forces printing the parent stack entries. It is meaningful in connection with a nun-NULL id parameter value only.
\ No newline at end of file
diff --git a/documentation/dev/managed_ffi.md b/documentation/dev/managed_ffi.md
index 4e07641430cc13487e861d24c288b7e112db7a2a..22f9d046fba35fe8ec4e8f10403d4d496dc1c3e0 100644
--- a/documentation/dev/managed_ffi.md
+++ b/documentation/dev/managed_ffi.md
@@ -1,25 +1,25 @@
 
 # Quick start
-FastR supports a 'managed' mode, in which it does not execute any native code directly, especially code coming from GNU R and packages, 
-and tries to avoid other potentially security sensitive code, e.g. instrumentation agents. To enable this mode, clean build and run 
-FastR with environment variable `FASTR_MANAGED` set to *true*.
+FastR supports a 'managed' mode, in which it does not execute any native code directly, especially code coming from GNU R and packages,
+and tries to avoid other potentially security sensitive code, e.g. instrumentation agents. To enable this mode, clean build and run
+FastR with environment variable `FASTR_RFFI` set to `managed`.
 
 # Details
-FastR has an 'implementation' of RFFI that does not use any native code directly (e.g. through JNI) and implements only small subset of the API. 
-Any usage of the unimplemented parts will cause error at runtime. To enable this RFFI implementation clean build FastR with environment variable 
-`FASTR_RFFI` set to *managed* and when running FastR set java property named *fastr.rffi.factory.class* to 
+FastR has an 'implementation' of RFFI that does not use any native code directly (e.g. through JNI) and implements only small subset of the API.
+Any usage of the unimplemented parts will cause error at runtime. To enable this RFFI implementation clean build FastR with environment variable
+`FASTR_RFFI` set to *managed* and when running FastR set java property named *fastr.rffi.factory.class* to
 `com.oracle.truffle.r.runtime.ffi.managed.Managed_RFFIFactory`.
 
 There are additional options that can restrict other usages of native code in FastR:
 
-* When FastR option `LoadPackagesNativeCode=false`, then FastR does not load builtin packages (graphics and base) native code. 
+* When FastR option `LoadPackagesNativeCode=false`, then FastR does not load builtin packages (graphics and base) native code.
 Note that loading of their native code is going to fail with *managed* RFFI implementation.
-* When FastR option `LoadProfiles=false`, then FastR does not load user profile, machine profile etc. Those scripts typically use 
+* When FastR option `LoadProfiles=false`, then FastR does not load user profile, machine profile etc. Those scripts typically use
 some R code that ends up trying to call native code, which is again going to fail with *managed* RFFI implementation.
-* Set `FastRConfig#InternalGridAwtSupport` to `false` before building FastR. This should remove usages of AWT from FastR's 
+* Set `FastRConfig#InternalGridAwtSupport` to `false` before building FastR. This should remove usages of AWT from FastR's
 bytecode and thus reduce the amount of native code that can be invoked by running arbitrary R code in FastR.
 
 Following option can be useful for improving security when running FastR:
 
-* Set java property *fastr.objectsize.factory.class*  to `com.oracle.truffle.r.runtime.data.SimpleObjectSizeFactory` to avoid 
+* Set java property *fastr.objectsize.factory.class*  to `com.oracle.truffle.r.runtime.data.SimpleObjectSizeFactory` to avoid
 usage of otherwise more precise `AgentObjectSizeFactory`, which uses instrumentation agent.
diff --git a/documentation/dev/testing.md b/documentation/dev/testing.md
index a5a2718be1a78c80dc8ebd3ccca71ea017dbd3a9..bfcd1a4f90095744595a0ce2a233895714882ba6 100644
--- a/documentation/dev/testing.md
+++ b/documentation/dev/testing.md
@@ -7,18 +7,30 @@ The unit testing works by executing the R test and the comparing the output with
 
 ## Unit Tests
 
-The unit tests reside mainly in the `com.oracle.truffle.r.test` project, with a smaller number in the and `com.oracle.truffle.r.nodes.test` project. To execute the unit tests use the `mx junit` command. The standard set of unit tests is available via the `mx junitdefault` command and the following additional variants are available:
+The unit tests reside mainly in the `com.oracle.truffle.r.test` project, with a smaller number in the `com.oracle.truffle.r.nodes.test` project. The execution of the tests uses the `unittest` command that is built into `mx` and
+used by all the Truffle languages. See `mx unittest --help` for a complete description of the options. Certain system properties are used to control the test environment, a;; of which begin with `fastr.test`.
 
-1. `mx junitsimple`: everything except the package tests and the `com.oracle.truffle.r.nodes.test`
-2. `mx junit --tests list`: `list` is a comma-separated list of test patterns, where a pattern is a package or class. For example to just run the "builtin" tests run `mx junit --tests com.oracle.truffle.r.test.builtins`.
+1. `fastr.test.trace.tests`: this causes the specific test method being executed to be output to the standard output. A sometimes useful debugging tool.
+2. `fastr.test.check.expected`: this can be used in combination with `fastr.test.generate` to checked whether `ExpectedTestOutput.test` is in sync with the current set of tests.
+3. `fastr.test.generate`: Used internally by `mx rtestgen`, see below.
+4. `fastr.test.generate.quiet`; Used internally by `mx rtestgen`, see below.
 
-As with most FastR `mx` commands, additional parameters can be passed to the underlying FastR process using the `--J` option. For example to debug a unit test under an IDE, it is important to disable the internal timeout mechanism that detects looping tests, vis:
+For convenience and backwards compatibility FastR provides some wrapper commands that invoke `unittest` with specific arguments.
+In particular the standard set of unit tests is available via the `mx junitgate` command and the following additional variants are available:
 
-    mx -d junit --tests sometestclass --J @-DDisableTestTimeout
+1. `mx rutsimple`: everything except the tests in `com.oracle.truffle.r.nodes.test`
+2. `mx rutgate`: all the tests that run in the gate
+
+
+For example to debug a unit test under an IDE, it is important to disable the internal timeout mechanism that detects looping tests, vis:
+
+    mx -d unittest -Dfastr.test.timeout sometestclass
+
+Note that no value for `fastr.test.timeout` is treated as in infinite timeout. Any other value is expected to be an integer value, interpreted as seconds.
 
 ### Regenerating ExpectedTestOutput.test
 
-After adding, removing or altering units tests (including the `TestTrait` argument), it is necessary to regenerate the GNU R output, vis:
+After adding, removing or altering units tests (including the `TestTrait` argument), it is necessary to regenerate the `ExpectedTestOutput.test` file, vis:
 
     mx rtestgen
 
diff --git a/documentation/dev/truffle_llvm_ffi.md b/documentation/dev/truffle_llvm_ffi.md
index 511d667d43f38135dc850ca0aa6ed0ae5e01da8a..c0cbb908c0ec77477037ff3386533ea9fb05fa80 100644
--- a/documentation/dev/truffle_llvm_ffi.md
+++ b/documentation/dev/truffle_llvm_ffi.md
@@ -6,58 +6,86 @@ The Truffle implementation of the R FFI is based on the Truffle implementation o
 # Building
 Special setup is required to build FastR to use the Truffle R FFI implementation.
 
+## Pre-Requisites
+
+The DragonEgg plugin requires that `gcc 4.6` and `gfortran 4.6` be available.
+
+On Mac OS, these can be installed with MacPorts (recommended) or Brew. Having installed these, set the following environment variables:
+
+    export SULONG_GPP=/opt/local/bin/g++-mp-4.6
+    export SULONG_GFORTRAN=/opt/local/bin/gfortran-mp-4.6
+    export SULONG_GCC=/opt/local/bin/gcc-mp-4.6
+
+The above definitions assume a MacPorts installation.
+
+On Linux, the installation is system dependent, but once installed, set the same environment variables.
+
 ## Building Sulong
 The `sulong` repository must be cloned to a sibling directory of `fastr` and built:
 
     cd $FASTR_HOME
     git clone https://github.com/graalvm/sulong.git
     cd sulong
-    mx build
     mx su-pulldragonegg
 
-The `mx build` step will clone the `compiler` repository, if necessary, and build that also. The `mx su-pulldragonegg` step is required to be able to compile Fortran code to LLVM, which is required by FastR.
+The `mx su-pulldragonegg` step is required to be able to compile Fortran code to LLVM, which is required by FastR.. As well as downloading DragonEgg this will also download and clang 3.2, which is needed to build DragonEgg. On Linux, it is necessary to use clang 3.2 in preference to any installed clang, e.g., 3.8, as some of the LLVM code generated by DragonEgg is syntax-incompatible with 3.8. The downloaded version is saved in `cache/tools/llvm/bin`. Since DragonEgg only needs to be built once per platform, the shared library can be copied from the sulong tree (search for `draghonegg.so`) into a shared location foir use with FastR.
 
-## Additional Pre-Requisites
+Once `dragonegg` is built, unset the `SULONG_GCC`, `SULONG_GFORTRAN` and `SULONG_GPP` environment variables.
 
-The DragonEgg plugin requires that `gcc 4.6` and `gfortran 4.6` be available. On Mac OS, these can be installed with MacPorts (recommended) or Brew. Having installed these, set the following environment variables:
+Sulong must be built with a more recent version of `clang` than 3.2, which means that `sulong` and `fastr` cannot be built in one step.
+First make sure that you have a supported version of `clang` and related tools installed, e.g., 3.8 and that they are on your `PATH`. Also if you are on MacOS and are using MacPorts, you must make symbolic links to the explicitly versioned tool names, i.e. `clang` -> `clang-mp-3.8`. This also applies to the `opt` and `llvm-link` tools. You can set these links directly in `/opt/local/bin` using `sudo` or create a local `bin` directory and place the links there, making sure that this directory is on your `PATH`.
 
-    export SULONG_GPP=/opt/local/bin/g++-mp-4.6
-    export SULONG_GFORTRAN=/opt/local/bin/gfortran-mp-4.6
-    export SULONG_GCC=/opt/local/bin/gcc-mp-4.6
+ and this (absolute) path should be added to `PATH`.
 
-The above definitions assume a MacPorts installation.
+Now the remainder of sulong can be built.
+
+    mx build
 
-Both GNU R and FastR native code must be compiled to generate LLVM code. This is handled by special "wrapper" compiler scripts that encapsulate the required steps.
-To ensure that the wrapper compiler scripts are used in the GNU R build set:
+The `mx build` step will clone the `graal` repository, if necessary, and build the `truffle` suite also.
 
-    export FASTR_TRUFFLE_RFFI=true
+## Building FastR
 
-If you have an existing build, you must unset any definition of `GNUR_NOCLEAN` then run `mx build -c`. The wrapper scripts add quite a bit of overhead to the build process, particularly the GNU R configure step, but fortunately this only has to be done once.
+To ensure that an LLVM build variant is chosen, set:
 
-## Running
+    export FASTR_RFFI=llvm
+
+N.B. It is necessary to inform the build of the location of the various required libraries, e.g. `libpcre` as these are loaded explicitly from the `lib` directory at runtime. The build copies these libraries from wherever they were installed to the `lib` directory. For example on Ubuntu, set:
+
+    export PKG_LDFLAGS_OVERRIDE=-L/lib/x86_64-linux-gnu
+
+On Mac OS (with MacPorts) set:
 
-There is no compile-time dependency between FastR and Sulong; all communication is via the Truffle Interop API. Therefore Sulong must be dynamically imported using either `mx --dynamicimport sulong` or by setting the environment variable `DEFAULT_DYNAMIC_IMPORTS=sulong`, with latter being most convenient. With this in effect, a normal `mx R` will make SuLong available. In particular, the factory class that controls which FFI implementation is in used is chosen based on whether Sulong is available.
+    export PKG_LDFLAGS_OVERRIDE="-L/opt/local/lib -L/opt/local/lib/libgcc"
 
-Even then, by default, the Truffle FFI implementation is not enabled and the system defaults to the normal JNI RFFI implementation, in order to support an
-incremental approach to enabling native code for LLVM implementation. To enable one or more packages (strictly their associated dynamic libraries) for LLVM implementation, set the environment variable `FASTR_TRUFFLE_LIBS` to a comma-separated list of library names, e.g. `stats,testrffi`. If this variable is unset,and the Truffle RFFI factory class is enabled, a warning is given on every library open that the load is defaulting to the JNI implementation.
+FastR necessarily provides very fine control over the versions of the llvm tools that are used, through environment variables all beginning with `FASTR_LLVM`. It also allows FastR to be completely independent from sulong. The following variables are mandatory:
 
-At the time of writing, only the following libraries have been tested in LLVM mode:
+`FASTR_LLVM_DRAGONEGG`: the location of the DragonEgg plugin (shared library built above)
+`FASTR_LLVM_GFORTRAN`: a 4.6 version of `gfortran` (see `SULONG_GFORTRAN` above)
+`FASTR_LLVM_GFORTRAN_LLVM_AS`: a 3.2 version of the `llvm-as` tool. N.B. this is created in sulong as part of the `DragonEgg` build. This can also be copied to a shared location.
 
-* `liburand`: this is not actually a package library, but a test for the user-defined random number generator feature of R. It lives in the
-`com.oracle.truffle.r.test.native/urand` directory and must be loaded explicitly using `dyn.load`. See the `TestUserRNG` class for an example of how to test it.
-* `testrffi`: This is the (evolving) RFFI test package that lives in `com.oracle.truffle.r.test.native/packages/testrffi`. It must first be installed by e.g, `bin/R CMD INSTALL com.oracle.truffle.r.test.native/packages/testrffi/lib/testrffi.tar`. As always this will install to the location specified by the `R_LIBS_USER` or `R_LIBS` environment variables or, if unset, the FastR `library` directory. An example test would then be to execute `library(testrffi); rffi.addDouble(2,3)` after running `mx R`.
-* `stats`: Most of the native code in the GNU R `stats` package has either been rewritten in Java or temporarily disabled. However, the Fast Fourier Transform code is written in C and called through the FFI. E.g. `fft(1:4)` is a simple test.
-* `digest`: This is a CRAN package that contains a significant amount of native code, relating to MD5 and SHA digest generation. The simple way to install and test this is to execute: `mx pkgtest '^digest$'`. This assumes an internet connection is available to access CRAN.
+The tools needed to build FastR and to install packages containing native code are `clang`, `clang++` and `opt`. Precisely which versions of these tools are used can be controlled in two ways.
 
-Note that if the `LLVM_PARSE_TIME` environment variable is set to any value, the time taken to parse each LLVM module is logged to the console, which is also an indication that the LLVM implementation variant is being used.
+1. Set `FASTR_LLVM_HOME` to a directory containing the tools, named as above. N.B. Since MacPorts uses names of the form `clang-mp-3.8` this requires using symbolic links. E.g. create a directory called, say, `llvm-3.8` and symlink to the MacPorts binary, e.g., `clang-mp-3.8` and name it as `clang`. Then set `FASTR_LLVM_HOME` to that directory.
+2. Set `FASTR_LLVM_CLANG`, `FASTR_LLVM_CLANGPP` and `FASTR_LLVM_OPT` to the actual binary images, e.g., `export FASTR_LLVM_CLANG=/opt/local/bin/clang-mp-3.8`.
+
+Not all versions of the llvm tools can compile FastR. `clang-3.2` that is downloaded as part of the DragonEgg build is known to work. This currently is placed in `sulong/cache/tools/llvm/bin` by the DragonEgg build and, again, can be copied to a shared location. `clang-3.8` and `clang-4.0` are known not to work, but `clang-3.9` does.
+
+Once the above is set up, run `mx build`.
+
+## Running
+
+There is no compile-time dependency between FastR and Sulong; all communication is via the Truffle Interop API. Therefore Sulong must be dynamically imported using either `mx --dynamicimport sulong` or by setting the environment variable `DEFAULT_DYNAMIC_IMPORTS=sulong`, with latter being most convenient. With this in effect, a normal `mx R` will make Sulong available.
+
+Note that if the `LLVM_PARSE_TIME` environment variable is set to any value, the time taken to parse each LLVM module is logged to the console, which is also a check that the LLVM implementation variant is being used.
 
 # Implementation Details
 
 ## Compiler Wrapper Scripts
 
-The compiler wrapper scripts are simple shell scripts that first test for the existence of the `sulong` sibling directory and, if it exists and the environment variable `FASTR_SULONG_IGNORE` is not set, invoke associated `mx` commands to perform the compilation. Otherwise, the standard compiler is used. The scripts are stored in the `compilers` sub-directory of `mx.fastr` and are named: `fastr-cc`, `fastr-fc`, `fastr-c++` and `fastr-cpp`. The associated `mx` commands are in `mx.fastr/mx_fastr_compilers.py`.
-
-In order to support both LLVM and non-LLVM execution, each native source file is compiled twice, once to generate native machine code and once to generate LLVM IR. The LLVM IR is actually stored in the object file and extracted at runtime. This avoids having to disrupt the normal R package build process by allowing it to be completely unaware of the existence of LLVM.
+Compiler wrapper scripts are used to map the commands generated the `make` into an appropriate set of llvm tool invocations. This way no change is required to the `Makefile`s or the R package installation process.
+Once Fastr is built, the scripts are stored in the `bin` sub-directory and are named: `llvm-cc`, `llvm-fc` and `llvm-c++`, for use during package installation.
 
-Currently, for convenience, the Python wrappers invoke code in the Sulong `sulong/mx.sulong` directory. Eventually, they will modified to be independent of Sulong.
+The scripts normally operate silently. However, if `FASTR_LLVM_TOOLMODE`is set to `echorun`, the actual llvm tool commands resulting from the normal C/C++/Fortran command will be echoed to the standard output.
 
+## Limitations
+At the time of writing all the `RFFI` interfaces are implemented for LLVM. However, owing to a bug in DragonEgg, the actual Fortran code for the Lapack library is not executed under LLVM, only the wrapper.
diff --git a/documentation/graphics.md b/documentation/graphics.md
new file mode 100644
index 0000000000000000000000000000000000000000..8cd2bfb9a4fa981c99f8ea45bd98b4c41523247a
--- /dev/null
+++ b/documentation/graphics.md
@@ -0,0 +1,97 @@
+# Introduction
+
+There are two main built-in R packages that provide basic graphical output 
+support: *graphics* and *grid*. They both use some parts of even lower level
+*grDevices* package, which allows users to change the "device" to which the 
+graphical output will be drawn. The probably most popular graphical packages 
+*lattice* and *ggplot2* are build on top of the *grid* package.
+
+FastR has its own implementation of the *grid* package and it also emulates 
+the most important R level functions from the *grDevices* package. This 
+implementation is purely Java based and has been tested to work with 
+the unmodified *lattice* package, support for unmodified *ggplot2* package 
+is work in progress.
+
+Any functions from the *graphics* package are not going to work with FastR, 
+namely e.g. the `plot` function. R documentation, which can be displayed by 
+typing `?functionName` can be used to determine if a function is from *graphics* 
+or *grid* package or potentially from some *grid* based higher level package.
+
+The longer term goal is to emulate R level *graphics* package functions by 
+means of *grid* package drawing primitives.
+
+# Examples
+
+The *grid* package is distributed with FastR, but not loaded by default, 
+therefore one has to load it using the `library` function. Following example 
+draws a red rectangle in the center of the screen.
+
+```
+library(grid)
+grid.rect(width=0.5, height=0.5, gp=gpar(col='red'))
+```
+
+The *lattice* package must be installed using:
+
+```
+install.packages('lattice');
+```
+
+With the *lattice* package installed, one can run the 
+following example showing a barchart.
+
+```
+library(lattice)
+mtcars$cars <- rownames(mtcars)
+barchart(cars~mpg, data=mtcars)
+```
+
+# Devices Support
+
+FastR supports the following devices:
+
+* awt: opens a new AWT window for drawing, the window can be resized and 
+its contents can be saved with the standard `savePlot` function. 
+This is the default device for interactive sessions. 
+In FastR, for compatibility with GNU R, *X11* device is alias for the *awt* device.
+
+* svg: generates SVG image, which is saved into a specified file. 
+The contents may be read into a character vector by FastR specific function 
+`grDevices:::svg.off()`. FastR produces the SVG code directly from *grid* drawing commands, 
+therefore the SVG code may look more SVG idiomatic and resembling the R code that created it, 
+but may produce visually slightly different image compared to other devices. 
+This device is default for non-interactive FastR sessions.
+
+* jpg, png, bmp: these devices create an image file of specified format. Unlike the SVG device, 
+these are also based on the AWT framework.
+
+Devices that generate file take filename as an argument. The file will be saved on disk only 
+once the standard `dev.off()` function is called. FastR honors the "device" option, which 
+may override the default device. See the documentation of *grDevices* package for more details.
+
+# Java Interoperability
+
+The `grDevices::awt` function can accept `java.awt.Graphics2D` object and width and height in AWT units, 
+in which case all the drawing will be done using that object. Example:
+
+```
+grDevices:::awt(420, 420, graphicsObj);
+```
+
+One possible use case is to create a Java based UI with a `JPanel` that will be 
+used for visualizing some data from R. Override the `JPanel`'s `paint` 
+method and pass the graphics object to R code using `PolyglotEngine`. 
+The R code can do any *grid* based visualization and it will be directly 
+displayed in the UI.
+
+# Limitations
+
+FastR's grid implementation does not yet support:
+
+* expressions in `grid.text`
+* `grid.xspline` function
+* clipping
+
+FastR does not plan to implement the R graphics engine display list
+and related functions. However, the grid display list is implemented.
+
diff --git a/documentation/tutorials/debugging/InteropDebugging/JS/main.js b/documentation/tutorials/debugging/InteropDebugging/JS/main.js
new file mode 100644
index 0000000000000000000000000000000000000000..a1d81827fbda13ae1b5ee5f906f78c4f8a1ec3b3
--- /dev/null
+++ b/documentation/tutorials/debugging/InteropDebugging/JS/main.js
@@ -0,0 +1,5 @@
+var greeting = "Ahoy";
+var greet = function (x) {
+    console.log(x);
+}
+greet(greeting);
\ No newline at end of file
diff --git a/mx.fastr/compilers/fastr-fc b/documentation/tutorials/debugging/InteropDebugging/R/main.r
old mode 100755
new mode 100644
similarity index 59%
rename from mx.fastr/compilers/fastr-fc
rename to documentation/tutorials/debugging/InteropDebugging/R/main.r
index e5f506854e54513bd3dacbe95f94690dfd99fce3..383ea6ece226525c9655b32628a0ae1df3e6de50
--- a/mx.fastr/compilers/fastr-fc
+++ b/documentation/tutorials/debugging/InteropDebugging/R/main.r
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -20,28 +20,21 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-#!/bin/bash
 
-SOURCE="${BASH_SOURCE[0]}"
-while [ -h "$SOURCE" ]; do
-  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
-  SOURCE="$(readlink "$SOURCE")"
-  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
-done
-DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
+print("Hello, World! (from file)")
+print("Creating a Java object in FastR")
 
-with_sulong=0
-while [ $DIR != "/" ] ; do
-  if [ -d $DIR/sulong ] && [ -d $DIR/sulong/mx.sulong ] ; then
-    with_sulong=1
-    break
-  fi
-  DIR=`dirname $DIR`
-done
+clazz <- new.java.class("java.util.Date")
+obj <- new.external(clazz, as.external.long(as.integer(Sys.time())*1000))
+print(obj$toString())
 
-if [ $with_sulong = 1 ] && [ "$FASTR_SULONG_IGNORE" = "" ] ; then
-    mx --dynamicimport sulong fastr-fc $@
-else
-    gfortran $@
-fi
+# add classpath entry to be able to use our class
+java.addToClasspath("build/classes")
+clazz <- new.java.class("com.oracle.truffle.r.JavaMessage")
+obj <- new.external(clazz, "Hi there")
+print(obj$getMessage())
+
+JS_MIME_TYPE <- "application/javascript"
+eval.external(JS_MIME_TYPE, source='var s = "Hello from Javascript"; print(s)')
+eval.external(JS_MIME_TYPE, path="JS/main.js")
 
diff --git a/documentation/tutorials/debugging/InteropDebugging/manifest.mf b/documentation/tutorials/debugging/InteropDebugging/manifest.mf
new file mode 100644
index 0000000000000000000000000000000000000000..328e8e5bc3b7f1f7bad2bc0751a933e00c801983
--- /dev/null
+++ b/documentation/tutorials/debugging/InteropDebugging/manifest.mf
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+X-COMMENT: Main-Class will be added automatically by build
+
diff --git a/documentation/tutorials/debugging/InteropDebugging/src/com/oracle/truffle/r/JavaMessage.java b/documentation/tutorials/debugging/InteropDebugging/src/com/oracle/truffle/r/JavaMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..a6ea29c3593eadf08671ee6bda744263f420bb97
--- /dev/null
+++ b/documentation/tutorials/debugging/InteropDebugging/src/com/oracle/truffle/r/JavaMessage.java
@@ -0,0 +1,47 @@
+/*
+ * 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.
+ */
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.truffle.r;
+
+public class JavaMessage {
+
+    private String message;
+
+    public JavaMessage(String message) {
+        this.message = message;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public String toString() {
+        return message;
+    }
+
+}
diff --git a/documentation/tutorials/debugging/InteropDebugging/src/com/oracle/truffle/r/Main.java b/documentation/tutorials/debugging/InteropDebugging/src/com/oracle/truffle/r/Main.java
new file mode 100644
index 0000000000000000000000000000000000000000..300a6e6390f598af2856a26f78a8fb2bfab53278
--- /dev/null
+++ b/documentation/tutorials/debugging/InteropDebugging/src/com/oracle/truffle/r/Main.java
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ */
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.oracle.truffle.r;
+
+import com.oracle.truffle.api.source.Source;
+import com.oracle.truffle.api.vm.PolyglotEngine;
+import java.io.File;
+import java.io.IOException;
+
+public class Main {
+
+    private static final String R_MIME_TYPE = "application/x-r";
+
+    /**
+     * @param args the command line arguments
+     * @throws java.io.IOException
+     */
+    public static void main(String[] args) throws IOException {
+        PolyglotEngine newVM = PolyglotEngine.newBuilder().config(R_MIME_TYPE, "debugContext", null).build();
+        newVM.eval(fromString("print('Hello, World! (from string)')"));
+        newVM.eval(fromFile("R/main.r"));
+    }
+    
+    private static Source fromString(String code) {
+        return Source.newBuilder(code).name("<shell_input>").mimeType(R_MIME_TYPE).interactive().build();
+    }
+    
+    private static Source fromFile(String path) throws IOException {
+        return Source.newBuilder(new File(path)).mimeType(R_MIME_TYPE).build();
+    }
+    
+}
diff --git a/documentation/tutorials/debugging/R/binSearch.r b/documentation/tutorials/debugging/R/binSearch.r
new file mode 100644
index 0000000000000000000000000000000000000000..4290216371d9b8f4725d7d2ee94d6cabf7dd1c5c
--- /dev/null
+++ b/documentation/tutorials/debugging/R/binSearch.r
@@ -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.
+#
+# Returns the index of the value in the sorted vector.
+binSearch <- function(vec, value) {
+  low <- 1L
+  high <- length(vec)+1L
+  while(low < high) {
+    idx <- as.integer((low + high) / 2L)
+    if(vec[[idx]] == value) {
+      return (idx)
+    } else if(vec[[idx]] < value) {
+      low <- idx
+    } else { 
+      high <- idx
+    }
+  }
+}
diff --git a/com.oracle.truffle.r.native/fficall/src/caccess/Makefile b/documentation/tutorials/debugging/R/dummy.r
similarity index 80%
rename from com.oracle.truffle.r.native/fficall/src/caccess/Makefile
rename to documentation/tutorials/debugging/R/dummy.r
index de9823908ec737bd08446e1b290fbd40230ca647..a9904460ee5e673f58340dc3aca3f55eb169eee7 100644
--- a/com.oracle.truffle.r.native/fficall/src/caccess/Makefile
+++ b/documentation/tutorials/debugging/R/dummy.r
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -21,14 +21,12 @@
 # questions.
 #
 
-ifneq ($(MAKECMDGOALS),clean)
-include $(TOPDIR)/platform.mk
-endif
+bar <- function(x) print(x)
 
+fun <- function(x) {
+	print("Hello")
+	for(i in seq(3)) print(i)
+	bar("World")
+	print(x)
+}
 
-.PHONY: all
-
-all: caccess.o
-
-caccess.o: caccess.c
-	$(CC) $(CFLAGS) -c caccess.c -o $@
diff --git a/mx.fastr/compilers/fastr-c++ b/documentation/tutorials/debugging/R/dump.r
old mode 100755
new mode 100644
similarity index 60%
rename from mx.fastr/compilers/fastr-c++
rename to documentation/tutorials/debugging/R/dump.r
index 2d8cc481f9b9a50c0d6225a4e6b66c52525e7707..fc8a8b5b3c81dc6c8c6df58681101e4005e347e0
--- a/mx.fastr/compilers/fastr-c++
+++ b/documentation/tutorials/debugging/R/dump.r
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -20,28 +20,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-#!/bin/bash
 
-SOURCE="${BASH_SOURCE[0]}"
-while [ -h "$SOURCE" ]; do
-  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
-  SOURCE="$(readlink "$SOURCE")"
-  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
-done
-DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
-
-with_sulong=0
-while [ $DIR != "/" ] ; do
-  if [ -d $DIR/sulong ] && [ -d $DIR/sulong/mx.sulong ] ; then
-    with_sulong=1
-    break
-  fi
-  DIR=`dirname $DIR`
-done
-
-if [ $with_sulong = 1 ] && [ "$FASTR_SULONG_IGNORE" = "" ] ; then
-    mx --dynamicimport sulong fastr-c++ $@
-else
-    g++ $@
-fi
+gen_data <- function() {
+    res <- list(rep(0, 100))
+    for(i in seq_along(res)) {
+        res[[i]] <- i %% 5
+    }
+    res
+}
 
+library(jsonlite)
+jsonStr <- toJSON(gen_data())
+cat(jsonStr)
diff --git a/documentation/tutorials/debugging/tutorial.md b/documentation/tutorials/debugging/tutorial.md
new file mode 100644
index 0000000000000000000000000000000000000000..136bc7f1c50e793ffa4d43835429de6ce32b219b
--- /dev/null
+++ b/documentation/tutorials/debugging/tutorial.md
@@ -0,0 +1,176 @@
+# FastR NetBeans Debugging Tutorial
+
+## Getting started
+
+Read the documentation in *documentation/debugging.md* in FastR's GitHub repository.  
+
+This tutorial is based on GraalVM (and not on standalone FastR, which has a slightly different command line interface).  
+Therefore, download the latest GraalVM from [Oracle Technology Network (OTN)](http://www.oracle.com/technetwork/oracle-labs/program-languages/downloads/index.html) and extract the archive.  
+  
+First, start the FastR shell by running following command:  
+
+    graalvm/bin/R -J:-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -J:-Dtruffle.ndebug.supressLangErrs=true
+
+An argument prefixed with `-J:` will be passed to the *Java Virtual Machine*.  
+The first argument `-J:-Xrunjdwp:...` enables a debugging server such that we are able to attach a debugger.  
+The second argument is to suppress annoying error output when you (accidentally) enter values in the variables view. 
+Once you run the command, it will print following line:  
+
+    Listening for transport dt_socket at address: 8000
+
+This means that the VM is ready and waits for a remote debugger to connect. Therefore, start NetBeans and attach the debugger as described in *documentation/debugging.md*.  
+
+Let's start with a simple example:  
+
+    source("R/binSearch.r")  
+    binSearch(1:100, 1)  
+    binSearch(1:100, 100)  
+    binSearch(1:100, 50)  
+    binSearch(1:100, 67)  
+    binSearch(1:100, 0)   
+    binSearch(1:100, 101) # why does this not stop  
+
+Set a line breakpoint in function `binSearch`, step through the loop iterations and find the problem.
+
+## Debugging Packages 1
+Packages are loaded lazily from a binary file containing the serialized code and data of the package.
+Therefore, you can usually only install a function breakpoint to package code.
+However, FastR keeps the package source such that you can set a line breakpoint in the package's source files.
+
+Determine the path where packages are installed:
+
+    .libPaths()  
+
+To demonstrate this, start FastR in debug mode and attach the NetBeans debugger. 
+Then enter `.libPaths()` to determine where your R packages are installed. 
+
+For example, let's debug package *jsonlite* (so, if you haven't installed it, do so by typing `install.packages("jsonlite")`).  
+This tutorial assumes *jsonlite* in version 1.5.  
+Go to the installation directory from package *jsonlite* and open the file *jsonlite/R/toJSON.R*.  
+Set a line breakpoint at line 31 which calls the generic `asJSON` function.  
+Now, run our script *dump.r* using `source("R/dump.r")`.  
+As soon as the debugging cursor stops at the line breakpoint, step into the call of function *asJSON* to find out which of the concrete implementations is actually executed.
+
+## Debugging Packages 2
+For some reason, it may be that packages do not have source code available.
+In this case installing line breakpoints is not straight forward.
+Therefore, FastR provides a facility to query the source of an R function.
+As in GnuR, if the source is not available for the function, the function's body is deparsed and a string representation is generated.
+FastR then generates a temporary source file containing the deparsed source code.
+This temporary source file can be queried using function `.fastr.srcinfo`.
+
+Let's work through an example: 
+Load the provided file `dummy.r` which defines a function named *fun*.
+
+    source("R/dummy.r")  
+    fun  
+    attributes(fun)  
+
+Actually, *fun* has just been sourced and we would expect that there is a *srcref* attribute.
+Let's have a look what function *source* is actually doing:
+
+    .fastr.srcinfo(source)  
+    [1] "/tmp/deparse/source-58f3b608a4.r#1"  
+
+This output means that FastR generated a temporary source file "/deparse/source-58f3b608a4.r" and function *source* starts at line 1.
+Open the file in NetBeans (File -> Open File ...) and set a breakpoint at line 62.
+
+    source("R/dummy.r")  
+
+Open the __Evaluate Expression__ view under menu Debug -> Evaluate Expression.  
+Type `isTRUE(keep.source)` and press __CTRL + ENTER__.  
+The result of the evaluation should be `TRUE`. So, why there are no source reference attributes?  
+Continue stepping until line 90 (`.Internal(parse(file, n = -1, NULL, "?", srcfile, encoding))`).  
+This line calls the internal parse function which we unfortunately cannot step into because internal functions do not have R code.  
+They are implemented in Java or C.  
+Now, step over line 89 and evaluate the expression: `attributes(exprs)`  
+The results shows that the resulting expressions actually have source reference attributes.  
+Now, keep stepping until line 132 (`ei <- exprs[i]`) which copies one of the elements of the parsed expression.  
+Now, evaluate expression: `attributes(exprs[i])`  
+It turns out that the subexpression does not have any attributes.  
+The reason is that FastR does not create source reference attributes in the parser because the source information is stored differently.  
+
+## Inspecting Promises
+Promises are in particular difficult to handle during debugging.  
+The maxim of debugging is to not modify the program as it could change its behavior and make any debugging difficult.  
+However, this means that you will often not be able to inspect a promise until it is too late since a promise is evaluated at the time it is used.  
+FastR allows to inspect promises in the variables view.  
+Every promise (function parameter) has three fields: `value`, `isEvaluated`, and `expression`  
+If `isEvaluated` cannot be modified, then you will immediately see the value of the promise.   
+If `isEvaluated` can be modified, then it will initially be `FALSE` and `value` will be `NULL`.  
+As soon as the executed function uses the parameter, the promise will be evaluated and `isEvaluated` becomes `TRUE`.  
+Since the function may never use the value, it is possible to inspect the promise's value by manually setting `isEvaluated` to `TRUE` in the variables view.   
+The promise is now evaluated and its value can be inspected.   
+In order to reset the promise to its state before, you can simply set `isEvaluated` to `FALSE` again.  
+The field `expression` shows the actual expression of the promise, e.g., as it has been passed in a function call.  
+
+For example, load the source of file *dummy.r* (if not already done).  
+
+    source("R/dummy.r")
+
+Set a line breakpoint somewhere in function `fun` and call the function as following:  
+
+    fun({ s0 <- "Hello"; s1 <- "World"; paste0(s0, ", ", s1) })
+
+When the debugger stops at the breakpoint in function `fun`, you will notice that variable `x` is of type *promise*.  
+The field `value` is `NULL` and field `isEvaluated` is `FALSE`.  
+Now, change the value of field `isEvaluated` to `TRUE`.  
+Unfortunately, the variables view does not recognize that other values might also have changed.  
+But we can use the __Evaluate Expression__ view to inspect the updated value of `x`.  
+Enter `x` and press __CTRL + ENTER__.  
+You will see the final string the promise evaluates to.  
+Now, reset the promise to not alter the programs behavior by setting field `isEvaluated` to `FALSE` in the variables view.  
+  
+## GraalVM-featured
+FastR is part of the Graal/Truffle world and it is therefore easily possible to write R applications that interact with other programming languages like Java. 
+FastR has its dedicated Java interoperability API that allows to create and use Java objects. 
+It is also possible to cross language boundaries during stepping when using the NetBeans debugger with GraalVM.  
+
+### Preparation
+
+1. Open NetBeans and add GraalVM as Java Platform:
+  1. Tools -> Java Platforms
+  2. Add Platform ...
+  3. Java Standard Edition -> Next
+  4. Navigate to the extracted folder of GraalVM and select the __jdk__ subfolder and click *Next*.
+  5. Specify an appropriate platform name like __GraalVM JDK__ and click finish. 
+2. Open the NetBeans project *InteropDebugging* and ensure that it uses __GraalVM JDK__ as platform:
+3. Open the NetBeans project *InteropDebugging*
+  1. File -> New Project ...
+  2. Java Project with Existing Sources
+  3. Specify name *InteropDebugging*, select folder *InteropDebugging* and click Next
+  4. Add folder *src* to *Source Package Folders* and click Next
+  5. There should be two files *JavaMessage.java* and *Main.java*
+  6. Click Finish
+4. To be able to build the project, ensure that the library *truffle-api.jar* is imported correctly.
+  1. Right click on the project and select *Properties*.
+  2. Then select entry *Libraries*, select the *Compile* tab and look for *Classpath*.
+  3. Click on *...* and add file *graalvm/lib/truffle/truffle-api.jar*, where *graalvm* is the folder where you extracted the downloaded GraalVM into.
+5. Clean and build project *InteropDebugging*.
+
+### Inter-language Debugging 
+
+File `Main.java` creates a `PolyglotEngine` object that can execute R code. This is basically the FastR engine. 
+The engine object can now run R code by creating a source object (representing R code) and submitting the source to the engine. 
+The expression `fromString("print('Hello, World! (from string)')")` creates a source code from a string. 
+Expression `fromFile("R/main.r")` creates source code from file *R/main.r*. 
+
+Now, set a line breakpoint at line 46 (the second eval expression), build the project and run the Java application using GraalVM on the command line:
+`graalvm-<version>/bin/graalvm -J:-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -cp build/classes com.oracle.truffe.r.Main` 
+Attach the NetBeans debugger as described in *documentation/debugging.md* via Debug -> Attach Debugger. 
+Once the debugger breaks at line 46, you can step into the R application (Debug -> Step Into). 
+The debugging cursor will next arrive in file *R/main.r*. 
+
+File *R/main.r* also uses language interoperability to create a Java object and to run JavaScript code.
+We can easily debug the executed Java code by setting a breakpoint in method `java.util.Date.toString`. 
+During stepping through the R program, you will also step into the Java code. 
+
+Next, lines 31 to 35 in *R/main.r* instantiate an object of a class in our NetBeans Java project. 
+Before we can use our class *JavaMessage*, we need to add this project to the class path for the Java interoperability. 
+This is done by statement `java.addToClasspath("build/classes")`. 
+You can now also set a breakpoint in the `getMessage()` method and the debugger will halt on this breakpoint if the R expression `obj$getMessage()` is evaluated. 
+
+Lines 38 and 39 further evaluate code of a different language, namely JavaScript.
+If you have stepped to this call, you will be able to step into the JavaScript program.
+You can then continue your debugging activities in the JavaScript program and you will return to the origin.
+
diff --git a/documentation/tutorials/interop/javaInteroperability.md b/documentation/tutorials/interop/javaInteroperability.md
new file mode 100644
index 0000000000000000000000000000000000000000..4cbd543c431a3ddea9e796af49324c115dc66421
--- /dev/null
+++ b/documentation/tutorials/interop/javaInteroperability.md
@@ -0,0 +1,258 @@
+# FastR Java Interoperability
+
+This tutorial shows how to take advantage of FastR`s Java interoperability features (and other Truffle implemented languages eventually).
+
+All following examples are meant to be executed in the R Console, no additional Java dependencies are necessary.
+
+# Setup
+* download and unzip GraalVM/FastR. The bin directory contains the R and Rscript commands.
+* or build from the [FastR Github repository](https://github.com/graalvm/fastr)
+* to access third party java libraries, they have to be placed on FastR class path
+```
+> java.addToClasspath("/foo/bar.jar")
+> java.addToClasspath(c("/foo/bar.jar", "/foo/bar2.jar"))
+```
+
+# Working with Java Classes and Objects
+## Create a Java Class
+By providing the fully qualified class name to the `new.java.class` function. 
+```
+> calendarClass <- new.java.class('java.util.GregorianCalendar')
+```
+
+(Every requested class has to be on FastR`s classpath. Java JDK classes, like GregorianCalendar used above, work out of the box.)
+
+The returned value is an external object representing a Java Class.
+
+## Create a new Java Object
+By providing an external object representig a Java class to the `new.external` function.
+```
+> calendar <- new.external(calendarClass)
+```
+
+In addition to the class it is also possible to pass over additional constructor arguments.
+
+```
+> calendar <- new.external(calendarClass, year=2042L, moth=3L, day=1L)
+```
+
+And apart from the interop builtins, the `new` function can be used as well.
+
+```
+calendar <- new("java.util.GregorianCalendar")
+calendar <- new("java.util.GregorianCalendar", year=2042L, moth=3L, day=1L)
+```
+
+## Accessing Fields and Methods
+Access to static and instance fields and methods is provided by the `$` and `[` operators.
+
+### Accessing Java Fields
+```
+> calendarClass$SUNDAY
+> calendarClass["SUNDAY"]
+```
+### Invoking Java Methods
+```
+> currentTime <- calendar$getTime()
+> currentTime["toString"]()
+> calendar$setTime(currentTime)
+```
+
+External objects returned from a field, method or created via `new` or `new.external` are either automatically converted into according R values or they live on as external objects in the FastR environment. If necessary, they can be passed over to java.
+
+```
+> cet <- new.java.class("java.util.TimeZone")$getTimeZone("CET")
+> cetCalendar <- new.external(calendarClass, cet)
+```
+
+### Handling of Java primitives
+Returned java primitives, primitive wrappers and String instances are automatically converted into according R values. 
+
+### Passing Java specific primitives as arguments
+R does not have primitives as e.g. java float or byte. As a result there are cases when it is necessary to designate a value passed over to Java to be converted into such a primitive type. 
+
+```
+> byteClass <- new.java.class('java.lang.Byte')
+> new.external(byteClass, as.external.byte(1))
+```
+
+also 
+
+```
+> interopByte <- as.external.byte(1)
+> interopChar <- as.external.char("a")
+> interopFloat <- as.external.float(1.1)
+> interopLong <- as.external.long(1)
+> interopShort <- as.external.short(1)
+```
+
+R `integer` values map directly to Java `int`/`Integer`, R `numeric` to Java `double`/`Double`, R `logical` to Java `boolean`/`Boolean` and R `character` to Java `String`.
+
+### Inspecting external objects
+The `names` function can be used to obtain a list of instance and static members from an external Java Object or Java Class.
+```
+> names(calendar)
+> names(calendarClass)
+```
+
+Code completion works as well
+
+```
+> calendar$a<TAB>
+```
+
+## Working with Java Arrays
+The need for Java Arrays apears at the latest when they have to be passed over to java as arguments. 
+
+### Create a Java Array 
+By providing the component type and the array length or dimensions to the `new.java.array` function.
+```
+> intArray <- new.java.array('int', 3)
+```
+
+The component type names of primitive arrays are `boolean`, `byte`, `char`, `double`, `float`, `int`, `long` and `short`. (The same as in each particular primitive wrapper TYPE constant - see e.g. Integer.TYPE.getName().)
+```
+> integerArray <- new.java.array('java.lang.Integer', 3)
+> stringArray <- new.java.array('java.lang.String', 3)
+> string2DimArray <- new.java.array('java.lang.String', c(2, 3))
+```
+
+### Accessing array elements
+Access to array elements is provided by the `[` operator
+```
+> stringArray[1] <- 'a'
+> string2DimArray[1,1] <- 'a'
+> element <- stringArray[1]
+> element <- string2DimArray[1,1]
+```
+
+### Converting R objects to Java Arrays
+Another way to create java arrays is to convert a vector or a list .
+```
+> intArray <- as.java.array(list(0L, 1L, 2L, 3L))
+> intArray <- as.java.array(c(0L, 1L, 2L, 3L))
+```
+
+The resulting array component type is either automatically given by the according R type. Otherwise it has to be explicitly specified.
+```
+> as.java.array(c(1L,2L,3L), 'double')
+```
+
+### Converting Java Arrays to R objects 
+Unlike Java primitives or their wrappers, java arrays aren't on access automatically converted into a R vector. Nevertheless, when appropriate they can be handled by FastR builtin functions the same way as native R objects.
+```
+> sapply(intArray, function(e) { e })
+> length(stringArray)
+> length(string2DimArray[1])
+```
+
+### Explicit Java Array conversion
+By providing a Java Array to the `as.vector` function.
+```
+> intVec <- as.vector(intArray)
+```
+
+Arrays where the component type is a Java primitive, a primitive wrapper or String are converted into a R vector, otherwise a list containing the array elements is created.
+
+See also
+```
+> characterVector <- as.character(intArray)
+> logicalVector <- as.logical(intArray)
+> ...
+```
+
+### The Java Iterable Interface
+When appropriate, Java objects implementing `java.lang.Iterable` are handled in the same way like Java Arrays when passed as arguments to functions.
+```
+> javaList <- new.external(new.java.class('java.util.ArrayList'))
+> javaList$add(0); 
+> javaList$add(1)
+> length(javaList)
+> as.integer(javaList)
+> as.logical(javaList)
+```
+
+## Other useful Java Interop functions
+To determine whether an object is an external object.
+```
+> is.external(calendar)
+```
+
+To determine whether an external object is executable.
+```
+> is.external.executable(calendar$getTime)
+```
+
+To determine whether an external object represents `null`.
+```
+> is.external.null(calendar)
+```
+
+To determine whether an external object represents an array-like structure.
+```
+> is.external.array(intArray)
+```
+
+To obtain the class name from an external Java Object.
+```
+> java.class(intArray)
+```
+
+## Compatibility with rJava 
+FastR comes with a with a rJava compatibility layer based on FastR`s Java Interoperabily features. While currently only a subset of rJava functionality is supported, the ultimate future goal is to have a flawless execution of rJava based R code.
+For more information see also the [rJava CRAN Page](https://cran.r-project.org/web/packages/rJava/index.html)
+
+### Setup
+* DO NOT try to install rJava via `install.packages`. The FastR\`s rJava package has to be installed instead: `bin/r CMD INSTALL com.oracle.truffle.r.pkgs/rjava`   
+* any additional Java Libraries have to be added to FastR class path
+```
+> java.addToClasspath("/foo/bar.jar")
+```
+
+* as with any other R package, before executing any rJava functions, the package has to be loaded first.
+```
+> library(rJava)
+```
+
+### Supported rJava features
+The `$` and `[` operators work the same as described above.
+
+The following functions are supported in at least some aspects:
+```
+J
+.jnew
+.jcall
+.jfield
+.jarray
+.jevalArray
+.jbyte
+.jchar
+.jshort
+.jlong
+.jfloat
+```
+
+# FastR Interop Builtins
+Bellow a list of available FastR Interoperability builtins. For more information see the FastR help pages.
+```
+> help(as.external.byte)
+> ?as.external.byte
+>```
+
+* as.external.byte
+* as.external.char
+* as.external.float
+* as.external.long
+* as.external.short
+* as.java.array
+* is.external
+* is.external.array
+* is.external.executable
+* is.external.null
+* java.class
+* new.external
+* new.java.array
+* new.java.class
+* external.eval
+* export
+* import
\ No newline at end of file
diff --git a/mx.fastr/compilers/have_sulong b/mx.fastr/compilers/have_sulong
deleted file mode 100755
index a650e87c518dd7362aaf94bb3ae25ab69aad2bd0..0000000000000000000000000000000000000000
--- a/mx.fastr/compilers/have_sulong
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
-# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-#
-# This code is free software; you can redistribute it and/or modify it
-# 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.
-#
-#!/bin/bash
-
-SOURCE="${BASH_SOURCE[0]}"
-while [ -h "$SOURCE" ]; do # resolve $SOURCE until the file is no longer a symlink
-  DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
-  SOURCE="$(readlink "$SOURCE")"
-  [[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE" # if $SOURCE was a relative symlink, we need to resolve it relative to the path where the symlink file was located
-done
-DIR="$( cd -P "$( dirname "$SOURCE" )" && pwd )"
-
-with_sulong=0
-while [ $DIR != "/" ] ; do
-  if [ -d $DIR/sulong ] && [ -d $DIR/sulong/mx.sulong ] ; then
-    with_sulong=1
-    break
-  fi
-  DIR=`dirname $DIR`
-done
-
-if [ $with_sulong = 1 ] && [ "$FASTR_SULONG_IGNORE" = "" ] ; then
-  echo "yes"
-else
-  echo "no"
-fi
diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides
index b2505b0cb646d5b616d1a72e2a6f7d02099ab07c..5c069dde67df806db7e0be218e168f045c6a5555 100644
--- a/mx.fastr/copyrights/overrides
+++ b/mx.fastr/copyrights/overrides
@@ -1,95 +1,59 @@
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java,gnu_r_graphics.copyright
+com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nodes/AsRealNode.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.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/GPar.java,gnu_r_murrel_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/graphics/RGridGraphicsAdapter.java,gnu_r_graphics.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/GridLinesNode.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.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
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.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/LCircleBounds.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.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/LInitGrid.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRaster.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java,gnu_r_murrel_core.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/TransformMatrix.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java,gnu_r_murrel_core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java,gnu_r_murrel_core.copyright
+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/graphics/RGraphics.java,gnu_r_graphics.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/Slot.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Arithmetic.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNorm.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RBeta.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RMultinom.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Cauchy.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QTukey.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PTukey.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/BinDist.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/CompleteCases.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java,gnu_r.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java,gnu_r.core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dbinom.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RNBinom.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNBinom.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNBinom.java,gnu_r.core.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/DPQ.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rt.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java,gnu_r_qgamma.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QHyper.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DHyper.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PHyper.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qt.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pt.java,gnu_r_scan.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pbeta.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNBeta.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNBeta.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnf.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dnf.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnt.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnt.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dnt.java,gnu_r.foundation.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNBeta.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/LBeta.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pbinom.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pf.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PPois.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QPois.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QBeta.java,gnu_r_scan.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qf.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qbinom.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnorm.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RPois.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rbinom.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Unif.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rnorm.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Chisq.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNChisq.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNChisq.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNChisq.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RandFunctionsNodes.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java,gnu_r_splines.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QuantileSearch.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNBinom.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMathError.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Choose.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Mach.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/LogNormal.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/MathConstants.java,gnu_r_ihaka.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/TOMS708.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SExp.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RGamma.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PGamma.java,gnu_r_welinder.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Logis.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnf.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rf.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Exp.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Geom.java,gnu_r_ihaka_core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dt.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Df.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DBeta.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DPois.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RNchisq.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java,gnu_r.core.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Weibull.java,gnu_r_ihaka_core.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/DirChmod.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/tools/ToolsText.java,gnu_r.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/CountFields.java,gnu_r.copyright
+com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Menu.java,gnu_r.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/common/arithmetic_fastr.c,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/common/coerce_fastr.c,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/common/errors_fastr.c,gnu_r.core.copyright
@@ -97,34 +61,37 @@ com.oracle.truffle.r.native/fficall/src/common/inlined_fastr.c,gnu_r_gentleman_i
 com.oracle.truffle.r.native/fficall/src/common/localecharset_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/common/print_fastr.c,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/common/printutils_fastr.c,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.native/fficall/src/common/rffi_upcallsindex.h,no.copyright
 com.oracle.truffle.r.native/fficall/src/common/sys_fastr.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/common/unimplemented.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/common/util_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/common/X11_fastr.c,gnu_r.copyright
-com.oracle.truffle.r.native/fficall/src/common/unimplemented.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/include/contour-common.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/Defn.h,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.native/fficall/src/include/Fileio.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/Graphics.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/GraphicsBase.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/Internal.h,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.native/fficall/src/include/nmath.h,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/include/Print.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/include/Rgraphics.h,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.native/fficall/src/include/Fileio.h,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.native/fficall/src/include/contour-common.h,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.native/fficall/src/include/nmath.h,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/include/rlocale.h,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/fficall/src/jni/Memory.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/jni/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.native/fficall/src/jni/Rdynload_fastr.c,gnu_r.copyright
-com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_llvm/Memory.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_llvm/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/truffle_nfi/Memory.c,gnu_r.copyright
 com.oracle.truffle.r.native/fficall/src/truffle_nfi/pcre_rffi.c,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.native/fficall/src/truffle_llvm/Rdynload_fastr.c,gnu_r.copyright
-com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c,gnu_r.copyright
+com.oracle.truffle.r.native/fficall/src/truffle_nfi/Rdynload_fastr.c,gnu_r.copyright
 com.oracle.truffle.r.native/library/base/src/registration.c,no.copyright
 com.oracle.truffle.r.native/library/grDevices/src/gzio.c,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.native/library/methods/src/methods_dummy.c,no.copyright
 com.oracle.truffle.r.native/library/parallel/src/glpi.h,no.copyright
-com.oracle.truffle.r.native/library/parallel/src/rngstream.c,no.copyright
 com.oracle.truffle.r.native/library/parallel/src/parallel_dummy.c,no.copyright
+com.oracle.truffle.r.native/library/parallel/src/rngstream.c,no.copyright
 com.oracle.truffle.r.native/library/splines/src/splines.c,no.copyright
 com.oracle.truffle.r.native/library/stats/src/gnur_extracts.c,no.copyright
 com.oracle.truffle.r.native/library/stats/src/modreg.h,no.copyright
@@ -133,14 +100,12 @@ com.oracle.truffle.r.native/library/stats/src/port.h,no.copyright
 com.oracle.truffle.r.native/library/stats/src/stats.h,no.copyright
 com.oracle.truffle.r.native/library/stats/src/statsR_dummy.c,no.copyright
 com.oracle.truffle.r.native/library/stats/src/ts.h,no.copyright
-com.oracle.truffle.r.native/library/tools/src/gramRd.c,no.copyright
 com.oracle.truffle.r.native/library/tools/src/tools_dummy.c,no.copyright
 com.oracle.truffle.r.native/library/utils/src/utils_dummy.c,no.copyright
 com.oracle.truffle.r.native/run/R.sh,oracle_bash.copyright
 com.oracle.truffle.r.native/run/Rclasspath.sh,oracle_bash.copyright
 com.oracle.truffle.r.native/run/Rscript_exec.sh,oracle_bash.copyright
 com.oracle.truffle.r.native/run/Rscript.sh,oracle_bash.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Abbrev.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BaseGammaFunctions.java,gnu_r_ihaka.copyright
@@ -162,45 +127,55 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/D
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EncodeString.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CairoProps.java,gnu_r.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrcf.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Dqrdc2.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Fft.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/Flushconsole.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/FortranAndCFunctions.java,gnu_r.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/CallAndExternalFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/MakeQuartzDefault.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/ReadTableHead.java,gnu_r.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/foreign/WriteTable.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetClass.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GrepFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java,gnu_r.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java,gnu_r.core.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InheritsBuiltin.java,purdue.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsListFactor.java,gnu_r.core.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java,gnu_r.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LoadSaveFunctions.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Order.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Pretty.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quit.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Prod.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rank.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RepeatLength.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Row.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowMeans.java,purdue.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowsumFunctions.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/RowSums.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample.java,gnu_r_sample.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sample2.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Scan.java,gnu_r_scan.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/SeqFunctions.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Slot.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/StandardGeneric.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Strtrim.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Switch.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java,gnu_r_gentleman_ihaka.copyright
@@ -210,6 +185,7 @@ com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/U
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java,purdue.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateSlot.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java,purdue.copyright
+com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastrDqrls.java,gnu_r.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java,purdue.copyright
@@ -225,31 +201,105 @@ com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/InheritsNode.java,purdue.copyright
 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java,purdue.copyright
 com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/R.g,purdue.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RStartParams.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SA_TYPE.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Arithmetic.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Choose.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Cauchy.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Chisq.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DBeta.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dbinom.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Df.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DHyper.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNBeta.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNBinom.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNChisq.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dnf.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DNorm.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dnt.java,gnu_r.foundation.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/DPois.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Dt.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Exp.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Geom.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Logis.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/LogNormal.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pbeta.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pbinom.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pf.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PGamma.java,gnu_r_welinder.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PHyper.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNBeta.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNBinom.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PNChisq.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnf.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnorm.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pnt.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PPois.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Pt.java,gnu_r_scan.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/PTukey.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QBeta.java,gnu_r_scan.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qbinom.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qf.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QHyper.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNBeta.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNBinom.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QNChisq.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnf.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnorm.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qnt.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QPois.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Qt.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QTukey.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/QuantileSearch.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RBeta.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rbinom.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rf.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RGamma.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RHyper.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RMultinom.java,gnu_r_gentleman_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RNBinom.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RNchisq.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rnorm.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RPois.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Rt.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SExp.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Signrank.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/SNorm.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Unif.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Weibull.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/Wilcox.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/DPQ.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/GammaFunctions.java,gnu_r_qgamma.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/LBeta.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/Mach.java,gnu_r_ihaka_core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/MathConstants.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMath.java,gnu_r_ihaka.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/RMathError.java,gnu_r.core.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/TOMS708.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/DuplicationHelper.java,purdue.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/BinaryArithmetic.java,gnu_r_purdue.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/UnaryArithmetic.java,gnu_r_unary.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrettyIntevals.java,gnu_r_gentleman_ihaka2.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RAccuracyInfo.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCleanUp.java,gnu_r_gentleman_ihaka2.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/DuplicationHelper.java,purdue.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mm/MarsagliaMulticarry.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/mt/MersenneTwister.java,hiroshima.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RandomNumberGenerator.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RNGInitAdapter.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RandomNumberGenerator.java,gnu_r.copyright
-com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/PrimitiveMethodsInfo.java,gnu_r_gentleman_ihaka.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java,gnu_r.copyright
+com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSrcref.java,gnu_r.copyright
 com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java,gnu_r.copyright
-com.oracle.truffle.r.test.native/urand/src/urand.c,gnu_r.copyright
 com.oracle.truffle.r.test.native/urand/src/nrand.c,gnu_r.copyright
+com.oracle.truffle.r.test.native/urand/src/urand.c,gnu_r.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abbreviate.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_abs.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_acos.java,purdue.copyright
@@ -618,8 +668,8 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sam
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scale.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_scan.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sep.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_len.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_along.java,purdue.copyright
+com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq_len.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seq.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_seqint.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_setdiff.java,purdue.copyright
@@ -667,15 +717,15 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sum
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_summaryconnection.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sweep.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_switch.java,purdue.copyright
+com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscall.java,purdue.copyright
+com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscalls.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syschmod.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Sysgetenv.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Sysglob.java,purdue.copyright
+com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysnframe.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysonexit.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysparent.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysparents.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_sysnframe.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscall.java,purdue.copyright
-com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_syscalls.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Sysreadlink.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetenv.java,purdue.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_Syssetlocale.java,purdue.copyright
@@ -729,50 +779,3 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/base/TestSimpleV
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/data/tree2/incx.r,no.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/simple/data/tree2/setx.r,no.copyright
 com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java,purdue.copyright
-com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/ffi/AsRealNode.java,gnu_r_gentleman_ihaka.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/AttributesPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/DoubleVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PrintParameters.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/StringVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/IntegerVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ComplexVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/LogicalVectorPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/PairListPrinter.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/Deriv.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/deriv/DerivVisitor.java,gnu_r_gentleman_ihaka2.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRect.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPretty.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LRectBounds.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LCircleBounds.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LLocnBounds.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Arrows.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LPoints.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridState.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPortBuiltin.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUpViewPort.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LNewPage.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitGrid.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LInitViewPortStack.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GPar.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/TransformMatrix.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LSegments.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/DoSetViewPort.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LUnsetViewPort.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPort.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridUtils.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/Unit.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LValidUnit.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortLocation.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/ViewPortContext.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/GridLinesNode.java,gnu_r_murrel_core.copyright
-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
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/fastrGrid/LConvert.java,gnu_r_murrel_core.copyright
-com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java,gnu_r_gentleman_ihaka2.copyright
diff --git a/mx.fastr/mx_copylib.py b/mx.fastr/mx_copylib.py
index 34df957df61dade528f4c8142dafe4f35e59a00c..d266242ea54ee5aa4cf462ff6e4eb7d52d80845b 100644
--- a/mx.fastr/mx_copylib.py
+++ b/mx.fastr/mx_copylib.py
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2016, 2016, Oracle and/or its affiliates. All rights reserved.
+# 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
@@ -42,7 +42,7 @@ def _darwin_extract_realpath(lib, libpath):
     except subprocess.CalledProcessError:
         mx.abort('copylib: otool failed')
 
-def _copylib(lib, libpath, target):
+def _copylib(lib, libpath, plain_libpath_base, target):
     '''
     Just copying libxxx.so/dylib isn't sufficient as versioning is involved.
     The path is likely a symlink to libxxx.so.n, for example, but what is really
@@ -67,20 +67,19 @@ def _copylib(lib, libpath, target):
     # copy both files
     shutil.copyfile(real_libpath, os.path.join(target, os.path.basename(real_libpath)))
     mx.log('copied ' + lib + ' library from ' + real_libpath + ' to ' + target)
-    libpath_base = os.path.basename(libpath)
     os.chdir(target)
-    mx.log('libpath: ' + libpath + ' real_libpath: ' + real_libpath)
-    if os.path.basename(libpath) != os.path.basename(real_libpath):
+    mx.log('plain_libpath_base: ' + plain_libpath_base + ' libpath: ' + libpath + ' real_libpath: ' + real_libpath)
+    if os.path.basename(real_libpath) != plain_libpath_base:
         # create a symlink
-        if os.path.exists(libpath_base):
-            os.remove(libpath_base)
-        mx.log('ln -s ' + os.path.basename(real_libpath) + ' ' + libpath_base)
-        os.symlink(os.path.basename(real_libpath), libpath_base)
+        if os.path.exists(plain_libpath_base):
+            os.remove(plain_libpath_base)
+        mx.log('ln -s ' + os.path.basename(real_libpath) + ' ' + plain_libpath_base)
+        os.symlink(os.path.basename(real_libpath), plain_libpath_base)
     # On Darwin we change the id to use @rpath
     if platform.system() == 'Darwin':
         try:
-            mx.log('install_name_tool -id @rpath/' + libpath_base + ' ' + libpath_base)
-            subprocess.check_call(['install_name_tool', '-id', '@rpath/' + libpath_base, libpath_base])
+            mx.log('install_name_tool -id @rpath/' + plain_libpath_base + ' ' + plain_libpath_base)
+            subprocess.check_call(['install_name_tool', '-id', '@rpath/' + plain_libpath_base, plain_libpath_base])
         except subprocess.CalledProcessError:
             mx.abort('copylib: install_name_tool failed')
 
@@ -104,21 +103,22 @@ def copylib(args):
         parts = os.environ['PKG_LDFLAGS_OVERRIDE'].split(' ')
         ext = '.dylib' if platform.system() == 'Darwin' else '.so'
         lib_prefix = 'lib' + args[0]
-        plain_libpath = lib_prefix + ext
+        plain_libpath_base = lib_prefix + ext
         for part in parts:
             path = part.strip('"').lstrip('-L')
             if os.path.exists(path):
                 for f in os.listdir(path):
                     if f.startswith(lib_prefix):
-                        if os.path.exists(os.path.join(path, plain_libpath)):
-                            f = plain_libpath
+                        if os.path.exists(os.path.join(path, plain_libpath_base)):
+                            f = plain_libpath_base
                         target_dir = args[1]
                         if not os.path.exists(os.path.join(target_dir, f)):
-                            _copylib(args[0], os.path.join(path, f), args[1])
+                            _copylib(args[0], os.path.join(path, f), plain_libpath_base, args[1])
                         return 0
 
     if os.environ.has_key('FASTR_RELEASE'):
-        if args[0] == 'quadmath' and (mx.get_arch() == 'sparcv9' or mx.get_os() == 'solaris'):
+#        if args[0] == 'quadmath' and (mx.get_arch() == 'sparcv9' or mx.get_os() == 'solaris'):
+        if mx.get_arch() == 'sparcv9' or mx.get_os() == 'solaris':
             return 0
         mx.abort(args[0] + ' not found in PKG_LDFLAGS_OVERRIDE, but required with FASTR_RELEASE')
 
diff --git a/mx.fastr/mx_fastr.py b/mx.fastr/mx_fastr.py
index 4eac3bba913e9a318b1e888f7a8fe891ba02e65e..ef0a29387f7aa8f5dfc73e2d1bc0757c50587c15 100644
--- a/mx.fastr/mx_fastr.py
+++ b/mx.fastr/mx_fastr.py
@@ -26,13 +26,12 @@ from argparse import ArgumentParser
 import mx
 import mx_gate
 import mx_fastr_pkgs
-import mx_fastr_compile
 import mx_fastr_dists
-import mx_fastr_junit
-from mx_fastr_dists import FastRTestNativeProject, FastRReleaseProject, FastRNativeRecommendedProject #pylint: disable=unused-import
+from mx_fastr_dists import FastRReleaseProject, FastRNativeRecommendedProject #pylint: disable=unused-import
 import mx_copylib
 import mx_fastr_mkgramrd
 import mx_fastr_edinclude
+import mx_unittest
 
 import os
 
@@ -51,12 +50,10 @@ If this is None, then we run under the standard VM in interpreted mode only.
 _mx_graal = mx.suite("compiler", fatalIfMissing=False)
 _mx_sulong = mx.suite("sulong", fatalIfMissing=False)
 
-_r_command_package = 'com.oracle.truffle.r.engine'
-_repl_command = 'com.oracle.truffle.tools.debug.shell.client.SimpleREPLClient'
-_command_class_dict = {'r': _r_command_package + ".shell.RCommand",
-                       'rscript': _r_command_package + ".shell.RscriptCommand",
-                        'rrepl': _repl_command,
-                        'rembed': _r_command_package + ".shell.REmbedded",
+_command_class_dict = {'r': "com.oracle.truffle.r.launcher.RCommand",
+                       'rscript': "com.oracle.truffle.r.launcher.RscriptCommand",
+                        'rrepl': "com.oracle.truffle.tools.debug.shell.client.SimpleREPLClient",
+                        'rembed': "com.oracle.truffle.r.engine.shell.REmbedded",
                     }
 # benchmarking support
 def r_path():
@@ -152,8 +149,7 @@ def set_graal_options():
 
 def _sulong_options():
     if _mx_sulong:
-        return ['-Dfastr.ffi.factory.class=com.oracle.truffle.r.engine.interop.ffi.llvm.TruffleLLVM_RFFIFactory',
-                '-XX:-UseJVMCIClassLoader']
+        return ['-Dpolyglot.llvm.libraryPath=' + _mx_sulong.dir + '/mxbuild/sulong-libs']
     else:
         return []
 
@@ -267,23 +263,19 @@ def _fastr_gate_runner(args, tasks):
     # check that the expected test output file is up to date
     with mx_gate.Task('UnitTests: ExpectedTestOutput file check', tasks) as t:
         if t:
-            if junit(['--tests', _gate_unit_tests(), '--check-expected-output']) != 0:
-                t.abort('unit tests expected output check failed')
+            mx_unittest.unittest(['-Dfastr.test.gen.expected=' + _test_srcdir(), '-Dfastr.test.check.expected'] + _gate_unit_tests())
 
     with mx_gate.Task('UnitTests: no specials', tasks) as t:
         if t:
-            if junit(['--J', '@-DR:-UseSpecials', '--tests', _gate_noapps_unit_tests()]) != 0:
-                t.abort('unit tests failed')
+            mx_unittest.unittest(['-DR:-UseSpecials'] + _gate_noapps_unit_tests())
 
     with mx_gate.Task('UnitTests: with specials', tasks) as t:
         if t:
-            if junit(['--tests', _gate_noapps_unit_tests()]) != 0:
-                t.abort('unit tests failed')
+            mx_unittest.unittest(_gate_noapps_unit_tests())
 
     with mx_gate.Task('UnitTests: apps', tasks) as t:
         if t:
-            if junit(['--tests', _apps_unit_tests()]) != 0:
-                t.abort('unit tests failed')
+            mx_unittest.unittest(_apps_unit_tests())
 
 mx_gate.add_gate_runner(_fastr_suite, _fastr_gate_runner)
 
@@ -295,103 +287,24 @@ def rgate(args):
     '''
     mx_gate.gate(args)
 
-def _test_srcdir():
-    tp = 'com.oracle.truffle.r.test'
-    return join(mx.project(tp).dir, 'src', tp.replace('.', sep))
-
-def _junit_r_harness(args, vmArgs, jdk, junitArgs):
-    # always pass the directory where the expected output file should reside
-    runlistener_arg = 'expected=' + _test_srcdir()
-    # there should not be any unparsed arguments at this stage
-    if args.remainder:
-        mx.abort('unexpected arguments: ' + str(args.remainder).strip('[]') + '; did you forget --tests')
-
-    def add_arg_separator():
-        # can't update in Python 2.7
-        arg = runlistener_arg
-        if len(arg) > 0:
-            arg += ','
-        return arg
-
-    if args.gen_fastr_output:
-        runlistener_arg = add_arg_separator()
-        runlistener_arg += 'gen-fastr=' + args.gen_fastr_output
-
-    if args.check_expected_output:
-        args.gen_expected_output = True
-        runlistener_arg = add_arg_separator()
-        runlistener_arg += 'check-expected'
-
-    if args.gen_expected_output:
-        runlistener_arg = add_arg_separator()
-        runlistener_arg += 'gen-expected'
-        if args.keep_trailing_whitespace:
-            runlistener_arg = add_arg_separator()
-            runlistener_arg += 'keep-trailing-whitespace'
-        if args.gen_expected_quiet:
-            runlistener_arg = add_arg_separator()
-            runlistener_arg += 'gen-expected-quiet'
-
-    if args.gen_diff_output:
-        runlistener_arg = add_arg_separator()
-        runlistener_arg += 'gen-diff=' + args.gen_diff_output
-
-    if args.trace_tests:
-        runlistener_arg = add_arg_separator()
-        runlistener_arg += 'trace-tests'
-
-#    if args.test_methods:
-#        runlistener_arg = add_arg_separator()
-#        runlistener_arg = 'test-methods=' + args.test_methods
-
-    runlistener_arg = add_arg_separator()
-    runlistener_arg += 'test-project-output-dir=' + mx.project('com.oracle.truffle.r.test').output_dir()
-
-    # use a custom junit.RunListener
-    runlistener = 'com.oracle.truffle.r.test.TestBase$RunListener'
-    if len(runlistener_arg) > 0:
-        runlistener += ':' + runlistener_arg
-
-    junitArgs += ['--runlistener', runlistener]
-
-    # on some systems a large Java stack seems necessary
-    vmArgs += ['-Xss12m']
-    # no point in printing errors to file when running tests (that contain errors on purpose)
-    vmArgs += ['-DR:-PrintErrorStacktracesToFile']
-    vmArgs += _sulong_options()
-
-    setREnvironment()
-
-    return mx.run_java(vmArgs + junitArgs, nonZeroIsFatal=False, jdk=jdk)
-
-def junit(args):
-    '''run R Junit tests'''
-    parser = ArgumentParser(prog='r junit')
-    parser.add_argument('--gen-expected-output', action='store_true', help='generate/update expected test output file')
-    parser.add_argument('--gen-expected-quiet', action='store_true', help='suppress output on new tests being added')
-    parser.add_argument('--keep-trailing-whitespace', action='store_true', help='keep trailing whitespace in expected test output file')
-    parser.add_argument('--check-expected-output', action='store_true', help='check but do not update expected test output file')
-    parser.add_argument('--gen-fastr-output', action='store', metavar='<path>', help='generate FastR test output file in given directory (e.g. ".")')
-    parser.add_argument('--gen-diff-output', action='store', metavar='<path>', help='generate difference test output file in given directory (e.g. ".")')
-    parser.add_argument('--trace-tests', action='store_true', help='trace the actual @Test methods as they are executed')
-    # parser.add_argument('--test-methods', action='store', help='pattern to match test methods in test classes')
-
-    if os.environ.has_key('R_PROFILE_USER'):
-        mx.abort('unset R_PROFILE_USER before running unit tests')
-    _unset_conflicting_envs()
-    return mx_fastr_junit.junit(args, _junit_r_harness, parser=parser, jdk_default=get_default_jdk())
+def _unittest_config_participant(config):
+    vmArgs, mainClass, mainClassArgs = config
+    # need to pass location of FASTR_UNIT_TESTS_NATIVE
+    d = mx.distribution('FASTR_UNIT_TESTS_NATIVE')
+    vmArgs = ['-Dfastr.test.native=' + d.path] + vmArgs
+    return (vmArgs, mainClass, mainClassArgs)
 
-def junit_simple(args):
-    return mx.command_function('junit')(['--tests', _simple_unit_tests()] + args)
+def ut_simple(args):
+    return mx_unittest.unittest(args + _simple_unit_tests())
 
-def junit_noapps(args):
-    return mx.command_function('junit')(['--tests', _gate_noapps_unit_tests()] + args)
+def ut_noapps(args):
+    return mx_unittest.unittest(args + _gate_noapps_unit_tests())
 
-def junit_default(args):
-    return mx.command_function('junit')(['--tests', _all_unit_tests()] + args)
+def ut_default(args):
+    return mx_unittest.unittest(args + _all_unit_tests())
 
-def junit_gate(args):
-    return mx.command_function('junit')(['--tests', _gate_unit_tests()] + args)
+def ut_gate(args):
+    return mx_unittest.unittest(args + _gate_unit_tests())
 
 def _test_package():
     return 'com.oracle.truffle.r.test'
@@ -400,34 +313,35 @@ def _test_subpackage(name):
     return '.'.join((_test_package(), name))
 
 def _simple_generated_unit_tests():
-    return ','.join(map(_test_subpackage, ['engine.shell', 'library.base', 'library.fastrGrid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rng', 'runtime.data', 'S4']))
+    return map(_test_subpackage, ['engine.shell', 'engine.interop', 'library.base', 'library.grid', 'library.fastrGrid', 'library.methods', 'library.stats', 'library.utils', 'library.fastr', 'builtins', 'functions', 'parser', 'rffi', 'rng', 'runtime.data', 'S4'])
 
 def _simple_unit_tests():
-    return ','.join([_simple_generated_unit_tests(), _test_subpackage('tck')])
+    return _simple_generated_unit_tests() + [_test_subpackage('tck')]
 
 def _nodes_unit_tests():
-    return 'com.oracle.truffle.r.nodes.test'
+    return ['com.oracle.truffle.r.nodes.test']
 
 def _apps_unit_tests():
-    return _test_subpackage('apps')
+    return [_test_subpackage('apps')]
 
 def _gate_noapps_unit_tests():
-    return ','.join([_simple_unit_tests(), _nodes_unit_tests()])
+    return _simple_unit_tests() + _nodes_unit_tests()
 
 def _gate_unit_tests():
-    return ','.join([_gate_noapps_unit_tests(), _apps_unit_tests()])
+    return _gate_noapps_unit_tests() +  _apps_unit_tests()
 
 def _all_unit_tests():
     return _gate_unit_tests()
 
 def _all_generated_unit_tests():
-    return ','.join([_simple_generated_unit_tests()])
+    return _simple_generated_unit_tests()
+
+def _test_srcdir():
+    tp = 'com.oracle.truffle.r.test'
+    return join(mx.project(tp).dir, 'src', tp.replace('.', sep))
 
 def testgen(args):
-    '''generate the expected output for unit tests, and All/Failing test classes'''
-    parser = ArgumentParser(prog='r testgen')
-    parser.add_argument('--tests', action='store', default=_all_generated_unit_tests(), help='pattern to match test classes')
-    args = parser.parse_args(args)
+    '''generate the expected output for unit tests'''
     # check we are in the home directory
     if os.getcwd() != _fastr_suite.dir:
         mx.abort('must run rtestgen from FastR home directory')
@@ -453,13 +367,14 @@ def testgen(args):
         except subprocess.CalledProcessError:
             mx.abort('RVersionNumber.main failed')
 
-    # now just invoke junit with the appropriate options
+    tests = _all_generated_unit_tests()
+    # now just invoke unittst with the appropriate options
     mx.log("generating expected output for packages: ")
-    for pkg in args.tests.split(','):
+    for pkg in tests:
         mx.log("    " + str(pkg))
     os.environ["TZDIR"] = "/usr/share/zoneinfo/"
     _unset_conflicting_envs()
-    junit(['--tests', args.tests, '--gen-expected-output', '--gen-expected-quiet'])
+    mx_unittest.unittest(['-Dfastr.test.gen.expected=' + _test_srcdir(), '-Dfastr.test.gen.expected.quiet', '-Dfastr.test.project.output.dir=' + mx.project('com.oracle.truffle.r.test').output_dir()] + tests)
 
 def _unset_conflicting_envs():
     # this can interfere with the recommended packages
@@ -469,9 +384,6 @@ def _unset_conflicting_envs():
     if os.environ.has_key('EDITOR'):
         del os.environ['EDITOR']
 
-def unittest(args):
-    print "use 'junit --tests testclasses' or 'junitsimple' to run FastR unit tests"
-
 def rbcheck(args):
     '''Checks FastR builtins against GnuR
 
@@ -568,6 +480,8 @@ def nativebuild(args):
 def mx_post_parse_cmd_line(opts):
     mx_fastr_dists.mx_post_parse_cmd_line(opts)
 
+mx_unittest.add_config_participant(_unittest_config_participant)
+
 _commands = {
     'r' : [rshell, '[options]'],
     'R' : [rshell, '[options]'],
@@ -575,12 +489,10 @@ _commands = {
     'Rscript' : [rscript, '[options]'],
     'rtestgen' : [testgen, ''],
     'rgate' : [rgate, ''],
-    'junit' : [junit, ['options']],
-    'junitsimple' : [junit_simple, ['options']],
-    'junitdefault' : [junit_default, ['options']],
-    'junitgate' : [junit_gate, ['options']],
-    'junitnoapps' : [junit_noapps, ['options']],
-    'unittest' : [unittest, ['options']],
+    'rutsimple' : [ut_simple, ['options']],
+    'rutdefault' : [ut_default, ['options']],
+    'rutgate' : [ut_gate, ['options']],
+    'rutnoapps' : [ut_noapps, ['options']],
     'rbcheck' : [rbcheck, '--filter [gnur-only,fastr-only,both,both-diff]'],
     'rbdiag' : [rbdiag, '(builtin)* [-v] [-n] [-m] [--sweep | --sweep=lite | --sweep=total] [--mnonly] [--noSelfTest] [--matchLevel=same | --matchLevel=error] [--maxSweeps=N] [--outMaxLev=N]'],
     'rrepl' : [rrepl, '[options]'],
@@ -588,6 +500,9 @@ _commands = {
     'r-cp' : [r_classpath, '[options]'],
     'pkgtest' : [mx_fastr_pkgs.pkgtest, ['options']],
     'pkgtest-cmp' : [mx_fastr_pkgs.pkgtest_cmp, ['gnur_path fastr_path']],
+    'r-pkgtest-analyze' : [mx_fastr_pkgs.pta, ['options']],
+    'r-findtop100' : [mx_fastr_pkgs.find_top100, ['options']],
+    'r-duppkgs' : [mx_fastr_pkgs.remove_dup_pkgs, ['options']],
     'installpkgs' : [mx_fastr_pkgs.installpkgs, '[options]'],
     'mkgramrd': [mx_fastr_mkgramrd.mkgramrd, '[options]'],
     'rcopylib' : [mx_copylib.copylib, '[]'],
@@ -598,5 +513,4 @@ _commands = {
     'nativebuild' : [nativebuild, '[]'],
     }
 
-_commands.update(mx_fastr_compile._commands)
 mx.update_commands(_fastr_suite, _commands)
diff --git a/mx.fastr/mx_fastr_compile.py b/mx.fastr/mx_fastr_compile.py
deleted file mode 100644
index 94fac7e4f7dbb70935e2c1e220b35d9b46d62cf4..0000000000000000000000000000000000000000
--- a/mx.fastr/mx_fastr_compile.py
+++ /dev/null
@@ -1,343 +0,0 @@
-#
-# 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.
-#
-"""
-A wrapper for the C/C++/Fortran compilers that optionally handles the generation of LLVM bitcode.
-When not running with sulong is simply forwards to the default compiler for the platform.
-When running under sulong, it uses sulong to do two compilations; first to generate object code
-and second to generate LLVM bitcode.
-"""
-import os, sys
-import mx
-import mx_fastr
-
-def _sulong():
-    sulong = mx.suite('sulong', fatalIfMissing=False)
-    if sulong:
-        return sulong.extensions
-    else:
-        return None
-
-def _is_linux():
-    return sys.platform.startswith('linux')
-
-def _is_darwin():
-    return sys.platform.startswith('darwin')
-
-def _log(cmd, args):
-    if os.environ.has_key('FASTR_COMPILE_LOGFILE'):
-        with open(os.environ['FASTR_COMPILE_LOGFILE'], 'a') as f:
-            f.write(cmd)
-            f.write('(')
-            f.write(os.getcwd())
-            f.write(')')
-            f.write(' ')
-            f.write(' '.join(args))
-            f.write('\n')
-
-class AnalyzedArgs:
-    '''
-    is_link: True iff the command is a shared library link
-    llvm_ir_file: the target file for the ir derived from the .o file (only set if is_link=False)
-    compile_args: possibly modified args for C compilation
-    emit_llvm_args: the args to generate the llvm ir
-    '''
-    def __init__(self, llvm_ir_file, is_link, compile_args, emit_llvm_args):
-        self.llvm_ir_file = llvm_ir_file
-        self.is_link = is_link
-        self.compile_args = compile_args
-        self.emit_llvm_args = emit_llvm_args
-
-
-def _c_dummy_file():
-    return os.path.join(mx_fastr._fastr_suite.dir, 'com.oracle.truffle.r.native', 'fficall', 'src', 'truffle_llvm', 'llvm_dummy.c')
-
-def _analyze_args(args, dragonEgg=False):
-    '''
-    Analyzes the original arguments to the compiler and returns an adjusted
-    list that will run the compiler (via sulong) to extract the llvm ir.
-    Result is an instance of AnalyzedArgs:
-    '''
-    compile_args = []
-    emit_llvm_args = []
-    llvm_ir_file_ext = '.bc'
-    if not dragonEgg:
-        emit_llvm_args.append('-emit-llvm')
-    else:
-        # dragonEgg plugin doesn't seem able to make bitcode directly
-        emit_llvm_args.append('-S')
-        llvm_ir_file_ext = '.ll'
-
-    is_link = False
-    llvm_ir_file = None
-    c_dummy = False
-    i = 0
-    while i < len(args):
-        arg = args[i]
-        if arg == '-DFASTR_LLVM':
-            c_dummy = True
-            i = i + 1
-            continue
-
-        emit_llvm_args.append(arg)
-        compile_args.append(arg)
-        if arg == '-c':
-            cfile = args[i + 1]
-            if c_dummy:
-                cfile = _c_dummy_file()
-            compile_args.append(cfile)
-            emit_llvm_args.append(args[i + 1])
-            i = i + 1
-
-        if arg == '-o':
-            ext = os.path.splitext(args[i + 1])[1]
-            is_link = ext == '.so' or ext == '.dylib'
-            compile_args.append(args[i + 1])
-            if ext == '.o':
-                llvm_ir_file = os.path.splitext(args[i + 1])[0] + llvm_ir_file_ext
-                emit_llvm_args.append(llvm_ir_file)
-            i = i + 1
-
-        i = i + 1
-    _log('adjusted-compile-args', compile_args)
-    _log('emit-llvm-args', emit_llvm_args)
-    return AnalyzedArgs(llvm_ir_file, is_link, compile_args, emit_llvm_args)
-
-def cc(args):
-    _log('fastr:cc', args)
-    compiler = None
-    sulong = _sulong()
-    if sulong:
-        analyzed_args = _analyze_args(args)
-        if _is_linux():
-            rc = sulong.compileWithGCC(analyzed_args.compile_args)
-            if rc == 0 and analyzed_args.llvm_ir_file:
-                if not analyzed_args.is_link:
-                    rc = sulong.compileWithGCC(analyzed_args.emit_llvm_args)
-        elif _is_darwin():
-            rc = sulong.compileWithClang(analyzed_args.compile_args)
-            if rc == 0 and analyzed_args.llvm_ir_file:
-                if not analyzed_args.is_link:
-                    rc = sulong.compileWithClang(analyzed_args.emit_llvm_args)
-        else:
-            mx.abort('unsupported platform')
-        if rc == 0 and not analyzed_args.is_link and analyzed_args.llvm_ir_file:
-            rc = _mem2reg_opt(analyzed_args.llvm_ir_file)
-            if rc == 0:
-                rc = _embed_ir(analyzed_args.llvm_ir_file)
-    else:
-        if _is_linux():
-            compiler = 'gcc'
-        elif _is_darwin():
-            compiler = 'clang'
-        else:
-            mx.abort('unsupported platform')
-
-        rc = mx.run([compiler] + args, nonZeroIsFatal=False)
-
-    return rc
-
-def fc(args):
-    _log('fastr:fc', args)
-    compiler = None
-    sulong = _sulong()
-    if sulong:
-        analyzed_args = _analyze_args(args, dragonEgg=True)
-        rc = mx.run([sulong.getGFortran()] + analyzed_args.compile_args, nonZeroIsFatal=False)
-        if rc == 0:
-            rc = sulong.dragonEggGFortran(analyzed_args.emit_llvm_args)
-            if rc == 0 and analyzed_args.llvm_ir_file:
-                # create bitcode from textual IR
-                llvm_as = sulong.findLLVMProgram('llvm-as')
-                llvm_bc_file = os.path.splitext(analyzed_args.llvm_ir_file)[0] + '.bc'
-                rc = mx.run([llvm_as, analyzed_args.llvm_ir_file, '-o', llvm_bc_file])
-                rc = _embed_ir(llvm_bc_file)
-    else:
-        compiler = 'gfortran'
-        rc = mx.run([compiler] + args, nonZeroIsFatal=False)
-
-    return rc
-
-def cpp(args):
-    _log('fastr:c++', args)
-    compiler = None
-    sulong = _sulong()
-    if sulong:
-        analyzed_args = _analyze_args(args)
-        if _is_linux():
-            rc = sulong.dragonEggGPP(analyzed_args.compile_args)
-        elif _is_darwin():
-            rc = sulong.compileWithClangPP(analyzed_args.compile_args)
-            if rc == 0:
-                if analyzed_args.llvm_ir_file:
-                    rc = sulong.compileWithClangPP(analyzed_args.emit_llvm_args)
-        else:
-            mx.abort('unsupported platform')
-        if rc == 0 and not analyzed_args.is_link:
-            rc = _embed_ir(analyzed_args.llvm_ir_file)
-    else:
-        compiler = 'g++'
-        rc = mx.run([compiler] + args, nonZeroIsFatal=False)
-
-    return rc
-
-def cppcpp(args):
-    '''C++ pre-preprocessor'''
-    _log('fastr:cpp', args)
-    rc = mx.run(['cpp'] + args)
-    return rc
-
-def _mem2reg_opt(llvm_ir_file):
-    filename = os.path.splitext(llvm_ir_file)[0]
-    ext = os.path.splitext(llvm_ir_file)[1]
-    opt_filename = filename + '.opt' + ext
-    rc = _sulong().opt(['-mem2reg', llvm_ir_file, '-o', opt_filename])
-    if rc == 0:
-        os.rename(opt_filename, llvm_ir_file)
-    return rc
-
-def _embed_ir(llvm_ir_file):
-    '''
-    Given an llvm_ir_file, generates an assembler file containing the content as a sequence
-    of .byte directives, then uses ld to merge that with the original .o file, replacing
-    the original .o file.
-    '''
-
-    def write_hexbyte(f, b):
-        f.write("0x%0.2X" % b)
-
-    def write_int(f, n):
-        write_hexbyte(f, n & 255)
-        f.write(',')
-        write_hexbyte(f, (n >> 8) & 255)
-        f.write(',')
-        write_hexbyte(f, (n >> 16) & 255)
-        f.write(',')
-        write_hexbyte(f, (n >> 24) & 255)
-
-    def write_symbol(f, sym):
-        write_dot_byte(f)
-        write_hexbyte(f, len(sym))
-        f.write(', ')
-        first = True
-        for ch in sym:
-            if first:
-                first = False
-            else:
-                f.write(', ')
-            write_hexbyte(f, ord(ch))
-        f.write('\n')
-
-    def write_dot_byte(f):
-        f.write('        .byte ')
-
-    def checkchars(s):
-        return s.replace("-", "_")
-
-    # find the exported symbols
-    llvm_nm = _sulong().findLLVMProgram("llvm-nm")
-
-    class NMOutputCapture:
-        def __init__(self):
-            self.exports = []
-            self.imports = []
-
-        def __call__(self, data):
-            # T name
-            s = data.strip()
-            if s[0] == 'T':
-                self.exports.append(s[2:])
-            elif s[0] == 'U':
-                self.imports.append(s[2:])
-
-    llvm_nm_out = NMOutputCapture()
-    mx.run([llvm_nm, llvm_ir_file], out=llvm_nm_out)
-
-    with open(llvm_ir_file) as f:
-        content = bytearray(f.read())
-    filename = os.path.splitext(llvm_ir_file)[0]
-    ext = os.path.splitext(llvm_ir_file)[1]
-    as_file = llvm_ir_file + '.s'
-    gsym = "__llvm_" + checkchars(os.path.basename(filename))
-    with open(as_file, 'w') as f:
-        f.write('        .const\n')
-        f.write('        .globl ' + gsym + '\n')
-        f.write(gsym + ':\n')
-        count = 0
-        lenc = len(content)
-        write_dot_byte(f)
-        # 1 for text, 2 for binary, followed by length
-        write_hexbyte(f, 1 if ext == '.ll' else 2)
-        f.write(',')
-        write_int(f, lenc)
-        f.write('\n')
-        # now the exported symbols
-        write_dot_byte(f)
-        write_int(f, len(llvm_nm_out.exports))
-        f.write('\n')
-        for sym in llvm_nm_out.exports:
-            write_symbol(f, sym)
-        # now the imported symbols
-        write_dot_byte(f)
-        write_int(f, len(llvm_nm_out.imports))
-        f.write('\n')
-        for sym in llvm_nm_out.imports:
-            write_symbol(f, sym)
-        # now the content
-        write_dot_byte(f)
-        first = True
-        for b in content:
-            if first:
-                first = False
-            else:
-                f.write(',')
-            write_hexbyte(f, b)
-            count = count + 1
-            if count % 20 == 0 and count < lenc:
-                f.write('\n')
-                write_dot_byte(f)
-                first = True
-        f.write('\n')
-
-    ll_o_file = llvm_ir_file + '.o'
-    rc = mx.run(['gcc', '-c', as_file, '-o', ll_o_file], nonZeroIsFatal=False)
-    if rc == 0:
-        # combine
-        o_file = filename + '.o'
-        dot_o_file = o_file + '.o'
-        os.rename(o_file, dot_o_file)
-        rc = mx.run(['ld', '-r', dot_o_file, ll_o_file, '-o', o_file], nonZeroIsFatal=False)
-        os.remove(dot_o_file)
-        os.remove(as_file)
-        os.remove(ll_o_file)
-    return rc
-
-def mem2reg(args):
-    _mem2reg_opt(args[0])
-
-_commands = {
-    'fastr-cc' : [cc, '[options]'],
-    'fastr-fc' : [fc, '[options]'],
-    'fastr-c++' : [cpp, '[options]'],
-    'fastr-cpp' : [cppcpp, '[options]'],
-    'mem2reg' : [mem2reg, '[options]'],
-}
diff --git a/mx.fastr/mx_fastr_dists.py b/mx.fastr/mx_fastr_dists.py
index 2f81965b06e1e888b039f925cb09a2e43338ea3d..6ef478f23a76bab6c5e8e54e394bb66fb5db405d 100644
--- a/mx.fastr/mx_fastr_dists.py
+++ b/mx.fastr/mx_fastr_dists.py
@@ -42,32 +42,6 @@ class FastRProjectAdapter(mx.ArchivableProject):
                 if not filterfun or filterfun(f):
                     results.append(join(root, f))
 
-
-class FastRTestNativeProject(FastRProjectAdapter):
-    '''
-    Custom class for building the com.oracle.truffle.r.native project.
-    The customization is to support the creation of an exact FASTR_NATIVE_DEV distribution.
-    '''
-    def __init__(self, suite, name, deps, workingSets, theLicense, **args):
-        FastRProjectAdapter.__init__(self, suite, name, deps, workingSets, theLicense)
-
-    def getBuildTask(self, args):
-        return mx.NativeBuildTask(args, self)
-
-    def getResults(self):
-        '''
-        Capture all the files from the com.oracle.truffle.r.test.native project that are needed
-        for running unit tests in an alternate implementation.
-        '''
-        # plain files
-        results = []
-
-        self._get_files(join('packages', 'recommended'), results)
-        self._get_files(join('packages', 'repo'), results)
-
-        results.append(join(self.dir, 'urand', 'lib', 'liburand.so'))
-        return results
-
 class FastRReleaseProject(FastRProjectAdapter):
     '''
     Custom class for creating the FastR release project, which supports the
@@ -219,7 +193,7 @@ class FastRArchiveParticipant:
             # will include all their class files at the top-level of the jar by default.
             # Since we have already encapsulated the class files in 'fastr_jars/fastr.jar' we
             # suppress their inclusion here by resetting the deps field. A bit of a hack.
-        if self.dist.name == "FASTR_RELEASE":
+        if "FASTR_RELEASE" in self.dist.name:
             assert isinstance(self.dist.deps[0], FastRReleaseProject)
             self.release_project = self.dist.deps[0]
             self.dist.deps[0].deps = []
@@ -231,7 +205,7 @@ class FastRArchiveParticipant:
         return False
 
     def __closing__(self):
-        if self.dist.name == "FASTR_RELEASE" and os.environ.has_key('FASTR_RELEASE'):
+        if "FASTR_RELEASE" in self.dist.name and os.environ.has_key('FASTR_RELEASE'):
             # the files copied  in can be confused as source files by
             # e.g., mx copyright, so delete them, specifically thne
             # include dir
@@ -239,5 +213,13 @@ class FastRArchiveParticipant:
             shutil.rmtree(include_dir)
 
 def mx_post_parse_cmd_line(opts):
+    if os.environ.has_key('FASTR_RFFI'):
+        val = os.environ['FASTR_RFFI']
+    else:
+        val = ""
+    mx.instantiateDistribution('FASTR_RELEASE<rffi>', dict(rffi=val))
+
     for dist in mx_fastr._fastr_suite.dists:
-        dist.set_archiveparticipant(FastRArchiveParticipant(dist))
+        if isinstance(dist, mx.JARDistribution):
+            dist.set_archiveparticipant(FastRArchiveParticipant(dist))
+
diff --git a/mx.fastr/mx_fastr_edinclude.py b/mx.fastr/mx_fastr_edinclude.py
index dce5109799b948d7dec404ff2724f92ef4f31235..1ca1490bc01cf29bcb8a3133320c43ceb3a174e3 100644
--- a/mx.fastr/mx_fastr_edinclude.py
+++ b/mx.fastr/mx_fastr_edinclude.py
@@ -34,7 +34,7 @@ r_internals_vars = ['R_NilValue', 'R_UnboundValue', 'R_MissingArg', 'R_GlobalEnv
     'R_LevelsSymbol', 'R_ModeSymbol', 'R_NameSymbol', 'R_NamesSymbol', 'R_NaRmSymbol', 'R_PackageSymbol',
     'R_QuoteSymbol', 'R_RowNamesSymbol', 'R_SeedsSymbol', 'R_SourceSymbol', 'R_TspSymbol', 'R_dot_defined',
     'R_dot_Method', 'R_dot_target', 'R_SrcrefSymbol', 'R_SrcfileSymbol', 'R_NaString', 'R_BlankString',
-    'R_BlankScalarString', 'R_BaseSymbol', 'R_baseSymbol', 'R_NamespaceEnvSymbol']
+    'R_DoubleColonSymbol', 'R_BlankScalarString', 'R_BaseSymbol', 'R_baseSymbol', 'R_NamespaceEnvSymbol']
 
 interface_vars = ['R_Home', 'R_TempDir',]
 
@@ -84,7 +84,8 @@ use_internals_end = '''#endif
 
 '''
 preserveObject = '''#ifdef FASTR
-SEXP R_PreserveObject(SEXP);
+SEXP R_PreserveObject_FASTR(SEXP);
+#define R_PreserveObject(var) ((var) = R_PreserveObject_FASTR((var)))
 #else
 '''
 
diff --git a/mx.fastr/mx_fastr_junit.py b/mx.fastr/mx_fastr_junit.py
deleted file mode 100644
index 9f9555149705ef90c8b13dcf8a98d88f8855b0ed..0000000000000000000000000000000000000000
--- a/mx.fastr/mx_fastr_junit.py
+++ /dev/null
@@ -1,107 +0,0 @@
-#
-# 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.
-#
-from argparse import ArgumentParser, REMAINDER
-import os, tempfile
-import mx
-import mx_fastr
-
-def junit(args, harness, parser=None, jdk_default=None):
-    """run Junit tests"""
-    suppliedParser = parser is not None
-    parser = parser if suppliedParser else ArgumentParser(prog='mx junit')
-    parser.add_argument('--tests', action='store', help='pattern to match test classes')
-    parser.add_argument('--J', dest='vm_args', action='append', help='target VM arguments (e.g. --J @-dsa)', metavar='@<args>')
-    parser.add_argument('--jdk', action='store', help='jdk to use')
-    if suppliedParser:
-        parser.add_argument('remainder', nargs=REMAINDER, metavar='...')
-    args = parser.parse_args(args)
-
-    vmArgs = ['-ea', '-esa']
-
-    if args.vm_args:
-        vmArgs = vmArgs + mx_fastr.split_j_args(args.vm_args)
-
-    testfile = os.environ.get('MX_TESTFILE', None)
-    if testfile is None:
-        (_, testfile) = tempfile.mkstemp(".testclasses", "mx")
-        os.close(_)
-
-    candidates = []
-    if args.jdk:
-        jdk = mx.get_jdk(tag=args.jdk)
-        if not jdk:
-            mx.abort("jdk '" + args.jdk + "' not found")
-    else:
-        if not jdk_default:
-            jdk = mx.get_jdk()
-        else:
-            jdk = jdk_default
-
-    for p in mx.projects(opt_limit_to_suite=True):
-        if not p.isJavaProject() or jdk.javaCompliance < p.javaCompliance:
-            continue
-        candidates += _find_classes_with_annotations(p, None, ['@Test']).keys()
-
-    tests = [] if args.tests is None else [name for name in args.tests.split(',')]
-    classes = []
-    if len(tests) == 0:
-        classes = candidates
-    else:
-        for t in tests:
-            found = False
-            for c in candidates:
-                if t in c:
-                    found = True
-                    classes.append(c)
-            if not found:
-                mx.warn('no tests matched by substring "' + t + '"')
-
-    dists = ['FASTR', 'FASTR_UNIT_TESTS']
-    if mx.suite('r-apptests', fatalIfMissing=False):
-        dists.append('com.oracle.truffle.r.test.apps')
-    vmArgs += mx.get_runtime_jvm_args(dists, jdk=jdk)
-
-    if len(classes) != 0:
-        if len(classes) == 1:
-            testClassArgs = ['--testclass', classes[0]]
-        else:
-            with open(testfile, 'w') as f:
-                for c in classes:
-                    f.write(c + '\n')
-            testClassArgs = ['--testsfile', testfile]
-        junitArgs = ['com.oracle.truffle.r.test.FastRJUnitWrapper'] + testClassArgs
-        rc = harness(args, vmArgs, jdk, junitArgs)
-        return rc
-    else:
-        return 0
-
-def _find_classes_with_annotations(p, pkgRoot, annotations, includeInnerClasses=False):
-    """
-    Scan the sources of project `p` for Java source files containing a line starting with `annotation`
-    (ignoring preceding whitespace) and return the fully qualified class name for each Java
-    source file matched in a list.
-    """
-
-    matches = lambda line: len([a for a in annotations if line == a or line.startswith(a + '(')]) != 0
-    return p.find_classes_with_matching_source_line(pkgRoot, matches, includeInnerClasses)
-
diff --git a/mx.fastr/mx_fastr_pkgs.py b/mx.fastr/mx_fastr_pkgs.py
index 0e7fe3319fc8c82c75c152cd0defda535e9c73e4..cbb29164639e429711ee2970c1d841db91366125 100644
--- a/mx.fastr/mx_fastr_pkgs.py
+++ b/mx.fastr/mx_fastr_pkgs.py
@@ -145,6 +145,18 @@ def _installpkgs(args, **kwargs):
         _ensure_R_on_PATH(env, os.path.dirname(_graalvm_rscript()))
         return mx.run([_graalvm_rscript(), script] + args, **kwargs)
 
+_pta_main_class = 'com.oracle.truffle.r.test.packages.analyzer.PTAMain'
+
+def _pta_project():
+    return 'com.oracle.truffle.r.test.packages.analyzer'
+
+def pta(args, **kwargs):
+    '''
+    Run analysis for package installation/testing results.
+    '''
+    vmArgs = mx.get_runtime_jvm_args(_pta_project())
+    vmArgs += [_pta_main_class]
+    mx.run_java(vmArgs + args)
 
 def pkgtest(args):
     '''
@@ -393,6 +405,7 @@ def _set_test_status(fastr_test_info):
         for gnur_test_output_relpath, gnur_testfile_status in gnur_outputs.iteritems():
             # Can't compare if either GNUR or FastR failed
             if gnur_testfile_status.status == "FAILED":
+                fastr_test_status.status = "INDETERMINATE"
                 break
 
             if not gnur_test_output_relpath in fastr_outputs:
@@ -545,3 +558,20 @@ def pkgtest_cmp(args):
     with open(args[1]) as f:
         fastr_content = f.readlines()
     return _fuzzy_compare(gnur_content, fastr_content)
+
+def find_top100(args):
+    libinstall = join(_fastr_suite_dir(), "top100.tmp")
+    if not os.path.exists(libinstall):
+        os.mkdir(libinstall)
+    os.environ['R_LIBS_USER'] = libinstall
+    _installpkgs(['--find-top100', '--use-installed-pkgs'])
+
+def remove_dup_pkgs(args):
+    pkgs = args[0].split(",")
+    x = dict()
+    for p in pkgs:
+        x[p] = 1
+    result = []
+    for p in x.iterkeys():
+        result += p
+    return result
diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py
index b6c15400151768f64dae88ead2e9cb4863da44c4..4a898db5a388e2dd373b2dd84168c0d92a435a06 100644
--- a/mx.fastr/suite.py
+++ b/mx.fastr/suite.py
@@ -29,7 +29,7 @@ suite = {
             {
                "name" : "truffle",
                "subdir" : True,
-               "version" : "49be77b996566438b7be1f2bf9717b9b9f1c90c1",
+               "version" : "1a54617b9b05c825e6d4a9db1ef783a862fbaf01",
                "urls" : [
                     {"url" : "https://github.com/graalvm/graal", "kind" : "git"},
                     {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"},
@@ -194,10 +194,14 @@ suite = {
     },
 
     "com.oracle.truffle.r.test.native" : {
+      "native" : True,
       "sourceDirs" : [],
       "dependencies" : ["com.oracle.truffle.r.native"],
-      "class" : "FastRTestNativeProject",
-      "native" : "true",
+      "platformDependent" : True,
+      "output" : "com.oracle.truffle.r.test.native",
+      "results" :[
+         "urand/lib/liburand.so",
+       ],
       "workingSets" : "FastR",
     },
 
@@ -207,6 +211,16 @@ suite = {
       "workingSets" : "FastR",
     },
 
+    "com.oracle.truffle.r.test.packages.analyzer" : {
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+        "mx:JUNIT"
+      ],
+      "checkstyle" : "com.oracle.truffle.r.runtime",
+      "javaCompliance" : "1.8",
+      "workingSets" : "FastR",
+    },
+
     "com.oracle.truffle.r.engine" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
@@ -235,6 +249,7 @@ suite = {
     "com.oracle.truffle.r.runtime" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
+        "com.oracle.truffle.r.launcher",
         "truffle:TRUFFLE_API",
         "truffle:TRUFFLE_DEBUG",
         "XZ-1.5",
@@ -249,25 +264,53 @@ suite = {
       "jacoco" : "include",
     },
 
-    "com.oracle.truffle.r.runtime.ffi" : {
+    "com.oracle.truffle.r.launcher" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
-        "com.oracle.truffle.r.nodes",
+        "sdk:GRAAL_SDK",
+        "truffle:JLINE",
       ],
       "checkstyle" : "com.oracle.truffle.r.runtime",
       "javaCompliance" : "1.8",
+      "annotationProcessors" : [
+      ],
       "workingSets" : "Truffle,FastR",
       "jacoco" : "include",
     },
 
+    "com.oracle.truffle.r.ffi.impl" : {
+      "sourceDirs" : ["src"],
+      "dependencies" : [
+         "com.oracle.truffle.r.ffi.processor",
+         "com.oracle.truffle.r.nodes"
+      ],
+      "checkstyle" : "com.oracle.truffle.r.runtime",
+      "javaCompliance" : "1.8",
+      "annotationProcessors" : [
+          "truffle:TRUFFLE_DSL_PROCESSOR",
+          "R_FFI_PROCESSOR",
+      ],
+      "workingSets" : "Truffle,FastR",
+      "jacoco" : "include",
+    },
+
+    "com.oracle.truffle.r.ffi.processor" : {
+      "sourceDirs" : ["src"],
+      "checkstyle" : "com.oracle.truffle.r.runtime",
+      "javaCompliance" : "1.8",
+      "workingSets" : "FastR",
+    },
+
     "com.oracle.truffle.r.native" : {
       "sourceDirs" : [],
+#      "class" : "FastRNativeProject",
       "dependencies" : [
         "GNUR",
         "GNU_ICONV",
         "truffle:TRUFFLE_NFI_NATIVE",
       ],
-      "native" : "true",
+      "native" : True,
+      "single_job" : True,
       "workingSets" : "FastR",
       "buildEnv" : {
         "NFI_INCLUDES" : "-I<path:truffle:TRUFFLE_NFI_NATIVE>/include",
@@ -277,7 +320,7 @@ suite = {
     "com.oracle.truffle.r.library" : {
       "sourceDirs" : ["src"],
       "dependencies" : [
-        "com.oracle.truffle.r.runtime.ffi",
+        "com.oracle.truffle.r.ffi.impl",
       ],
       "annotationProcessors" : [
           "truffle:TRUFFLE_DSL_PROCESSOR",
@@ -300,10 +343,10 @@ suite = {
       "dependencies" : [
         "com.oracle.truffle.r.native",
         "com.oracle.truffle.r.engine",
-        "com.oracle.truffle.r.runtime.ffi"
+        "com.oracle.truffle.r.ffi.impl"
       ],
       "class" : "FastRNativeRecommendedProject",
-      "native" : "true",
+      "native" : True,
       "workingSets" : "FastR",
     },
 
@@ -312,23 +355,26 @@ suite = {
   "distributions" : {
     "TRUFFLE_R_PARSER_PROCESSOR" : {
       "description" : "internal support for generating the R parser",
-      "subDir" : "truffle",
       "dependencies" : ["com.oracle.truffle.r.parser.processor"],
       "exclude" : [
         "ANTLR-3.5",
         "ANTLR-C-3.5",
        ],
        "maven" : "False",
+    },
 
+    "R_FFI_PROCESSOR" : {
+      "description" : "internal support for generating FFI classes",
+      "dependencies" : ["com.oracle.truffle.r.ffi.processor"],
+      "maven" : "False",
     },
 
     "FASTR" : {
       "description" : "class files for compiling against FastR in a separate suite",
-      "dependencies" : ["com.oracle.truffle.r.engine", "com.oracle.truffle.r.runtime.ffi"],
-      "mainClass" : "com.oracle.truffle.r.engine.shell.RCommand",
+      "dependencies" : ["com.oracle.truffle.r.engine", "com.oracle.truffle.r.launcher", "com.oracle.truffle.r.ffi.impl"],
+      "mainClass" : "com.oracle.truffle.r.launcher.RCommand",
       "exclude" : [
         "truffle:JLINE",
-        "ANTLR-C-3.5",
         "ANTLR-3.5",
         "GNUR",
         "GNU_ICONV",
@@ -339,7 +385,6 @@ suite = {
         "truffle:TRUFFLE_DEBUG",
         "truffle:TRUFFLE_NFI",
         "truffle:TRUFFLE_NFI_NATIVE",
-        "TRUFFLE_R_PARSER_PROCESSOR",
       ],
     },
 
@@ -363,49 +408,36 @@ suite = {
 
     "FASTR_UNIT_TESTS_NATIVE" : {
       "description" : "unit tests support (from test.native project)",
-      "exclude" : ["GNUR", "GNU_ICONV"],
-       "os_arch" : {
-         "linux" : {
-           "amd64" : {
-             "path" : "mxbuild/dists/linux/amd64/fastr-unit-tests-native.jar",
-           },
-           "sparcv9" : {
-             "path" : "mxbuild/dists/linux/sparcv9/fastr-unit-tests-native.jar",
-           },
-        },
-        "darwin" : {
-           "amd64" : {
-             "path" : "mxbuild/dists/darwin/amd64/fastr-unit-tests-native.jar",
-           },
-        },
-        "solaris" : {
-           "sparcv9" : {
-             "path" : "mxbuild/dists/solaris/sparcv9/fastr-unit-tests-native.jar",
-           },
-        },
-      },
+       "native" : True,
+       "platformDependent" : True,
+      "dependencies" : [
+        "com.oracle.truffle.r.test.native",
+     ],
     },
 
-    "FASTR_RELEASE": {
+    "FASTR_RELEASE<rffi>": {
       "description" : "a binary release of FastR",
       "dependencies" : ["com.oracle.truffle.r.release"],
        "os_arch" : {
          "linux" : {
           "amd64" : {
-            "path" : "mxbuild/dists/linux/amd64/fastr-release.jar",
+            "path" : "mxbuild/dists/linux/amd64/<rffi>/fastr-release.jar",
           },
           "sparcv9" : {
-            "path" : "mxbuild/dists/linux/sparcv9/fastr-release.jar",
+            "path" : "mxbuild/dists/linux/sparcv9/<rffi>/fastr-release.jar",
           },
         },
         "darwin" : {
           "amd64" : {
-            "path" : "mxbuild/dists/darwin/amd64/fastr-release.jar",
+            "path" : "mxbuild/dists/darwin/amd64/<rffi>/fastr-release.jar",
           },
         },
         "solaris" : {
+          "amd64" : {
+            "path" : "mxbuild/dists/solaris/amd64/<rffi>/fastr-release.jar",
+          },
           "sparcv9" : {
-            "path" : "mxbuild/dists/solaris/sparcv9/fastr-release.jar",
+            "path" : "mxbuild/dists/solaris/sparcv9/<rffi>/fastr-release.jar",
           },
         },
       },