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 5fc6b0f04145fedd0c0fd60b425c98e22aefadc7..cda4d1348e5d18b7e30d5df3f89eaeef21e504f4 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
@@ -152,7 +152,7 @@ public final class REngine implements RContext.Engine {
         return globalFrame;
     }
 
-    public static void checkAndRunStartupFunction(String name) {
+    private static void checkAndRunStartupFunction(String name) {
         Object func = REnvironment.globalEnv().findFunction(name);
         if (func != null) {
             /*
@@ -201,14 +201,6 @@ public final class REngine implements RContext.Engine {
         return parseAndEvalImpl(new ANTLRStringStream(rscript), Source.fromText(rscript, "<test_input>"), REnvironment.globalEnv().getFrame(), printResult, false);
     }
 
-    public class ParseException extends Exception {
-        private static final long serialVersionUID = 1L;
-
-        public ParseException(String msg) {
-            super(msg);
-        }
-    }
-
     public RExpression parse(Source source) throws RContext.Engine.ParseException {
         try {
             Sequence seq = (Sequence) ParseUtil.parseAST(new ANTLRStringStream(source.getCode()), source);
@@ -385,7 +377,7 @@ public final class REngine implements RContext.Engine {
     private static RootCallTarget doMakeCallTarget(RNode body, String funName) {
         FunctionBodyNode fbn = new FunctionBodyNode(SaveArgumentsNode.NO_ARGS, new FunctionStatementsNode(body));
         FrameDescriptor descriptor = new FrameDescriptor();
-        FrameSlotChangeMonitor.initializeFrameDescriptor(descriptor, false);
+        FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(descriptor);
         FunctionDefinitionNode rootNode = new FunctionDefinitionNode(null, descriptor, fbn, FormalArguments.NO_ARGS, funName, true, true);
         RootCallTarget callTarget = Truffle.getRuntime().createCallTarget(rootNode);
         return callTarget;
@@ -437,6 +429,9 @@ public final class REngine implements RContext.Engine {
         return true;
     }
 
+    private static final ArgumentsSignature PRINT_SIGNATURE = ArgumentsSignature.get("x", "...");
+    private static final ArgumentsSignature PRINT_INTERNAL_SIGNATURE = ArgumentsSignature.get("x");
+
     @TruffleBoundary
     private static void printResult(Object result) {
         if (RContext.isVisible()) {
@@ -444,10 +439,10 @@ public final class REngine implements RContext.Engine {
             if (loadBase) {
                 Object printMethod = REnvironment.globalEnv().findFunction("print");
                 RFunction function = (RFunction) (printMethod instanceof RPromise ? PromiseHelperNode.evaluateSlowPath(null, (RPromise) printMethod) : printMethod);
-                function.getTarget().call(RArguments.create(function, null, REnvironment.baseEnv().getFrame(), 1, new Object[]{resultValue, RMissing.instance}));
+                function.getTarget().call(RArguments.create(function, null, REnvironment.baseEnv().getFrame(), 1, new Object[]{resultValue, RMissing.instance}, PRINT_SIGNATURE));
             } else {
                 // we only have the .Internal print.default method available
-                getPrintInternal().getTarget().call(RArguments.create(printInternal, null, REnvironment.baseEnv().getFrame(), 1, new Object[]{resultValue}));
+                getPrintInternal().getTarget().call(RArguments.create(printInternal, null, REnvironment.baseEnv().getFrame(), 1, new Object[]{resultValue}, PRINT_INTERNAL_SIGNATURE));
             }
         }
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/VirtualEvalFrame.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/VirtualEvalFrame.java
index fb1d9b3f6c4caf7eac6f89fbb2fc2bab4ff4590f..74c91a0f8898504fbe50e3ac0189db8fec002451 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/VirtualEvalFrame.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/VirtualEvalFrame.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 @@ import com.oracle.truffle.r.runtime.data.*;
 /**
  * A "fake" {@link VirtualFrame}, to be used by {@link REngine}.eval only!
  */
-public final class VirtualEvalFrame implements VirtualFrame, MaterializedFrame {
+final class VirtualEvalFrame implements VirtualFrame, MaterializedFrame {
 
     private final MaterializedFrame originalFrame;
     @CompilationFinal private final Object[] arguments;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
new file mode 100644
index 0000000000000000000000000000000000000000..affe5ed6e594d67a82cc04885a4d82fd1fe3c295
--- /dev/null
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/utils/Download.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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 java.io.*;
+import java.net.*;
+
+/**
+ * Support for the "internal"method of "utils::download.file". TODO take note of "quiet", "mode" and
+ * "cacheOK".
+ */
+public class Download {
+    @SuppressWarnings("unused")
+    public static void download(String urlString, String destFile, boolean quiet, String mode, boolean cacheOK) throws IOException {
+        URL url = new URL(urlString);
+        byte[] buffer = new byte[8192];
+        try (BufferedInputStream in = new BufferedInputStream(url.openStream()); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(destFile))) {
+            int nread;
+            while ((nread = in.read(buffer)) > 0) {
+                out.write(buffer, 0, nread);
+            }
+        }
+    }
+}
diff --git a/com.oracle.truffle.r.native/platform.mk b/com.oracle.truffle.r.native/platform.mk
index 89bcf019ae25cdd505bbd5b0758a53766b940736..a695488a79001dfbc78f901fc45ace7062f0bc73 100644
--- a/com.oracle.truffle.r.native/platform.mk
+++ b/com.oracle.truffle.r.native/platform.mk
@@ -33,10 +33,10 @@ ifeq ($(OSNAME), Linux)
   LIBS        := -lgfortran
 else ifeq ($(OSNAME), SunOS)
   OS_DIR      := solaris
-  CC          := gcc
-  FC          := gfortran
-  CFLAGS      := -m64 -fPIC -O2
-  LDFLAGS     := -m64 -fPIC -shared
+  CC          := cc
+  FC          := f90
+  CFLAGS      := -m64 -O -xcode=pic13
+  LDFLAGS     := -G -m64
   SHARED_EXT  := so
   LIBS        := -lgfortran
 else ifeq ($(OSNAME), Darwin)
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 a57f183fda4796c8868dbb35233a72219922d27d..685177e89ddcb36a7ba83a890b9c3b466a45ed09 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -41,7 +41,7 @@ public abstract class All extends RBuiltinNode {
     public abstract Object execute(VirtualFrame frame, Object o);
 
     @CreateCast("arguments")
-    public RNode[] castArguments(RNode[] arguments) {
+    protected RNode[] castArguments(RNode[] arguments) {
         arguments[0] = CastLogicalNodeGen.create(arguments[0], true, false, false);
         return arguments;
     }
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 9e1c50c48b441d31a5661859b58d559593097ad9..0420798fc7cc69677648b8e2e49ed56aa64ce44f 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@ public abstract class Any extends RBuiltinNode {
     public abstract Object execute(VirtualFrame frame, Object o);
 
     @CreateCast("arguments")
-    public RNode[] castArguments(RNode[] arguments) {
+    protected RNode[] castArguments(RNode[] arguments) {
         arguments[0] = CastLogicalNodeGen.create(arguments[0], true, false, false);
         return arguments;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
index b8d3d253591f11cfd06ca712d6998d886f36d8eb..a9bb9ebae8f6b7d045a7ba4391f421396f3ad99b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Array.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -54,7 +54,7 @@ public abstract class Array extends RBuiltinNode {
     }
 
     @CreateCast({"arguments"})
-    public RNode[] createCastDimensions(RNode[] children) {
+    protected RNode[] createCastDimensions(RNode[] children) {
         RNode dimsVector = CastToVectorNodeGen.create(children[1], false, false, false, false);
         return new RNode[]{children[0], CastIntegerNodeGen.create(dimsVector, false, false, false), children[2]};
     }
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 3ae0476f9a2e997d355dc52410d7e480181a565e..439aea64b785cb47bce8c4f97e4fa95108a3537b 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
@@ -74,7 +74,7 @@ public class BaseGammaFunctions {
     @RBuiltin(name = "digamma", kind = PRIMITIVE, parameterNames = {"x"})
     public abstract static class DiGamma extends RBuiltinNode {
 
-        @Child DpsiFnCalc dpsiFnCalc;
+        @Child private DpsiFnCalc dpsiFnCalc;
 
         private final NACheck naClosureCheck = NACheck.create();
         private final NACheck naValCheck = NACheck.create();
@@ -142,7 +142,7 @@ public class BaseGammaFunctions {
 
         public abstract double executeDouble(VirtualFrame frame, double x, int n, int kode, double ans);
 
-        @Child DpsiFnCalc dpsiFnCalc;
+        @Child private DpsiFnCalc dpsiFnCalc;
 
         @CompilationFinal private static final double[] bvalues = new double[]{1.00000000000000000e+00, -5.00000000000000000e-01, 1.66666666666666667e-01, -3.33333333333333333e-02,
                         2.38095238095238095e-02, -3.33333333333333333e-02, 7.57575757575757576e-02, -2.53113553113553114e-01, 1.16666666666666667e+00, -7.09215686274509804e+00,
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 ab13da101dff27f6708ea811c0f1e74dff088fc2..5bde3b302f5b0008a2ab5a2b1a3c9ae68ea4c9c8 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
@@ -76,7 +76,7 @@ public abstract class Bind extends RPrecedenceBuiltinNode {
         return RNull.instance;
     }
 
-    private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get(new String[]{"deparse.level", "..."});
+    private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("deparse.level", "...");
 
     @Specialization(guards = {"!oneElement(args)", "isDataFrame(args)"})
     protected Object allDataFrame(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CapabilitiesFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CapabilitiesFunctions.java
index c6d428068a603885583597b349dd6e93a5028c9c..605c24090332440d6d994541faeddb9ccffe13b2 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CapabilitiesFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CapabilitiesFunctions.java
@@ -38,7 +38,7 @@ public class CapabilitiesFunctions {
             tcltk(false, null),
             X11(false, null),
             aqua(false, null),
-            http_fttp(false, "http/ftp"),
+            http_fttp(true, "http/ftp"),
             sockets(false, null),
             libxml(false, null),
             fifo(false, null),
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
index c67e67fc8808e0c44e0f8515565caa480bd32289..604ce950db10be8d49960b38781384e63f042867 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CharMatch.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -30,13 +30,13 @@ public abstract class CharMatch extends RBuiltinNode {
     }
 
     @CreateCast("arguments")
-    public RNode[] castArguments(RNode[] arguments) {
+    protected RNode[] castArguments(RNode[] arguments) {
         arguments[2] = CastIntegerNodeGen.create(arguments[2], true, false, false);
         return arguments;
     }
 
     @Specialization
-    public RIntVector doCharMatch(RAbstractStringVector x, RAbstractStringVector table, RAbstractIntVector noMatch) {
+    protected RIntVector doCharMatch(RAbstractStringVector x, RAbstractStringVector table, RAbstractIntVector noMatch) {
         int noMatchValue = noMatch.getDataAt(0);
         int[] ans = new int[x.getLength()];
         for (int i = 0; i < x.getLength(); ++i) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java
index 64576103ebed6f8e7553c869707b9f810f011495..7dcb7fac32ebf64f7d3134f7d524cc9f0176f6dd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColMeans.java
@@ -35,7 +35,7 @@ public abstract class ColMeans extends RBuiltinNode {
     private final NACheck na = NACheck.create();
 
     @CreateCast("arguments")
-    public RNode[] castArguments(RNode[] arguments) {
+    protected RNode[] castArguments(RNode[] arguments) {
         arguments[1] = CastIntegerNodeGen.create(arguments[1], true, false, false);
         arguments[2] = CastIntegerNodeGen.create(arguments[2], true, false, false);
         return arguments;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java
index 705e2876a1046f4d8c1fdcc33e12b1a85226d4ff..88dff61b4738bb110b87e9e5f3167e7f0632e029 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ColSums.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@ public abstract class ColSums extends RBuiltinNode {
     private final BinaryConditionProfile removeNA = (BinaryConditionProfile) ConditionProfile.createBinaryProfile();
 
     @CreateCast("arguments")
-    public RNode[] castArguments(RNode[] arguments) {
+    protected RNode[] castArguments(RNode[] arguments) {
         arguments[1] = CastIntegerNodeGen.create(arguments[1], true, false, false);
         arguments[2] = CastIntegerNodeGen.create(arguments[2], true, false, false);
         return arguments;
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 f1f9b2a7883484384a5dce5a022cfc140b86d4e5..c816ada6092384efee08151a20c18de8305b9636 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
@@ -150,7 +150,7 @@ public abstract class Combine extends RPrecedenceBuiltinNode {
         return (RList) passVector(list);
     }
 
-    private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get(new String[]{"..."});
+    private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("...");
 
     @Specialization(guards = "isNumericVersion(list)")
     /**
@@ -165,7 +165,7 @@ public abstract class Combine extends RPrecedenceBuiltinNode {
         return (RList) dcn.executeInternal(frame, list.getClassHierarchy(), new Object[]{list});
     }
 
-    public boolean isNumericVersion(RList list) {
+    protected boolean isNumericVersion(RList list) {
         RStringVector klass = list.getClassAttr(attrProfiles);
         if (klass != null) {
             for (int i = 0; i < klass.getLength(); i++) {
@@ -269,7 +269,7 @@ public abstract class Combine extends RPrecedenceBuiltinNode {
         return RDataFactory.createComplexVector(new double[]{value.getRealPart(), value.getImaginaryPart()}, true, getSuppliedSignature().createVector());
     }
 
-    public RAbstractVector namesMerge(RAbstractVector vector, String name) {
+    protected RAbstractVector namesMerge(RAbstractVector vector, String name) {
         RStringVector orgNamesObject = vector.getNames(attrProfiles);
         if ((orgNamesObject == null && name == null) || vector.getLength() == 0) {
             return vector;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
index 61ec72e8da95982e9ef122bbba45a70452f880a3..a458b80f48f29bcfc587993bd249bc27d263aaa9 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Dim.java
@@ -44,7 +44,7 @@ public abstract class Dim extends RBuiltinNode {
 
     private static final String NAME = "dim";
 
-    @Child ShortRowNames shortRowNames;
+    @Child private ShortRowNames shortRowNames;
     @Child private DispatchedCallNode dcn;
 
     private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
index dd663c9f5bc8362ad031d93b88db705d877b34ac..ec33c1d393b2414f835f4075a505720ae93205cc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DuplicatedFunctions.java
@@ -119,7 +119,7 @@ public class DuplicatedFunctions {
     @RBuiltin(name = "duplicated", kind = RBuiltinKind.INTERNAL, parameterNames = {"x", "imcomparables", "fromLast", "nmax"})
     public abstract static class Duplicated extends Adapter {
         @CreateCast("arguments")
-        public RNode[] castArguments(RNode[] arguments) {
+        protected RNode[] castArguments(RNode[] arguments) {
             arguments[2] = CastLogicalNodeGen.create(arguments[2], false, false, false);
             arguments[3] = CastIntegerNodeGen.create(arguments[3], false, false, false);
             return arguments;
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 aac07e22f7c58843cce19f2eccec90ed4b51746f..5113e013e05478480240f524c0e94abecf0a03aa 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
@@ -306,10 +306,10 @@ public class FileFunctions {
             // @formatter:off
             switch(column) {
                 case size: ((double[]) data[slot])[index] = (double) value; complete[slot] = (double) value != RRuntime.DOUBLE_NA; return;
-                case isdir: ((byte[]) data[slot])[index] = (byte) value; complete[slot] = (byte) value == RRuntime.LOGICAL_NA; return;
+                case isdir: ((byte[]) data[slot])[index] = (byte) value; complete[slot] = (byte) value != RRuntime.LOGICAL_NA; return;
                 case mode: case mtime: case ctime: case atime:
-                case uid: case gid: ((int[]) data[slot])[index] = (int) value; complete[slot] = (int) value == RRuntime.INT_NA; return;
-                case uname: case grname: ((String[]) data[slot])[index] = (String) value; complete[slot] = (String) value == RRuntime.STRING_NA; return;
+                case uid: case gid: ((int[]) data[slot])[index] = (int) value; complete[slot] = (int) value != RRuntime.INT_NA; return;
+                case uname: case grname: ((String[]) data[slot])[index] = (String) value; complete[slot] = (String) value != RRuntime.STRING_NA; return;
                 default: throw RInternalError.shouldNotReachHere();
             }
             // @formatter:on
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java
index 070cf6c38ae5344e96293097fdba5e320bf36b99..18d60bbac082ec883ee945deb20cfd81a2b90805 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForeignFunctions.java
@@ -824,6 +824,32 @@ public class ForeignFunctions {
             return matchName(f, "qgamma");
         }
 
+        @Specialization(guards = "isDownload(f)")
+        protected int doDownload(VirtualFrame frame, @SuppressWarnings("unused") RList f, RArgsValuesAndNames args, @SuppressWarnings("unused") RMissing packageName) {
+            controlVisibility();
+            Object[] argValues = args.getValues();
+            String url = isString(argValues[0]);
+            String destFile = isString(argValues[1]);
+            byte quiet = castLogical(frame, castVector(frame, argValues[2]));
+            String mode = isString(argValues[3]);
+            byte cacheOK = castLogical(frame, castVector(frame, argValues[4]));
+            if (url == null || destFile == null || mode == null) {
+                errorProfile.enter();
+                throw RError.error(getEncapsulatingSourceSection(), RError.Message.INVALID_UNNAMED_ARGUMENTS);
+            }
+            try {
+                Download.download(url, destFile, RRuntime.fromLogical(quiet), mode, RRuntime.fromLogical(cacheOK));
+                return 0;
+            } catch (IOException ex) {
+                errorProfile.enter();
+                throw RError.error(getEncapsulatingSourceSection(), RError.Message.GENERIC, ex.getMessage());
+            }
+        }
+
+        public boolean isDownload(RList f) {
+            return matchName(f, "download");
+        }
+
     }
 
     @RBuiltin(name = ".External2", kind = RBuiltinKind.PRIMITIVE, parameterNames = {".NAME", "..."})
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 bdfe24167f01a418645ac855ac4782d958f06b80..59c6f5385e6616962fb3309817f71e1b361a17b3 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
@@ -89,13 +89,6 @@ public abstract class Format extends RBuiltinNode {
         return newChildren;
     }
 
-    @SuppressWarnings("unused")
-    @Specialization(guards = "wrongArgsObject(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec)")
-    protected String formatWrongArgs(Object value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec,
-                    RLogicalVector sciVec) {
-        return null;
-    }
-
     // TODO: handling of logical values has been derived from GNU R, with handling of other
     // types following suit at some point for compliance
 
@@ -110,10 +103,10 @@ public abstract class Format extends RBuiltinNode {
         return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
     }
 
-    @SuppressWarnings("unused")
-    @Specialization(guards = "!wrongArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec)")
-    protected RStringVector format(VirtualFrame frame, RAbstractLogicalVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec,
+    @Specialization
+    protected RStringVector format(RAbstractLogicalVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec,
                     RLogicalVector naEncodeVec, RAbstractVector sciVec) {
+        checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec);
         if (value.getLength() == 0) {
             return RDataFactory.createEmptyStringVector();
         } else {
@@ -166,10 +159,10 @@ public abstract class Format extends RBuiltinNode {
         return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
     }
 
-    @SuppressWarnings("unused")
-    @Specialization(guards = "!wrongArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec)")
+    @Specialization
     protected RStringVector format(RAbstractIntVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec,
                     RLogicalVector naEncodeVec, RAbstractVector sciVec) {
+        checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec);
         if (value.getLength() == 0) {
             return RDataFactory.createEmptyStringVector();
         } else {
@@ -228,10 +221,20 @@ public abstract class Format extends RBuiltinNode {
         return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
     }
 
-    @SuppressWarnings("unused")
-    @Specialization(guards = "!wrongArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec)")
-    protected RStringVector format(VirtualFrame frame, RAbstractDoubleVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec,
+    @Specialization
+    protected RStringVector format(RAbstractDoubleVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec,
                     RLogicalVector naEncodeVec, RAbstractVector sciVec) {
+        checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec);
+        if (value.getLength() == 0) {
+            return RDataFactory.createEmptyStringVector();
+        } else {
+            return convertToString(value);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private void processArguments(VirtualFrame frame, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec,
+                    RAbstractVector sciVec) {
         byte trim = trimVec.getLength() > 0 ? trimVec.getDataAt(0) : RRuntime.LOGICAL_NA;
         int digits = digitsVec.getLength() > 0 ? digitsVec.getDataAt(0) : RRuntime.INT_NA;
         getConfig().digits = digits;
@@ -240,29 +243,24 @@ public abstract class Format extends RBuiltinNode {
         int justify = justifyVec.getLength() > 0 ? justifyVec.getDataAt(0) : RRuntime.INT_NA;
         byte naEncode = naEncodeVec.getLength() > 0 ? naEncodeVec.getDataAt(0) : RRuntime.LOGICAL_NA;
         int sci = computeSciArg(frame, sciVec);
-        if (value.getLength() == 0) {
-            return RDataFactory.createEmptyStringVector();
-        } else {
-            return convertToString(value);
-        }
     }
 
-    @SuppressWarnings("unused")
-    @Specialization(guards = "!wrongArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec)")
+    @Specialization
     protected RStringVector format(RStringVector value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec,
                     RAbstractVector sciVec) {
+        checkArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec);
         // TODO: implement full semantics
         return value;
     }
 
-    @Specialization(guards = "!wrongArgs(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec)")
+    @Specialization
     protected RStringVector format(RFactor value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec,
                     RAbstractVector sciVec) {
         return format(value.getVector(), trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec);
     }
 
     // TruffleDSL bug - should not need multiple guards here
-    protected boolean wrongArgsObject(RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec) {
+    protected void checkArgs(RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec) {
         if (trimVec.getLength() > 0 && RRuntime.isNA(trimVec.getDataAt(0))) {
             errorProfile.enter();
             throw RError.error(getEncapsulatingSourceSection(), RError.Message.INVALID_ARGUMENT, "trim");
@@ -291,11 +289,6 @@ public abstract class Format extends RBuiltinNode {
             errorProfile.enter();
             throw RError.error(getEncapsulatingSourceSection(), RError.Message.INVALID_ARGUMENT, "scientific");
         }
-        return false;
-    }
-
-    protected boolean wrongArgs(RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec) {
-        return wrongArgsObject(trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec);
     }
 
     public static class Config {
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 37c90db01a41355fb20f3a9ade121e654979e4f8..7e2ae372325efe41e4c7e49ef0f762f70753e47c 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
@@ -24,6 +24,8 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
 
+import java.util.*;
+
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
@@ -36,7 +38,7 @@ import com.oracle.truffle.r.nodes.function.*;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.data.RPromise.EvalPolicy;
+import com.oracle.truffle.r.runtime.data.RPromise.*;
 import com.oracle.truffle.r.runtime.env.*;
 
 /**
@@ -88,7 +90,14 @@ public class FrameFunctions {
         }
     }
 
-    private abstract static class CallHelper extends FrameHelper {
+    private abstract static class CallHelper extends FrameHelper implements ClosureCache {
+
+        private final IdentityHashMap<RNode, Closure> closureCache = new IdentityHashMap<>();
+
+        public IdentityHashMap<RNode, Closure> getContent() {
+            return closureCache;
+        }
+
         @TruffleBoundary
         protected RLanguage createCall(Frame cframe, @SuppressWarnings("unused") boolean sysCall, boolean expandDots) {
             SourceSection callSource = RArguments.getCallSourceSection(cframe);
@@ -113,7 +122,7 @@ public class FrameFunctions {
                         for (int i = 0; i < listArgs.length; i++) {
                             listArgs[i] = RASTUtils.createNodeForValue(temp.getValues()[i]);
                         }
-                        RNode varArgs = PromiseNode.createVarArgs(null, EvalPolicy.PROMISED, listArgs, temp.getSignature(), null, null);
+                        RNode varArgs = PromiseNode.createVarArgs(null, EvalPolicy.PROMISED, listArgs, temp.getSignature(), this, null);
                         CallArgumentsNode callArgsNode = CallArgumentsNode.create(false, false, new RNode[]{varArgs}, signature);
                         values = new Object[]{RASTUtils.createCall("list", callArgsNode)};
                         call = RDataFactory.createLanguage(RASTUtils.createCall(functionName, callArgsNode));
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
index ac88eabf7ffdb36bad86a9b5d96f0d8de0054082..cefa0dd8d2cb54a78e1e3d3f7eab946d01cb5ccc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java
@@ -166,6 +166,8 @@ public class HiddenInternalFunctions {
             return lazyLoadDBFetchInternal(frame.materialize(), key, datafile, (int) compressed.getDataAt(0), envhook);
         }
 
+        private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("n");
+
         @TruffleBoundary
         public Object lazyLoadDBFetchInternal(MaterializedFrame frame, RIntVector key, RStringVector datafile, int compression, RFunction envhook) {
             String dbPath = datafile.getDataAt(0);
@@ -207,7 +209,7 @@ public class HiddenInternalFunctions {
                     RSerialize.CallHook callHook = new RSerialize.CallHook() {
 
                         public Object eval(Object arg) {
-                            Object[] callArgs = RArguments.create(envhook, callCache.getSourceSection(), null, RArguments.getDepth(frame) + 1, new Object[]{arg}, ArgumentsSignature.empty(1));
+                            Object[] callArgs = RArguments.create(envhook, callCache.getSourceSection(), null, RArguments.getDepth(frame) + 1, new Object[]{arg}, SIGNATURE);
                             // TODO this cast is problematic
                             return callCache.execute((VirtualFrame) frame, envhook.getTarget(), callArgs);
                         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixEmulationFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixEmulationFunctions.java
index 2b496d6c1c5f5965c3697069815354cde5fe6f7a..e0d733bdce418919beadf269ff6743cd6c82da23 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixEmulationFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/InfixEmulationFunctions.java
@@ -70,7 +70,7 @@ public class InfixEmulationFunctions {
 
         @ExplodeLoop
         public Object execute(VirtualFrame frame, Object vector, Object[] pos, byte exact, Object[] newPositions) {
-            for (int i = 0; i < length; i++) {
+            for (int i = 0; i < getLength(); i++) {
                 newPositions[i] = executeArg(frame, vector, executeConvert(frame, vector, pos[i], exact, i), i);
                 if (multiDimOperatorConverters != null) {
                     newPositions[i] = executeMultiConvert(frame, vector, newPositions[i], i);
@@ -97,7 +97,7 @@ public class InfixEmulationFunctions {
 
         @ExplodeLoop
         public Object execute(VirtualFrame frame, Object vector, Object[] pos, Object[] newPositions, Object value) {
-            for (int i = 0; i < length; i++) {
+            for (int i = 0; i < getLength(); i++) {
                 newPositions[i] = executeArg(frame, vector, executeConvert(frame, vector, pos[i], true, i), i);
                 if (multiDimOperatorConverters != null) {
                     newPositions[i] = executeMultiConvert(frame, vector, value, newPositions[i], i);
@@ -238,7 +238,7 @@ public class InfixEmulationFunctions {
     @RBuiltin(name = "[", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"x", "...", "drop"})
     public abstract static class AccessArraySubsetBuiltin extends AccessArraySubsetBuiltinBase {
 
-        private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get(new String[]{"", "", "drop"});
+        private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("", "", "drop");
 
         private static final String NAME = "[";
 
@@ -354,7 +354,7 @@ public class InfixEmulationFunctions {
     @RBuiltin(name = "[[", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"", "...", "exact"})
     public abstract static class AccessArraySubscriptBuiltin extends AccessArraySubscriptBuiltinBase {
 
-        private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get(new String[]{"", "", "exact"});
+        private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("", "", "exact");
 
         private static final String NAME = "[[";
 
@@ -465,7 +465,7 @@ public class InfixEmulationFunctions {
     @RBuiltin(name = "[<-", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"", "..."})
     public abstract static class UpdateArraySubsetBuiltin extends UpdateArrayBuiltin {
 
-        private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get(new String[]{"", ""});
+        private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("", "");
 
         private static final String NAME = "[<-";
         private static final boolean IS_SUBSET = true;
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 b70656a5f55802c1d4a45bd6b6473b3b3a009ea2..9a065fa2ecb1ee37ee76b24521c0a2caf346438a 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
@@ -13,10 +13,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
 
-import java.util.*;
-
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
@@ -29,7 +26,6 @@ import com.oracle.truffle.r.nodes.binary.*;
 import com.oracle.truffle.r.nodes.builtin.*;
 import com.oracle.truffle.r.nodes.builtin.base.Lapply.GeneralLApplyNode.LapplyIteratorNode;
 import com.oracle.truffle.r.nodes.function.*;
-import com.oracle.truffle.r.nodes.function.MatchedArguments.MatchedArgumentsNode;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.RContext.Engine.ParseException;
 import com.oracle.truffle.r.runtime.data.*;
@@ -89,8 +85,8 @@ public abstract class Lapply extends RBuiltinNode {
         /**
          * These nodes are all independent of the details of a particular call.
          */
-        @Child LapplyIteratorNode iterator = new LapplyIteratorNode();
-        @Child LapplyFunctionNode functionNode = new LapplyFunctionNode();
+        @Child private LapplyIteratorNode iterator = new LapplyIteratorNode();
+        @Child private LapplyFunctionNode functionNode = new LapplyFunctionNode();
         @Child private WriteVariableNode writeVectorElement = WriteVariableNode.create(LAPPLY_VEC_ELEM, iterator, false, false);
         @Child private ReadVariableNode readVectorElement = ReadVariableNode.create(LAPPLY_VEC_ELEM, false);
 
@@ -125,17 +121,17 @@ public abstract class Lapply extends RBuiltinNode {
              * Increments the iterator index, updating the {@link #ITER_INDEX_NAME} variable. Always
              * specializes to the same tree.
              */
-            @Child WriteVariableNode incIndex;
+            @Child private WriteVariableNode incIndex;
             /**
              * Initializes the {@link #ITER_INDEX_NAME} variable to 1 (R indexing rules). Always
              * specializes to the same tree.
              */
-            @Child WriteVariableNode zeroIndex;
+            @Child private WriteVariableNode zeroIndex;
             /**
              * Loads the element of the vector based on the {@code X} variable and the current
              * {@link #ITER_INDEX_NAME} variable. Specialized based on the type of {@code X}.
              */
-            @Child RNode indexedLoad;
+            @Child private RNode indexedLoad;
 
             LapplyIteratorNode() {
                 RNode[] incArgs = new RNode[]{ReadVariableNode.create(ITER_INDEX_NAME, false), ConstantNode.create(1)};
@@ -183,7 +179,7 @@ public abstract class Lapply extends RBuiltinNode {
         protected static class LapplyFunctionNode extends RNode {
             private static final String LAPPLY_FUN = new String("FUN");
 
-            @Child ReadVariableNode readFun;
+            @Child private ReadVariableNode readFun;
 
             public LapplyFunctionNode() {
                 readFun = insert(ReadVariableNode.create(LAPPLY_FUN, false));
@@ -258,27 +254,15 @@ public abstract class Lapply extends RBuiltinNode {
 
             private static final class ResolvedCachedCallNode extends CachedCallNode {
 
-                private static class VarArgNodeState {
-                    final PromiseNode.VarArgNode varArgNode;
-                    final int argIndex;
-
-                    VarArgNodeState(PromiseNode.VarArgNode varArgNode, int argIndex) {
-                        this.varArgNode = varArgNode;
-                        this.argIndex = argIndex;
-                    }
-
-                }
-
                 private final RootCallTarget originalTarget;
                 private final VarArgsSignature originalSignature;
-                @CompilationFinal private ArrayList<VarArgNodeState> varArgNodeStates;
                 @Child private RCallNode callNode;
                 @Child private CachedCallNode next;
 
                 protected ResolvedCachedCallNode(RootCallTarget originalTarget, RArgsValuesAndNames varArgs, CachedCallNode next) {
                     super(next.owner);
                     this.originalTarget = originalTarget;
-                    this.originalSignature = CallArgumentsNode.createSignature(varArgs, 1, true);
+                    this.originalSignature = CallArgumentsNode.createSignature(varArgs, 1);
                     this.callNode = checkFunction(originalTarget, varArgs);
                     this.next = next;
                 }
@@ -290,35 +274,14 @@ public abstract class Lapply extends RBuiltinNode {
 
                 @Override
                 public Object execute(VirtualFrame frame, RootCallTarget target, RArgsValuesAndNames varArgs) {
-                    VarArgsSignature signature = CallArgumentsNode.createSignature(varArgs, 1, true);
-                    if (target != originalTarget || signature.isNotEqualTo(originalSignature)) {
+                    VarArgsSignature signature = CallArgumentsNode.createSignature(varArgs, 1);
+                    if (target != originalTarget || !signature.isEqualTo(originalSignature)) {
                         return next.execute(frame, target, varArgs);
                     } else {
-                        MatchedArgumentsNode m = callNode.getMatchedArgumentsNode();
-                        if (m != null && varArgNodeStates != null) {
-                            RNode[] matchedArgs = m.getArguments();
-                            for (RNode matchedArg : matchedArgs) {
-                                if (matchedArg instanceof PromiseNode.VarargPromiseNode) {
-                                    PromiseNode.VarArgNode varArgNode = ((PromiseNode.VarargPromiseNode) matchedArg).getVarArgNode();
-                                    updatePromise(varArgNode, varArgs);
-                                }
-                            }
-                        }
                         return callNode.execute(frame);
                     }
                 }
 
-                private void updatePromise(PromiseNode.VarArgNode varArgNode, RArgsValuesAndNames varArgs) {
-                    Object varArgNodePromiseRep = varArgNode.getPromise().getRep();
-                    for (VarArgNodeState varArgNodeState : varArgNodeStates) {
-                        Object thisRep = varArgNodeState.varArgNode.getPromise().getRep();
-                        if (varArgNodePromiseRep == thisRep) {
-                            RPromise promise = (RPromise) varArgs.getValues()[varArgNodeState.argIndex];
-                            varArgNode.setPromise(promise);
-                        }
-                    }
-                }
-
                 /**
                  * Creates the {@link RCallNode} for this target and {@code varArgs}.
                  *
@@ -351,14 +314,7 @@ public abstract class Lapply extends RBuiltinNode {
                         args[0] = owner.readVectorElement;
                         Object[] varArgsValues = varArgs.getValues();
                         for (int i = 0; i < varArgs.length(); i++) {
-                            RNode node = CallArgumentsNode.wrapVarArgValue(varArgsValues[i]);
-                            if (node instanceof PromiseNode.VarArgNode) {
-                                if (varArgNodeStates == null) {
-                                    varArgNodeStates = new ArrayList<>(varArgs.length());
-                                }
-                                varArgNodeStates.add(new VarArgNodeState((PromiseNode.VarArgNode) node, i));
-                            }
-                            args[i + 1] = node;
+                            args[i + 1] = CallArgumentsNode.wrapVarArgValue(varArgsValues[i], i);
 
                         }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
index c0769d17bf3f00d0607016371e7eb3f438f7fea7..7ef4de18a7752bd2fd82d524f39e31595be7e12f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java
@@ -102,7 +102,8 @@ public abstract class Match extends RBuiltinNode {
 
     @Specialization
     protected RIntVector match(VirtualFrame frame, RFactor x, RFactor table, Object nomatchObj, Object incomparables) {
-        naCheck.enable(!x.getVector().isComplete() || table.getVector().isComplete());
+        naCheck.enable(x.getVector());
+        naCheck.enable(table.getVector());
         return matchRecursive(frame, RClosures.createFactorToVector(x, naCheck), RClosures.createFactorToVector(table, naCheck), nomatchObj, incomparables);
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
index 06820da55513abdff5024c5bf2806663353e5e09..7992adb6b62a65eed7f2be6a9024268af526a1ba 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java
@@ -774,7 +774,7 @@ public abstract class PrettyPrinterNode extends RNode {
         return prettyPrintList0(operand, listElementName, quote, right);
     }
 
-    protected static double getMaxRoundFactor(RAbstractDoubleVector operand) {
+    private static double getMaxRoundFactor(RAbstractDoubleVector operand) {
         double maxRoundFactor = 0;
         for (int i = 0; i < operand.getLength(); i++) {
             double data = operand.getDataAt(i);
@@ -786,7 +786,7 @@ public abstract class PrettyPrinterNode extends RNode {
         return maxRoundFactor;
     }
 
-    protected static int getMaxDigitsBehindDot(double maxRoundFactor) {
+    private static int getMaxDigitsBehindDot(double maxRoundFactor) {
         int maxDigitsBehindDot = 0;
         for (double j = 1; j < maxRoundFactor; j *= 10) {
             maxDigitsBehindDot++;
@@ -898,7 +898,7 @@ public abstract class PrettyPrinterNode extends RNode {
         return printVector(operand, values, false, false);
     }
 
-    protected static boolean twoDimsOrMore(RAbstractVector v) {
+    protected static boolean twoDimsOrMore(RAbstractContainer v) {
         return v.hasDimensions() && v.getDimensions().length > 1;
     }
 
@@ -1271,14 +1271,9 @@ public abstract class PrettyPrinterNode extends RNode {
             return v instanceof RList;
         }
 
-        protected static boolean isLengthOne(RList v) {
-            return v.getLength() == 1;
-        }
-
         protected static boolean isLengthOne(RAbstractVector v) {
             return v.getLength() == 1;
         }
-
     }
 
     @NodeChildren({@NodeChild(value = "vector", type = RNode.class), @NodeChild(value = "isListOrStringVector", type = RNode.class), @NodeChild(value = "isComplexOrRawVector", type = RNode.class),
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 ba9c0b921c48392778ef9dc12dd8a38b3583200e..312798b4ef8be8b08dee727c06601179bcf09bf7 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +34,7 @@ import com.oracle.truffle.r.runtime.data.*;
 
 @RBuiltin(name = ".Primitive", kind = PRIMITIVE, parameterNames = "name")
 public abstract class Primitive extends RBuiltinNode {
-    protected final BranchProfile errorProfile = BranchProfile.create();
+    private final BranchProfile errorProfile = BranchProfile.create();
 
     @Override
     public RNode[] getParameterValues() {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
index 11d1904d5ac854487edfdeafb332a4c0af598663..c7d6693ea2d8041492e54d6bf6c9717487cd2076 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Recall.java
@@ -24,11 +24,13 @@ package com.oracle.truffle.r.nodes.builtin.base;
 
 import static com.oracle.truffle.r.runtime.RBuiltinKind.*;
 
+import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.nodes.function.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 
@@ -48,9 +50,15 @@ public abstract class Recall extends RBuiltinNode {
             throw RError.error(getEncapsulatingSourceSection(), RError.Message.RECALL_CALLED_OUTSIDE_CLOSURE);
         }
 
+        EvaluatedArguments evaluated = match(args, function);
+
         // Use arguments in "..." as arguments for RECALL call
-        Object[] argsObject = RArguments.create(function, callCache.getSourceSection(), null, RArguments.getDepth(frame) + 1, args.getValues());
+        Object[] argsObject = RArguments.create(function, callCache.getSourceSection(), null, RArguments.getDepth(frame) + 1, evaluated.getEvaluatedArgs(), evaluated.getSignature());
         return callCache.execute(frame, function.getTarget(), argsObject);
     }
 
+    @TruffleBoundary
+    private EvaluatedArguments match(RArgsValuesAndNames args, RFunction function) {
+        return ArgumentMatcher.matchArgumentsEvaluated(function, EvaluatedArguments.create(args.getValues(), args.getSignature()), getSourceSection(), false);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java
index 4cd05501dceb444977c04050c14975b75921c0b2..d6a9bf83d96f7ab350cb0f0287da83e1ce60e293 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Seq.java
@@ -664,14 +664,14 @@ public abstract class Seq extends RBuiltinNode {
     }
 
     @Specialization(guards = {"toLengthOne(to)", "positiveLengthOut(lengthOut)"})
-    public RDoubleSequence seq(RMissing start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) {
+    protected RDoubleSequence seq(RMissing start, RAbstractIntVector to, RMissing stride, int lengthOut, RMissing alongWith) {
         controlVisibility();
         validateParam(to.getDataAt(0), "to");
         return RDataFactory.createDoubleSequence(to.getDataAt(0) - lengthOut + 1, 1, lengthOut);
     }
 
     @Specialization(guards = {"toLengthOne(to)", "positiveLengthOut(lengthOut)"})
-    public RDoubleSequence seq(RMissing start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) {
+    protected RDoubleSequence seq(RMissing start, RAbstractIntVector to, RMissing stride, double lengthOut, RMissing alongWith) {
         controlVisibility();
         validateParam(to.getDataAt(0), "to");
         final int intLength = (int) Math.ceil(lengthOut);
@@ -679,14 +679,14 @@ public abstract class Seq extends RBuiltinNode {
     }
 
     @Specialization(guards = {"toLengthOne(to)", "positiveLengthOut(lengthOut)"})
-    public RDoubleSequence seq(RMissing start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) {
+    protected RDoubleSequence seq(RMissing start, RAbstractDoubleVector to, RMissing stride, double lengthOut, RMissing alongWith) {
         controlVisibility();
         validateParam(to.getDataAt(0), "to");
         return RDataFactory.createDoubleSequence(to.getDataAt(0) - lengthOut + 1, 1, (int) Math.ceil(lengthOut));
     }
 
     @Specialization(guards = "toLengthOne(to)")
-    public Object seq(VirtualFrame frame, RMissing start, RAbstractVector to, Object stride, RMissing lengthOut, RMissing alongWith) {
+    protected Object seq(VirtualFrame frame, RMissing start, RAbstractVector to, Object stride, RMissing lengthOut, RMissing alongWith) {
         controlVisibility();
         return seqRecursive(frame, 1.0, to, stride, lengthOut, alongWith);
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
index 0a5340983afc99f17a8c712182b95081278faf0a..951fde9bf6860dd77dd59ab28f50485e71998536 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sprintf.java
@@ -42,7 +42,7 @@ public abstract class Sprintf extends RBuiltinNode {
 
     public abstract Object executeObject(VirtualFrame frame, String fmt, Object args);
 
-    @Child Sprintf sprintfRecursive;
+    @Child private Sprintf sprintfRecursive;
 
     @Specialization
     @TruffleBoundary
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 57a4ea8d877ce54b811f4d506a3eb1c17bef2bf5..08ddb759c539b6c7acba2809b9b8e03c79ade705 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
@@ -41,7 +41,7 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL;
 
 @RBuiltin(name = "substr", kind = INTERNAL, parameterNames = {"x", "start", "stop"})
 public abstract class Substr extends RBuiltinNode {
-    protected final NACheck na = NACheck.create();
+    private final NACheck na = NACheck.create();
     private final BranchProfile everSeenIllegalRange = BranchProfile.create();
     private final ConditionProfile naIndexesProfile = ConditionProfile.createBinaryProfile();
 
@@ -78,7 +78,7 @@ public abstract class Substr extends RBuiltinNode {
         return RDataFactory.createStringVector(res, na.neverSeenNA());
     }
 
-    protected String substr0(String x, int start, int stop) {
+    private String substr0(String x, int start, int stop) {
         if (naIndexesProfile.profile(na.check(x) || na.check(start) || na.check(stop))) {
             return RRuntime.STRING_NA;
         } else {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index 7c61a923ce7cf891b90c90febf99f4871fa3ddae..e597e6c1944f94af78ed541d052bdc28a3163c69 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -197,7 +197,7 @@ public abstract class UpdateAttr extends RInvisibleBuiltinNode {
 
     // the guard is necessary as RNull and Object cannot be distinguished in case of multiple
     // specializations, such as in: x<-1; attr(x, "dim")<-1; attr(x, "dim")<-NULL
-    public boolean nullValue(Object value) {
+    protected boolean nullValue(Object value) {
         return value == RNull.instance;
     }
 
@@ -226,8 +226,4 @@ public abstract class UpdateAttr extends RInvisibleBuiltinNode {
             throw RError.nyi(getEncapsulatingSourceSection(), ": object cannot be attributed");
         }
     }
-
-    public boolean nullValueforEnv(REnvironment env, String name, Object value) {
-        return value == RNull.instance;
-    }
 }
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 f591486d7a9097c270557c2ad7308cbf4b5ad517..2e6c69ab060fcf0166e42a7c083bbeb9b2d43738 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
@@ -86,14 +86,7 @@ public abstract class UpdateOldClass extends RInvisibleBuiltinNode {
         return RVector.setVectorClassAttr(resultVector, null, arg.getElementClass() == RDataFrame.class ? arg : null, arg.getElementClass() == RFactor.class ? arg : null);
     }
 
-    @TruffleBoundary
-    public Object setOldClass(RFunction arg, @SuppressWarnings("unused") Object className) {
-        controlVisibility();
-        return arg;
-    }
-
     protected boolean isStringVector(RAbstractVector className) {
         return className.getElementClass() == RString.class;
     }
-
 }
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 135d3eca0fd94539c39e0acce3a4eac4607006fa..852dba6be2eeb7ff67b57b356744002a1cdc2d69 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
@@ -36,6 +36,7 @@ import com.oracle.truffle.r.nodes.function.PromiseNode.VarArgsPromiseNode;
 import com.oracle.truffle.r.nodes.instrument.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
+import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.env.*;
 
 /**
@@ -97,21 +98,18 @@ public class RASTUtils {
             return ((ConstantNode) argNode).getValue();
         } else if (argNode instanceof ReadVariableNode) {
             return RASTUtils.createRSymbol(argNode);
-        } else if (argNode instanceof VarArgNode) {
-            RPromise p = ((VarArgNode) argNode).getPromise();
-            return createLanguageElement(unwrap(p.getRep()));
         } else if (argNode instanceof VarArgsPromiseNode) {
             /*
              * This is mighty tedious, but GnuR represents this as a pairlist and we do have to
              * convert it into either an RPairList or an RList for compatibility.
              */
             VarArgsPromiseNode vapn = ((VarArgsPromiseNode) argNode);
-            RNode[] nodes = vapn.getNodes();
+            Closure[] closures = vapn.getClosures();
             ArgumentsSignature signature = vapn.getSignature();
             RPairList prev = null;
             RPairList result = null;
-            for (int i = 0; i < nodes.length; i++) {
-                RPairList pl = RDataFactory.createPairList(createLanguageElement(unwrap(nodes[i])), null, signature.getName(i));
+            for (int i = 0; i < closures.length; i++) {
+                RPairList pl = RDataFactory.createPairList(createLanguageElement(unwrap(closures[i].getExpr())), null, signature.getName(i));
                 if (prev != null) {
                     prev.setCdr(pl);
                 } else {
@@ -121,6 +119,7 @@ public class RASTUtils {
             }
             return result;
         } else {
+            assert !(argNode instanceof VarArgNode);
             return RDataFactory.createLanguage(argNode);
         }
     }
@@ -323,6 +322,20 @@ public class RASTUtils {
             RNode[] expandedNodes = new RNode[values.length];
             for (int i = 0; i < values.length; i++) {
                 Object argval = values[i];
+                while (argval instanceof RPromise) {
+                    RPromise promise = (RPromise) argval;
+                    Node unwrap = RASTUtils.unwrap(promise.getRep());
+                    if (unwrap instanceof VarArgNode) {
+                        VarArgNode varArgNode = (VarArgNode) unwrap;
+                        try {
+                            RArgsValuesAndNames v = (RArgsValuesAndNames) promise.getFrame().getObject(promise.getFrame().getFrameDescriptor().findFrameSlot("..."));
+                            argval = v.getValues()[varArgNode.getIndex()];
+                        } catch (FrameSlotTypeException e) {
+                            throw RInternalError.shouldNotReachHere();
+                        }
+                    }
+                    break;
+                }
                 if (argval instanceof RPromise) {
                     RPromise promise = (RPromise) argval;
                     expandedNodes[i] = (RNode) RASTUtils.unwrap(promise.getRep());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RNode.java
index c809b485f1a1aa76b0a803df821085ce5a0310c7..77e0a11e0af4820f3f5ba38803b3bc5229465fc4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RNode.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.nodes;
 
+import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
@@ -213,4 +214,32 @@ public abstract class RNode extends Node implements RSyntaxNode, RInstrumentable
     public boolean isInstrumentable() {
         return true;
     }
+
+    private static final long WORK_SCALE_FACTOR = 100;
+
+    /**
+     * Nodes that can do a significant amount of work in one execution (like arithmetic on vectors)
+     * can use this method to report the work to the Truffle system, similar to loop counts.
+     *
+     * @param amount an approximation of the number of operations
+     */
+    protected void reportWork(long amount) {
+        if (CompilerDirectives.inInterpreter()) {
+            reportWorkInternal(amount);
+        }
+    }
+
+    @TruffleBoundary
+    private void reportWorkInternal(long amount) {
+        CompilerAsserts.neverPartOfCompilation();
+        if (amount >= WORK_SCALE_FACTOR) {
+            int scaledAmount = (int) (amount / WORK_SCALE_FACTOR);
+            if (amount > 0) {
+                RootNode root = getRootNode();
+                if (root.getCallTarget() instanceof LoopCountReceiver) {
+                    ((LoopCountReceiver) root.getCallTarget()).reportLoopCount(scaledAmount);
+                }
+            }
+        }
+    }
 }
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 f3d114ed2750d064fba55ce2e01441b559fe7842..c998d7e6f3820e535bd03871e055dee0f2cc3115 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
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.env.frame.*;
  * The base class for R code that can be executed, namely {@link FunctionDefinitionNode} and
  * {@link RBuiltinNode}.
  */
-public abstract class RRootNode extends RootNode {
+public abstract class RRootNode extends RootNode implements HasSignature {
 
     @CompilationFinal private StableValue<MaterializedFrame> enclosingFrameAssumption;
     @CompilationFinal private StableValue<FrameDescriptor> enclosingFrameDescriptorAssumption;
@@ -74,7 +74,7 @@ public abstract class RRootNode extends RootNode {
                 if (enclosingFrameAssumption != null) {
                     if (enclosingFrameAssumption.getValue() != enclosingFrame) {
                         CompilerDirectives.transferToInterpreterAndInvalidate();
-                        enclosingFrameAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameAssumption(getFrameDescriptor(), enclosingFrameAssumption, enclosingFrame);
+                        enclosingFrameAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameAssumption(vf.materialize(), getFrameDescriptor(), enclosingFrameAssumption, enclosingFrame);
                     }
                 }
             }
@@ -90,7 +90,7 @@ public abstract class RRootNode extends RootNode {
                 FrameDescriptor enclosingFrameDescriptor = enclosingFrame == null ? null : enclosingFrameProfile.profile(enclosingFrame).getFrameDescriptor();
                 if (enclosingFrameDescriptorAssumption.getValue() != enclosingFrameDescriptor) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
-                    enclosingFrameDescriptorAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameDescriptorAssumption(getFrameDescriptor(), enclosingFrameDescriptorAssumption,
+                    enclosingFrameDescriptorAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameDescriptorAssumption(vf, getFrameDescriptor(), enclosingFrameDescriptorAssumption,
                                     enclosingFrameDescriptor);
                 }
             }
@@ -111,6 +111,10 @@ public abstract class RRootNode extends RootNode {
         return formalArguments;
     }
 
+    public ArgumentsSignature getSignature() {
+        return formalArguments.getSignature();
+    }
+
     @TruffleBoundary
     public String getSourceCode() {
         SourceSection ss = getSourceSection();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RSyntaxNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RSyntaxNode.java
index b842db3d30cd314112fc14da98ed0821b9b6ef58..0e2f8e064bd0628644bbe7ac236c6ba172f19ec7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RSyntaxNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RSyntaxNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,7 @@ public interface RSyntaxNode {
      * implementation convenience.
      */
     default void deparse(@SuppressWarnings("unused") State state) {
-        throw RInternalError.unimplemented();
+        throw RInternalError.unimplemented("deparse not implemented in " + getClass());
     }
 
     /**
@@ -50,7 +50,7 @@ public interface RSyntaxNode {
      * that no changes were made.
      */
     default RNode substitute(@SuppressWarnings("unused") REnvironment env) {
-        throw RInternalError.unimplemented();
+        throw RInternalError.unimplemented("substitute not implemented in " + getClass());
     }
 
     /**
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
index 7620a280d372da8cc1b2ce06f5a1ce36b1d69092..5b240ac9cc541196cf5a82cd4831c3dfb780de36 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java
@@ -38,6 +38,7 @@ import com.oracle.truffle.r.nodes.unary.*;
 import com.oracle.truffle.r.options.*;
 import com.oracle.truffle.r.parser.ast.*;
 import com.oracle.truffle.r.parser.ast.Constant.ConstantType;
+import com.oracle.truffle.r.parser.ast.Operation.*;
 import com.oracle.truffle.r.parser.tools.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
@@ -186,7 +187,7 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> {
             }
 
             FrameDescriptor descriptor = new FrameDescriptor();
-            FrameSlotChangeMonitor.initializeFrameDescriptor(descriptor, false);
+            FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(descriptor);
             String description = getFunctionDescription(func);
             FunctionDefinitionNode rootNode = new FunctionDefinitionNode(func.getSource(), descriptor, new FunctionBodyNode(saveArguments, statements), formals, description, false);
             callTarget = Truffle.getRuntime().createCallTarget(rootNode);
@@ -208,8 +209,8 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> {
     @Override
     public RNode visit(UnaryOperation op) {
         RNode operand = op.getLHS().accept(this);
-        final String functionName = op.getPrettyOperator();
-        final CallArgumentsNode aCallArgNode = CallArgumentsNode.createUnnamed(false, true, operand);
+        String functionName = op.getOperator().getName();
+        CallArgumentsNode aCallArgNode = CallArgumentsNode.createUnnamed(false, true, operand);
         if (!FastROptions.DisableGroupGenerics.getValue() && RGroupGenerics.isGroupGeneric(functionName)) {
             return GroupDispatchCallNode.create(functionName, RGroupGenerics.GROUP_OPS, aCallArgNode, op.getSource());
         }
@@ -220,12 +221,16 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> {
     public RNode visit(BinaryOperation op) {
         RNode left = op.getLHS().accept(this);
         RNode right = op.getRHS().accept(this);
-        final String functionName = op.getPrettyOperator();
-        final CallArgumentsNode aCallArgNode = CallArgumentsNode.createUnnamed(false, true, left, right);
-        if (!FastROptions.DisableGroupGenerics.getValue() && RGroupGenerics.isGroupGeneric(functionName)) {
-            return GroupDispatchCallNode.create(functionName, RGroupGenerics.getGroup(functionName), aCallArgNode, op.getSource());
+        if (op.getOperator() == Operator.COLON) {
+            return ColonNode.create(op.getSource(), left, right);
+        } else {
+            String functionName = op.getOperator().getName();
+            CallArgumentsNode aCallArgNode = CallArgumentsNode.createUnnamed(false, true, left, right);
+            if (!FastROptions.DisableGroupGenerics.getValue() && RGroupGenerics.isGroupGeneric(functionName)) {
+                return GroupDispatchCallNode.create(functionName, RGroupGenerics.getGroup(functionName), aCallArgNode, op.getSource());
+            }
+            return RCallNode.createStaticCall(op.getSource(), functionName, aCallArgNode, op);
         }
-        return RCallNode.createStaticCall(op.getSource(), functionName, aCallArgNode, op);
     }
 
     @Override
@@ -499,14 +504,6 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> {
         return createVectorUpdate(u.getVector(), u.getRHS().accept(this), u.isSuper(), u.getSource(), false);
     }
 
-    @Override
-    public RNode visit(Colon c) {
-        // TODO convert to function call
-        RNode left = c.getLHS().accept(this);
-        RNode right = c.getRHS().accept(this);
-        return ColonNode.create(c.getSource(), left, right);
-    }
-
     @Override
     public RNode visit(SimpleAssignVariable n) {
         if (n.getExpr() instanceof Function) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTypes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTypes.java
index 23a0dd5ced339c567555bef4d84240ca6da21f2f..1930d991224f1685103e50bdd758f4bb3b4ee0b6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTypes.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTypes.java
@@ -42,7 +42,7 @@ import com.oracle.truffle.r.runtime.env.*;
                 RRawVector.class, RComplexVector.class, RStringVector.class, RLogicalVector.class, RFunction.class, RNull.class, RMissing.class, REnvironment.class, RExpression.class,
                 RConnection.class, MaterializedFrame.class, FrameSlot.class, RAbstractIntVector.class, RAbstractDoubleVector.class, RAbstractLogicalVector.class, RAbstractComplexVector.class,
                 RAbstractStringVector.class, RAbstractRawVector.class, RList.class, RAbstractVector.class, RDataFrame.class, RFactor.class, RSymbol.class, RPromise.class, RLanguage.class,
-                RPairList.class, RFormula.class, RExternalPtr.class, RAbstractContainer.class, RAttributable.class, RArgsValuesAndNames.class, RType.class, Object[].class})
+                RPairList.class, RFormula.class, RExternalPtr.class, RAbstractContainer.class, RAttributable.class, RTypedValue.class, RArgsValuesAndNames.class, RType.class, Object[].class})
 public class RTypes {
 
     @TypeCheck(RNull.class)
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 87982e0913130c5dd6af4624439c8267207385d0..3dc0a7c802edc8b1098f522dc17b2ff5bc1df4a7 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
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.access.variables.*;
 import com.oracle.truffle.r.nodes.function.*;
@@ -50,6 +51,10 @@ public abstract class AccessArgumentNode extends RNode {
 
     @Child private PromiseHelperNode promiseHelper;
 
+    private final ConditionProfile topLevelInlinedPromiseProfile = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile varArgInlinedPromiseProfile = ConditionProfile.createBinaryProfile();
+    private final ConditionProfile varArgIsPromiseProfile = ConditionProfile.createBinaryProfile();
+
     /**
      * The formal index of this argument.
      */
@@ -68,11 +73,11 @@ public abstract class AccessArgumentNode extends RNode {
     @CompilationFinal private boolean deoptimized;
     @CompilationFinal private boolean defaultArgCanBeOptimized = EagerEvalHelper.optConsts() || EagerEvalHelper.optVars() || EagerEvalHelper.optExprs();
 
-    public AccessArgumentNode(int index) {
+    protected AccessArgumentNode(int index) {
         this.index = index;
     }
 
-    public AccessArgumentNode(AccessArgumentNode prev) {
+    protected AccessArgumentNode(AccessArgumentNode prev) {
         this.index = prev.index;
         formals = prev.formals;
         hasDefaultArg = prev.hasDefaultArg;
@@ -104,27 +109,44 @@ public abstract class AccessArgumentNode extends RNode {
     }
 
     @Specialization
-    public Object doArgument(VirtualFrame frame, RPromise promise) {
-        return handlePromise(frame, promise);
+    protected Object doArgument(VirtualFrame frame, RPromise promise) {
+        return handlePromise(frame, promise, topLevelInlinedPromiseProfile);
     }
 
-    @Specialization
-    public Object doArgument(VirtualFrame frame, RArgsValuesAndNames varArgsContainer) {
+    private void handleVarArgPromise(VirtualFrame frame, Object[] varArgs, int i) {
+        // DON'T use exprExecNode here, as caching would fail here: Every argument wrapped into
+        // "..." is a different expression
+
+        if (varArgIsPromiseProfile.profile(varArgs[i] instanceof RPromise)) {
+            varArgs[i] = handlePromise(frame, (RPromise) varArgs[i], varArgInlinedPromiseProfile);
+        }
+    }
+
+    @Specialization(limit = "1", guards = "cachedVarArgLength == varArgsContainer.length()")
+    @ExplodeLoop
+    protected Object doArgumentCached(VirtualFrame frame, RArgsValuesAndNames varArgsContainer, @Cached("varArgsContainer.length()") int cachedVarArgLength) {
+        Object[] varArgs = varArgsContainer.getValues();
+        for (int i = 0; i < cachedVarArgLength; i++) {
+            handleVarArgPromise(frame, varArgs, i);
+        }
+        return varArgsContainer;
+    }
+
+    @Specialization(contains = "doArgumentCached")
+    protected Object doArgument(VirtualFrame frame, RArgsValuesAndNames varArgsContainer) {
         Object[] varArgs = varArgsContainer.getValues();
         for (int i = 0; i < varArgsContainer.length(); i++) {
-            // DON'T use exprExecNode here, as caching would fail here: Every argument wrapped into
-            // "..." is a different expression
-            varArgs[i] = varArgs[i] instanceof RPromise ? handlePromise(frame, (RPromise) varArgs[i]) : varArgs[i];
+            handleVarArgPromise(frame, varArgs, i);
         }
         return varArgsContainer;
     }
 
-    private Object handlePromise(VirtualFrame frame, RPromise promise) {
+    private Object handlePromise(VirtualFrame frame, RPromise promise, ConditionProfile inlinedPromiseProfile) {
         assert !promise.isNonArgument();
 
         // Now force evaluation for INLINED (might be the case for arguments by S3MethodDispatch)
 
-        if (promise.isInlined()) {
+        if (inlinedPromiseProfile.profile(promise.isInlined())) {
             if (promiseHelper == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 promiseHelper = insert(new PromiseHelperNode());
@@ -135,14 +157,14 @@ public abstract class AccessArgumentNode extends RNode {
     }
 
     @Specialization(guards = {"!hasDefaultArg()", "!isVarArgIndex()"})
-    public Object doArgumentNoDefaultArg(RMissing argMissing) {
+    protected Object doArgumentNoDefaultArg(RMissing argMissing) {
         // Simply return missing if there's no default arg OR it represents an empty "..."
         // (Empty "..." defaults to missing anyway, this way we don't have to rely on )
         return argMissing;
     }
 
     @Specialization(guards = {"hasDefaultArg()"})
-    public Object doArgumentDefaultArg(VirtualFrame frame, @SuppressWarnings("unused") RMissing argMissing) {
+    protected Object doArgumentDefaultArg(VirtualFrame frame, @SuppressWarnings("unused") RMissing argMissing) {
         Object result;
         if (canBeOptimized()) {
             // Insert default value
@@ -174,7 +196,7 @@ public abstract class AccessArgumentNode extends RNode {
         return isVarArgIndex;
     }
 
-    protected boolean canBeOptimized() {
+    private boolean canBeOptimized() {
         return !deoptimized && defaultArgCanBeOptimized;
     }
 
@@ -211,7 +233,7 @@ public abstract class AccessArgumentNode extends RNode {
     }
 
     @Fallback
-    public Object doArgument(Object obj) {
+    protected Object doArgument(Object obj) {
         return obj;
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessFieldBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessFieldBaseNode.java
new file mode 100644
index 0000000000000000000000000000000000000000..dd2cc588a3b76480b7a31c506a8ddc4754e3c21b
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessFieldBaseNode.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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.access;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.*;
+import com.oracle.truffle.api.utilities.*;
+import com.oracle.truffle.r.nodes.*;
+import com.oracle.truffle.r.runtime.data.*;
+
+@NodeChild(value = "object", type = RNode.class)
+@NodeField(name = "field", type = String.class)
+public abstract class AccessFieldBaseNode extends RNode {
+
+    public abstract RNode getObject();
+
+    public abstract String getField();
+
+    protected final ConditionProfile hasNamesProfile = ConditionProfile.createBinaryProfile();
+    protected final BranchProfile inexactMatch = BranchProfile.create();
+    protected final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
+
+    @TruffleBoundary
+    public static int getElementIndexByName(RStringVector names, String name) {
+        for (int i = 0; i < names.getLength(); ++i) {
+            if (names.getDataAt(i).equals(name)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+}
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessFieldNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessFieldNode.java
index f108a76ac5f0ebac828798f4316852ef64b749d8..6bd99001d306fa0dda9bcd7cbc1286662424f81f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessFieldNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessFieldNode.java
@@ -23,7 +23,6 @@
 package com.oracle.truffle.r.nodes.access;
 
 import com.oracle.truffle.api.dsl.*;
-import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.RDeparse.State;
@@ -34,52 +33,43 @@ import com.oracle.truffle.r.runtime.env.*;
 /**
  * Perform a field access. This node represents the {@code $} operator in R.
  */
-@NodeChild(value = "object", type = RNode.class)
-@NodeField(name = "field", type = String.class)
-public abstract class AccessFieldNode extends RNode {
-
-    public abstract RNode getObject();
-
-    public abstract String getField();
-
-    private final BranchProfile inexactMatch = BranchProfile.create();
-    private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
+public abstract class AccessFieldNode extends AccessFieldBaseNode {
 
     @Specialization
     protected RNull access(@SuppressWarnings("unused") RNull object) {
         return RNull.instance;
     }
 
-    @Specialization(guards = "hasNames(object)")
+    @Specialization
     protected Object accessField(RList object) {
-        int index = object.getElementIndexByName(attrProfiles, getField());
-        if (index == -1) {
-            inexactMatch.enter();
-            index = object.getElementIndexByNameInexact(attrProfiles, getField());
+        RStringVector names = object.getNames(attrProfiles);
+        if (hasNamesProfile.profile(names != null)) {
+            int index = getElementIndexByName(names, getField());
+            if (index == -1) {
+                inexactMatch.enter();
+                index = object.getElementIndexByNameInexact(attrProfiles, getField());
+            }
+            return index == -1 ? RNull.instance : object.getDataAt(index);
+        } else {
+            return RNull.instance;
         }
-        return index == -1 ? RNull.instance : object.getDataAt(index);
-    }
-
-    @Specialization(guards = "!hasNames(object)")
-    protected Object accessFieldNoNames(@SuppressWarnings("unused") RList object) {
-        return RNull.instance;
     }
 
     // TODO: this should ultimately be a generic function
-    @Specialization(guards = "hasNames(object)")
+    @Specialization
     protected Object accessField(RDataFrame object) {
-        int index = object.getElementIndexByName(attrProfiles, getField());
-        if (index == -1) {
-            inexactMatch.enter();
-            index = object.getElementIndexByNameInexact(attrProfiles, getField());
-            // TODO: add warning if index found (disabled by default using options)
+        RStringVector names = object.getNames(attrProfiles);
+        if (hasNamesProfile.profile(names != null)) {
+            int index = getElementIndexByName(names, getField());
+            if (index == -1) {
+                inexactMatch.enter();
+                index = object.getElementIndexByNameInexact(attrProfiles, getField());
+                // TODO: add warning if index found (disabled by default using options)
+            }
+            return index == -1 ? RNull.instance : object.getDataAtAsObject(index);
+        } else {
+            return RNull.instance;
         }
-        return index == -1 ? RNull.instance : object.getDataAtAsObject(index);
-    }
-
-    @Specialization(guards = "!hasNames(object)")
-    protected Object accessFieldNoNames(@SuppressWarnings("unused") RDataFrame object) {
-        return RNull.instance;
     }
 
     @Specialization
@@ -93,25 +83,15 @@ public abstract class AccessFieldNode extends RNode {
         throw RError.error(RError.Message.DOLLAR_ATOMIC_VECTORS);
     }
 
-    @Specialization(guards = "hasNames(object)")
+    @Specialization
     protected Object accessFieldHasNames(RLanguage object) {
-        String field = getField();
         RStringVector names = object.getNames(attrProfiles);
-        for (int i = 0; i < names.getLength(); i++) {
-            if (field.equals(names.getDataAt(i))) {
-                return RContext.getRASTHelper().getDataAtAsObject(object, i);
-            }
+        if (hasNamesProfile.profile(names != null)) {
+            int index = getElementIndexByName(names, getField());
+            return index == -1 ? RNull.instance : RContext.getRASTHelper().getDataAtAsObject(object, index);
+        } else {
+            return RNull.instance;
         }
-        return RNull.instance;
-    }
-
-    @Specialization(guards = "!hasNames(object)")
-    protected Object accessField(@SuppressWarnings("unused") RLanguage object) {
-        return RNull.instance;
-    }
-
-    protected boolean hasNames(RAbstractContainer object) {
-        return object.getNames(attrProfiles) != null;
     }
 
     @Override
@@ -136,5 +116,4 @@ public abstract class AccessFieldNode extends RNode {
         }
         return AccessFieldNodeGen.create(object, field);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/CoerceBinaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/CoerceBinaryNode.java
index 30fccdcd20ff56d9aa3ca32375b86dfd567ca11e..09750775097287cb8de9dd3fd7e60bb736e7055d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/CoerceBinaryNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/CoerceBinaryNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +36,7 @@ import com.oracle.truffle.r.runtime.data.closures.*;
 import com.oracle.truffle.r.runtime.data.model.*;
 import com.oracle.truffle.r.runtime.ops.na.*;
 
-@SuppressWarnings({"unused", "static-method"})
+@SuppressWarnings({"unused"})
 @NodeChildren({@NodeChild("left"), @NodeChild("right")})
 public abstract class CoerceBinaryNode extends RNode {
 
@@ -45,7 +45,7 @@ public abstract class CoerceBinaryNode extends RNode {
 
     @Child private CoercedBinaryOperationNode updateNode = null;
 
-    public CoerceBinaryNode(CoercedBinaryOperationNode operationNode) {
+    protected CoerceBinaryNode(CoercedBinaryOperationNode operationNode) {
         this.updateNode = operationNode;
         leftNACheck = new NACheck();
         rightNACheck = new NACheck();
@@ -58,12 +58,12 @@ public abstract class CoerceBinaryNode extends RNode {
     }
 
     @CreateCast({"left"})
-    public RNode createCastLeft(RNode child) {
+    protected RNode createCastLeft(RNode child) {
         return VectorUpdateVectorCastNodeGen.create(child, leftNACheck);
     }
 
     @CreateCast({"right"})
-    public RNode createCastRight(RNode child) {
+    protected RNode createCastRight(RNode child) {
         return VectorUpdateValueCastNodeGen.create(child, leftNACheck);
     }
 
@@ -79,8 +79,8 @@ public abstract class CoerceBinaryNode extends RNode {
         }
     }
 
-    private RuntimeException illegal() {
-        return new IllegalStateException();
+    private static RuntimeException illegal() {
+        throw RInternalError.shouldNotReachHere();
     }
 
     private RIntVector doInt(VirtualFrame frame, RIntVector vector, int right) {
@@ -543,7 +543,7 @@ public abstract class CoerceBinaryNode extends RNode {
 
         @Specialization
         protected int doInt(int operand) {
-            getNACheck().enable(RRuntime.isNA(operand));
+            getNACheck().enable(operand);
             return operand;
         }
 
@@ -579,37 +579,37 @@ public abstract class CoerceBinaryNode extends RNode {
 
         @Specialization
         protected RIntVector doIntVector(RIntVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return operand;
         }
 
         @Specialization
         protected RDoubleVector doDoubleVector(RDoubleVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return operand;
         }
 
         @Specialization
         protected RComplexVector doComplexVector(RComplexVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return operand;
         }
 
         @Specialization
         protected RLogicalVector doLogicalVector(RLogicalVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return operand;
         }
 
         @Specialization
         protected RStringVector doStringVector(RStringVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return operand;
         }
 
         @Specialization
         protected RList doList(RList operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return operand;
         }
 
@@ -636,7 +636,7 @@ public abstract class CoerceBinaryNode extends RNode {
 
         @Specialization
         protected RIntVector doInt(int operand) {
-            getNACheck().enable(RRuntime.isNA(operand));
+            getNACheck().enable(operand);
             return RDataFactory.createIntVectorFromScalar(operand);
         }
 
@@ -678,37 +678,37 @@ public abstract class CoerceBinaryNode extends RNode {
 
         @Specialization
         protected RIntVector doIntVector(RIntVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return doVector(operand);
         }
 
         @Specialization
         protected RDoubleVector doDoubleVector(RDoubleVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return doVector(operand);
         }
 
         @Specialization
         protected RComplexVector doComplexVector(RComplexVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return doVector(operand);
         }
 
         @Specialization
         protected RLogicalVector doLogicalVector(RLogicalVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return doVector(operand);
         }
 
         @Specialization
         protected RStringVector doStringVector(RStringVector operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return doVector(operand);
         }
 
         @Specialization
         protected RList doList(RList operand) {
-            getNACheck().enable(!operand.isComplete());
+            getNACheck().enable(operand);
             return doVector(operand);
         }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
index 2f6bda5ffe5c71091b3209021fe757006802c27b..81aba72b4b970e30d3d5b28d3c650791624dfda4 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/FrameSlotNode.java
@@ -40,11 +40,7 @@ public abstract class FrameSlotNode extends Node {
 
     public abstract FrameSlot executeFrameSlot(VirtualFrame frame);
 
-    static FrameSlot findFrameSlot(Frame frame, Object identifier) {
-        return frame.getFrameDescriptor().findFrameSlot(identifier);
-    }
-
-    static Assumption getAssumption(Frame frame, Object identifier) {
+    private static Assumption getAssumption(Frame frame, Object identifier) {
         return frame.getFrameDescriptor().getNotInFrameAssumption(identifier);
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
index c53c6c6b853dd9b2ece37bd851917070e6ab1306..83bbb9da98c9e45859e34469dd6ae286aab1ed97 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/RemoveAndAnswerNode.java
@@ -49,7 +49,7 @@ public abstract class RemoveAndAnswerNode extends RNoDeparseNode {
         /**
          * The name of the variable that is to be removed and whose value is to be returned.
          */
-        protected final String name;
+        private final String name;
 
         protected RemoveAndAnswerUninitializedNode(String name) {
             this.name = name;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateFieldNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateFieldNode.java
index 3e950ba3b0f7407163e80f4e750138101f9a5f79..ef2b4169058f3ac3f32404106d56aa0c8dbc8615 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateFieldNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateFieldNode.java
@@ -37,32 +37,28 @@ import com.oracle.truffle.r.runtime.data.model.*;
 import com.oracle.truffle.r.runtime.env.*;
 import com.oracle.truffle.r.runtime.env.REnvironment.*;
 
-@NodeChildren({@NodeChild(value = "object", type = RNode.class), @NodeChild(value = "value", type = RNode.class)})
-@NodeField(name = "field", type = String.class)
-public abstract class UpdateFieldNode extends RNode {
-
-    public abstract RNode getObject();
+@NodeChild(value = "value", type = RNode.class)
+public abstract class UpdateFieldNode extends AccessFieldBaseNode {
 
     public abstract RNode getValue();
 
-    public abstract String getField();
-
-    private final BranchProfile inexactMatch = BranchProfile.create();
     private final BranchProfile noRemoval = BranchProfile.create();
     private final ConditionProfile nullValueProfile = ConditionProfile.createBinaryProfile();
-    private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
 
     @Child private CastListNode castList;
 
     @Specialization(guards = "!isNull(value)")
     protected Object updateField(RList object, Object value) {
+        RStringVector names = object.getNames(attrProfiles);
+        int index = -1;
         String field = getField();
-        int index = object.getElementIndexByName(attrProfiles, field);
-        if (index == -1) {
-            inexactMatch.enter();
-            index = object.getElementIndexByNameInexact(attrProfiles, field);
+        if (hasNamesProfile.profile(names != null)) {
+            index = getElementIndexByName(names, field);
+            if (index == -1) {
+                inexactMatch.enter();
+                index = object.getElementIndexByNameInexact(attrProfiles, field);
+            }
         }
-
         int newLength = object.getLength() + (index == -1 ? 1 : 0);
         if (index == -1) {
             index = newLength - 1;
@@ -76,7 +72,6 @@ public abstract class UpdateFieldNode extends RNode {
         if (object.getNames(attrProfiles) == null) {
             Arrays.fill(resultNames, "");
         } else {
-            RStringVector names = object.getNames(attrProfiles);
             System.arraycopy(names.getDataWithoutCopying(), 0, resultNames, 0, names.getLength());
             namesComplete = names.isComplete();
         }
@@ -93,11 +88,15 @@ public abstract class UpdateFieldNode extends RNode {
 
     @Specialization(guards = "isNull(value)")
     protected Object updateFieldNullValue(RList object, @SuppressWarnings("unused") Object value) {
+        RStringVector names = object.getNames(attrProfiles);
+        int index = -1;
         String field = getField();
-        int index = object.getElementIndexByName(attrProfiles, field);
-        if (index == -1) {
-            inexactMatch.enter();
-            index = object.getElementIndexByNameInexact(attrProfiles, field);
+        if (hasNamesProfile.profile(names != null)) {
+            index = getElementIndexByName(names, field);
+            if (index == -1) {
+                inexactMatch.enter();
+                index = object.getElementIndexByNameInexact(attrProfiles, field);
+            }
         }
 
         if (index == -1) {
@@ -120,7 +119,6 @@ public abstract class UpdateFieldNode extends RNode {
         if (object.getNames(attrProfiles) == null) {
             Arrays.fill(resultNames, "");
         } else {
-            RStringVector names = object.getNames(attrProfiles);
             ind = 0;
             for (int i = 0; i < names.getLength(); i++) {
                 if (i != index) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/ArrayPositionCast.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/ArrayPositionCast.java
index 599453b574709093d13710c82f38b66850471d40..be52d7abb3757659d41c072f0dc2dcc878b751bf 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/ArrayPositionCast.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/ArrayPositionCast.java
@@ -53,6 +53,8 @@ abstract class ArrayPositionsCastBase extends RNode {
         this.isSubset = isSubset;
     }
 
+    private final BranchProfile errorProfile = BranchProfile.create();
+
     private final ConditionProfile nameConditionProfile = ConditionProfile.createBinaryProfile();
     private final BranchProfile naValueMet = BranchProfile.create();
     private final BranchProfile intVectorMet = BranchProfile.create();
@@ -87,7 +89,8 @@ abstract class ArrayPositionsCastBase extends RNode {
         return rowNames.getLength();
     }
 
-    protected void dimensionsError() {
+    private void dimensionsError() {
+        errorProfile.enter();
         if (assignment) {
             if (isSubset) {
                 if (numDimensions == 2) {
@@ -199,14 +202,6 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
         }
     }
 
-    protected static boolean sizeOneOp(RAbstractContainer container, RAbstractIntVector operand) {
-        return operand.getLength() == 1;
-    }
-
-    protected boolean operandHasNames(RAbstractContainer container, RAbstractIntVector operand) {
-        return operand.getNames(attrProfiles) != null;
-    }
-
     protected boolean numDimensionsOne() {
         return numDimensions == 1;
     }
@@ -215,10 +210,6 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
         return assignment;
     }
 
-    protected boolean emptyOperand(RAbstractContainer container, RAbstractIntVector operand) {
-        return operand.getLength() == 0;
-    }
-
     @NodeChildren({@NodeChild(value = "vector", type = RNode.class), @NodeChild(value = "operand", type = RNode.class), @NodeChild(value = "exact", type = RNode.class)})
     public abstract static class OperatorConverterNode extends ArrayPositionsCastBase {
 
@@ -228,7 +219,7 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
         @Child private CastIntegerNode castInteger;
         @Child private CastLogicalNode castLogical;
         @Child private CastToVectorNode castVector;
-        @Child ContainerDimNamesGet dimNamesGetter;
+        @Child private ContainerDimNamesGet dimNamesGetter;
 
         private final NACheck naCheck = NACheck.create();
 
@@ -340,7 +331,7 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
             return operand;
         }
 
-        protected Object expandMissing(RAbstractContainer container) {
+        private Object expandMissing(RAbstractContainer container) {
             int[] dimensions = getDimensions(container);
             verifyDimensions(dimensions);
             int[] data = new int[numDimensions == 1 ? container.getLength() : dimensions[dimension]];
@@ -480,7 +471,7 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
                     if (dimSizeOneProfile.profile(dimSize == 1)) {
                         /*
                          * e.g. c(7)[-2] vs c(7)[[-2]]
-                         * 
+                         *
                          * only one element to be picked or ultimately an error caused by operand
                          */
                         return isSubset ? 1 : operand;
@@ -504,7 +495,7 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
             }
         }
 
-        protected Object doIntNegativeMultiDim(VirtualFrame frame, RAbstractContainer container, int operand) {
+        private Object doIntNegativeMultiDim(VirtualFrame frame, RAbstractContainer container, int operand) {
             if (elementsCountProfile.profile(isSubset || container.getLength() <= 2)) {
                 // it's negative, but not out of bounds - pick all indexes apart from the negative
                 // one
@@ -814,7 +805,7 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
             return data;
         }
 
-        protected RIntVector doLogicalVectorInternal(VirtualFrame frame, RAbstractContainer container, RAbstractLogicalVector operand) {
+        private RIntVector doLogicalVectorInternal(VirtualFrame frame, RAbstractContainer container, RAbstractLogicalVector operand) {
             int dimLength = numDimensions == 1 ? container.getLength() : getDimensions(container)[dimension];
             int resultLength = Math.max(operand.getLength(), dimLength);
             int logicalVectorLength = operand.getLength();
@@ -1195,7 +1186,7 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
     @NodeChild(value = "op")
     protected abstract static class ContainerDimNamesGet extends RNode {
 
-        @Child ContainerRowNamesGet rowNamesGetter;
+        @Child private ContainerRowNamesGet rowNamesGetter;
         @Child private CastStringNode castString;
 
         protected final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
@@ -1231,7 +1222,5 @@ public abstract class ArrayPositionCast extends ArrayPositionsCastBase {
         protected boolean isDataFrame(RAbstractContainer container) {
             return container.getElementClass() == RDataFrame.class;
         }
-
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/PositionsArrayConversionNodeAdapter.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/PositionsArrayConversionNodeAdapter.java
index 7bb039e20866888c86da5cdadf488614a68f5c78..325b8045549f7e9816b4e6937f18e0ae3662ae53 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/PositionsArrayConversionNodeAdapter.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/PositionsArrayConversionNodeAdapter.java
@@ -33,8 +33,8 @@ public abstract class PositionsArrayConversionNodeAdapter extends RNode {
     @Children protected final ArrayPositionCast[] positionCasts;
     @Children protected final OperatorConverterNode[] operatorConverters;
 
-    protected final boolean isSubset;
-    protected final int length;
+    private final boolean isSubset;
+    private final int length;
 
     public Object executeArg(VirtualFrame frame, Object container, Object operand, int i) {
         return positionCasts[i].executeArg(frame, container, operand);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java
index b18e7c70d56f96df7232750fc39408148961d390..2327237e17274b7cdcd9dda39d8e375fbead3803 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/AccessArrayNode.java
@@ -228,7 +228,8 @@ public abstract class AccessArrayNode extends RNode {
     protected static RStringVector getNamesVector(Object srcNamesObject, RIntVector p, int resLength, NACheck namesNACheck) {
         RStringVector srcNames = (RStringVector) srcNamesObject;
         String[] namesData = new String[resLength];
-        namesNACheck.enable(!srcNames.isComplete() || !p.isComplete());
+        namesNACheck.enable(srcNames);
+        namesNACheck.enable(p);
         for (int i = 0; i < p.getLength(); i++) {
             int position = p.getDataAt(i);
             if (namesNACheck.check(position)) {
@@ -241,9 +242,9 @@ public abstract class AccessArrayNode extends RNode {
         return RDataFactory.createStringVector(namesData, namesNACheck.neverSeenNA());
     }
 
-    private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get(new String[]{"", ""});
-    private static final ArgumentsSignature DROP_SIGNATURE = ArgumentsSignature.get(new String[]{"", "", "drop"});
-    private static final ArgumentsSignature EXACT_SIGNATURE = ArgumentsSignature.get(new String[]{"", "", "exact"});
+    private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("", "");
+    private static final ArgumentsSignature DROP_SIGNATURE = ArgumentsSignature.get("", "", "drop");
+    private static final ArgumentsSignature EXACT_SIGNATURE = ArgumentsSignature.get("", "", "exact");
 
     @Specialization(guards = {"isObject(container)", "isSubset()"})
     protected Object accessObjectSubset(VirtualFrame frame, RAbstractContainer container, Object exact, int recLevel, Object position, Object dropDim) {
@@ -531,7 +532,8 @@ public abstract class AccessArrayNode extends RNode {
     protected Object[] accessSubsetInternal(RList vector, RIntVector p) {
         int resLength = p.getLength();
         Object[] data = new Object[resLength];
-        elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+        elementNACheck.enable(vector);
+        elementNACheck.enable(p);
         for (int i = 0; i < resLength; i++) {
             int position = p.getDataAt(i);
             if (elementNACheck.check(position)) {
@@ -783,7 +785,8 @@ public abstract class AccessArrayNode extends RNode {
             int accSrcDimensions = vector.getLength() / srcDimSize;
             int accDstDimensions = resLength / p.getLength();
 
-            elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+            elementNACheck.enable(vector);
+            elementNACheck.enable(p);
             for (int i = 0; i < p.getLength(); i++) {
                 int dstArrayBase = accDstDimensions * i;
                 int pos = p.getDataAt(i);
@@ -846,19 +849,16 @@ public abstract class AccessArrayNode extends RNode {
     protected int[] accessInternal(RAbstractIntVector vector, RIntVector p) {
         int resLength = p.getLength();
         int[] data = new int[resLength];
-        elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+        elementNACheck.enable(vector);
+        elementNACheck.enable(p);
         for (int i = 0; i < resLength; i++) {
             int position = p.getDataAt(i);
             if (elementNACheck.check(position)) {
                 data[i] = RRuntime.INT_NA;
             } else {
-                try {
-                    data[i] = vector.getDataAt(position - 1);
-                } catch (ArrayIndexOutOfBoundsException x) {
-                    x.printStackTrace();
-
-                }
-                elementNACheck.check(data[i]);
+                int value = vector.getDataAt(position - 1);
+                data[i] = value;
+                elementNACheck.check(value);
             }
         }
         return data;
@@ -942,7 +942,8 @@ public abstract class AccessArrayNode extends RNode {
             int accSrcDimensions = vector.getLength() / srcDimSize;
             int accDstDimensions = resLength / p.getLength();
 
-            elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+            elementNACheck.enable(vector);
+            elementNACheck.enable(p);
             for (int i = 0; i < p.getLength(); i++) {
                 int dstArrayBase = accDstDimensions * i;
                 int pos = p.getDataAt(i);
@@ -1002,17 +1003,58 @@ public abstract class AccessArrayNode extends RNode {
         return RDataFactory.createDoubleVector(data, elementNACheck.neverSeenNA(), res.dimensions);
     }
 
+    protected double[] accessInternal(RDoubleVector vector, RIntVector p) {
+        /*
+         * this method (along with the associated specializations) is just a temporary workaround to
+         * avoid the getDataAt call in the inner loop - this will ultimately need a different
+         * solution.
+         */
+        int resLength = p.getLength();
+        double[] data = new double[resLength];
+        double[] vectorData = vector.getDataWithoutCopying();
+        elementNACheck.enable(vector);
+        elementNACheck.enable(p);
+        for (int i = 0; i < resLength; i++) {
+            int position = p.getDataAt(i);
+            if (elementNACheck.check(position)) {
+                data[i] = RRuntime.DOUBLE_NA;
+            } else {
+                double value = vectorData[position - 1];
+                data[i] = value;
+                elementNACheck.check(value);
+            }
+        }
+        return data;
+    }
+
+    @SuppressWarnings("unused")
+    @Specialization(guards = {"!isObject(vector)", "hasNames(vector)"})
+    protected RDoubleVector accessNames(RDoubleVector vector, Object exact, int recLevel, RIntVector p, Object dropDim) {
+        double[] data = accessInternal(vector, p);
+        RStringVector names = getNamesVector(vector.getNames(attrProfiles), p, p.getLength(), namesNACheck);
+        return RDataFactory.createDoubleVector(data, elementNACheck.neverSeenNA(), names);
+    }
+
+    @SuppressWarnings("unused")
+    @Specialization(guards = {"!isObject(vector)", "!hasNames(vector)"})
+    protected RDoubleVector access(RDoubleVector vector, Object exact, int recLevel, RIntVector p, Object dropDim) {
+        double[] data = accessInternal(vector, p);
+        return RDataFactory.createDoubleVector(data, elementNACheck.neverSeenNA());
+    }
+
     protected double[] accessInternal(RAbstractDoubleVector vector, RIntVector p) {
         int resLength = p.getLength();
         double[] data = new double[resLength];
-        elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+        elementNACheck.enable(vector);
+        elementNACheck.enable(p);
         for (int i = 0; i < resLength; i++) {
             int position = p.getDataAt(i);
             if (elementNACheck.check(position)) {
                 data[i] = RRuntime.DOUBLE_NA;
             } else {
-                data[i] = vector.getDataAt(position - 1);
-                elementNACheck.check(data[i]);
+                double value = vector.getDataAt(position - 1);
+                data[i] = value;
+                elementNACheck.check(value);
             }
         }
         return data;
@@ -1096,7 +1138,8 @@ public abstract class AccessArrayNode extends RNode {
             int accSrcDimensions = vector.getLength() / srcDimSize;
             int accDstDimensions = resLength / p.getLength();
 
-            elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+            elementNACheck.enable(vector);
+            elementNACheck.enable(p);
             for (int i = 0; i < p.getLength(); i++) {
                 int dstArrayBase = accDstDimensions * i;
                 int pos = p.getDataAt(i);
@@ -1159,14 +1202,16 @@ public abstract class AccessArrayNode extends RNode {
     protected byte[] accessInternal(RLogicalVector vector, RIntVector p) {
         int resLength = p.getLength();
         byte[] data = new byte[resLength];
-        elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+        elementNACheck.enable(vector);
+        elementNACheck.enable(p);
         for (int i = 0; i < resLength; i++) {
             int position = p.getDataAt(i);
             if (elementNACheck.check(position)) {
                 data[i] = RRuntime.LOGICAL_NA;
             } else {
-                data[i] = vector.getDataAt(position - 1);
-                elementNACheck.check(data[i]);
+                byte value = vector.getDataAt(position - 1);
+                data[i] = value;
+                elementNACheck.check(value);
             }
         }
         return data;
@@ -1250,7 +1295,8 @@ public abstract class AccessArrayNode extends RNode {
             int accSrcDimensions = vector.getLength() / srcDimSize;
             int accDstDimensions = resLength / p.getLength();
 
-            elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+            elementNACheck.enable(vector);
+            elementNACheck.enable(p);
             for (int i = 0; i < p.getLength(); i++) {
                 int dstArrayBase = accDstDimensions * i;
                 int pos = p.getDataAt(i);
@@ -1313,14 +1359,16 @@ public abstract class AccessArrayNode extends RNode {
     protected String[] accessInternal(RStringVector vector, RIntVector p) {
         int resLength = p.getLength();
         String[] data = new String[resLength];
-        elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+        elementNACheck.enable(vector);
+        elementNACheck.enable(p);
         for (int i = 0; i < resLength; i++) {
             int position = p.getDataAt(i);
             if (elementNACheck.check(position)) {
                 data[i] = RRuntime.STRING_NA;
             } else {
-                data[i] = vector.getDataAt(position - 1);
-                elementNACheck.check(data[i]);
+                String value = vector.getDataAt(position - 1);
+                data[i] = value;
+                elementNACheck.check(value);
             }
         }
         return data;
@@ -1404,7 +1452,8 @@ public abstract class AccessArrayNode extends RNode {
             int accSrcDimensions = vector.getLength() / srcDimSize;
             int accDstDimensions = resLength / p.getLength();
 
-            elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+            elementNACheck.enable(vector);
+            elementNACheck.enable(p);
             for (int i = 0; i < p.getLength(); i++) {
                 int dstArrayBase = accDstDimensions * i;
                 int pos = p.getDataAt(i);
@@ -1467,7 +1516,8 @@ public abstract class AccessArrayNode extends RNode {
     protected double[] accessInternal(RComplexVector vector, RIntVector p) {
         int resLength = p.getLength();
         double[] data = new double[resLength << 1];
-        elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+        elementNACheck.enable(vector);
+        elementNACheck.enable(p);
         int ind = 0;
         for (int i = 0; i < resLength; i++) {
             int position = p.getDataAt(i);
@@ -1627,14 +1677,14 @@ public abstract class AccessArrayNode extends RNode {
     protected byte[] accessInternal(RRawVector vector, RIntVector p) {
         int resLength = p.getLength();
         byte[] data = new byte[resLength];
-        elementNACheck.enable(!vector.isComplete() || !p.isComplete());
+        byte[] vectorData = vector.getDataWithoutCopying();
+        elementNACheck.enable(p);
         for (int i = 0; i < resLength; i++) {
             int position = p.getDataAt(i);
             if (elementNACheck.check(position)) {
                 data[i] = 0;
             } else {
-                data[i] = vector.getDataAt(position - 1).getValue();
-                elementNACheck.check(data[i]);
+                data[i] = vectorData[position - 1];
             }
         }
         return data;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/GetDimNamesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/GetDimNamesNode.java
index 141b19c1f8571070edf22e3711e1bc92bcdb12e0..fe939f776ce6fa7159b74ecb49db7121e5872339 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/GetDimNamesNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/GetDimNamesNode.java
@@ -77,7 +77,8 @@ abstract class GetDimNamesNode extends RNode {
             if (srcNamesNullProfile.profile(srcNames == null)) {
                 dstDimNames.updateDataAt(currentDstDimLevel - 1, RNull.instance, null);
             } else {
-                namesNACheck.enable(!srcNames.isComplete() || !p.isComplete());
+                namesNACheck.enable(srcNames);
+                namesNACheck.enable(p);
                 String[] namesData = new String[numPositions];
                 for (int i = 0; i < p.getLength(); i++) {
                     int pos = p.getDataAt(i);
@@ -107,7 +108,8 @@ abstract class GetDimNamesNode extends RNode {
                     if (srcNamesNullProfile.profile(srcNames == null)) {
                         dstDimNames.updateDataAt(currentDstDimLevel - 1, RNull.instance, null);
                     } else {
-                        namesNACheck.enable(!srcNames.isComplete() || !p.isComplete());
+                        namesNACheck.enable(srcNames);
+                        namesNACheck.enable(p);
                         String name;
                         int pos = p.getDataAt(0);
                         if (namesNACheck.check(pos)) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/PositionsArrayNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/PositionsArrayNode.java
index 654172afed95502e642e942a453976c006e6312d..21722f10d3b2c189b87b1aa0ea9ea6b1baf2a030 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/PositionsArrayNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/read/PositionsArrayNode.java
@@ -35,8 +35,8 @@ import com.oracle.truffle.r.runtime.env.*;
 
 public class PositionsArrayNode extends RNode {
 
-    @Child PositionsArrayConversionNodeMultiDimAdapter conversionAdapter;
-    @Child PositionsArrayNodeAdapter positionsAdapter;
+    @Child private PositionsArrayConversionNodeMultiDimAdapter conversionAdapter;
+    @Child private PositionsArrayNodeAdapter positionsAdapter;
     @Child private PromiseHelperNode promiseHelper;
 
     private final boolean hasVarArg;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/PositionsArrayNodeValue.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/PositionsArrayNodeValue.java
index 7634ee3fc9539e30f87fa39ec85007c73464304a..d3e97cc600ee67f2f056c18945287739cd784c06 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/PositionsArrayNodeValue.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/PositionsArrayNodeValue.java
@@ -34,8 +34,8 @@ import com.oracle.truffle.r.runtime.RDeparse.*;
 
 public class PositionsArrayNodeValue extends RNode {
 
-    @Child PositionsArrayConversionValueNodeMultiDimAdapter conversionAdapter;
-    @Child PositionsArrayNodeAdapter positionsAdapter;
+    @Child private PositionsArrayConversionValueNodeMultiDimAdapter conversionAdapter;
+    @Child private PositionsArrayNodeAdapter positionsAdapter;
     @Child private PromiseHelperNode promiseHelper;
     private final boolean hasVarArg;
 
@@ -62,14 +62,14 @@ public class PositionsArrayNodeValue extends RNode {
     }
 
     @ExplodeLoop
-    public Object executeEvalNoVarArg(VirtualFrame frame, Object vector, Object value) {
+    private Object executeEvalNoVarArg(VirtualFrame frame, Object vector, Object value) {
         int length = conversionAdapter.getLength();
         Object[] evaluatedElements = PositionsArrayNode.explodeLoopNoVarArg(frame, positionsAdapter, length);
         executeEvalInternal(frame, vector, value, evaluatedElements, length);
         return conversionAdapter.getLength() == 1 ? evaluatedElements[0] : evaluatedElements;
     }
 
-    public Object executeEvalVarArg(VirtualFrame frame, Object vector, Object value) {
+    private Object executeEvalVarArg(VirtualFrame frame, Object vector, Object value) {
         int length = conversionAdapter.getLength();
         Object[] evaluatedElements = PositionsArrayNode.explodeLoopVarArg(frame, positionsAdapter, length, promiseHelper);
         if (evaluatedElements.length != conversionAdapter.getLength()) {
@@ -82,7 +82,7 @@ public class PositionsArrayNodeValue extends RNode {
     }
 
     @ExplodeLoop
-    public void executeEvalInternal(VirtualFrame frame, Object vector, Object value, Object[] evaluatedElements, int length) {
+    private void executeEvalInternal(VirtualFrame frame, Object vector, Object value, Object[] evaluatedElements, int length) {
         for (int i = 0; i < length; i++) {
             Object convertedOperator = conversionAdapter.executeConvert(frame, vector, evaluatedElements[i], RRuntime.LOGICAL_TRUE, i);
             evaluatedElements[i] = conversionAdapter.executeArg(frame, vector, convertedOperator, i);
@@ -96,5 +96,4 @@ public class PositionsArrayNodeValue extends RNode {
     public void deparse(State state) {
         positionsAdapter.deparse(state);
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java
index 1bd16fe4ac7f24896bcf2ae99230eea8ff1fa00f..564db41f365d05422087ce10c4e47391329fe455 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java
@@ -53,7 +53,7 @@ import com.oracle.truffle.r.runtime.ops.na.*;
 public abstract class UpdateArrayHelperNode extends RNode {
 
     protected final boolean isSubset;
-    public final boolean forObjects;
+    private final boolean forObjects;
 
     private final NACheck elementNACheck = NACheck.create();
     private final NACheck posNACheck = NACheck.create();
@@ -97,13 +97,13 @@ public abstract class UpdateArrayHelperNode extends RNode {
 
     private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
 
-    public UpdateArrayHelperNode(boolean isSubset, boolean forObjects) {
+    protected UpdateArrayHelperNode(boolean isSubset, boolean forObjects) {
         this.isSubset = isSubset;
         this.forObjects = forObjects;
         this.recursiveIsSubset = isSubset;
     }
 
-    public UpdateArrayHelperNode(UpdateArrayHelperNode other) {
+    protected UpdateArrayHelperNode(UpdateArrayHelperNode other) {
         this.isSubset = other.isSubset;
         this.forObjects = other.forObjects;
         this.recursiveIsSubset = other.recursiveIsSubset;
@@ -246,7 +246,7 @@ public abstract class UpdateArrayHelperNode extends RNode {
         return CastToContainerNodeGen.create(child, false, false, false);
     }
 
-    private static final ArgumentsSignature VALUE_SIGNATURE = ArgumentsSignature.get(new String[]{"", "", "value"});
+    private static final ArgumentsSignature VALUE_SIGNATURE = ArgumentsSignature.get("", "", "value");
 
     @Specialization(guards = {"isObject(container)", "isSubset"})
     protected Object updateObjectSubset(VirtualFrame frame, Object v, Object value, int recLevel, Object positions, RAbstractContainer container) {
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 d405af097f468df0bc6c7508f4815b85afd67055..0c0c72d1e515a4135d12d10f2c6ebea170b92c68 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
@@ -33,6 +33,7 @@ import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.function.*;
+import com.oracle.truffle.r.options.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.RDeparse.State;
 import com.oracle.truffle.r.runtime.data.*;
@@ -118,7 +119,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
 
     @CompilationFinal private final boolean[] seenValueKinds = new boolean[FrameSlotKind.values().length];
 
-    public ReadVariableNode(String identifier, RType mode, ReadKind kind) {
+    private ReadVariableNode(String identifier, RType mode, ReadKind kind) {
         this.identifier = identifier;
         this.mode = mode;
         this.kind = kind;
@@ -142,7 +143,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
         return kind;
     }
 
-    public boolean seenValueKind(FrameSlotKind slotKind) {
+    private boolean seenValueKind(FrameSlotKind slotKind) {
         return seenValueKinds[slotKind.ordinal()];
     }
 
@@ -201,7 +202,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
         return result;
     }
 
-    public static final class LayoutChangedException extends SlowPathException {
+    private static final class LayoutChangedException extends SlowPathException {
         private static final long serialVersionUID = 3380913774357492013L;
     }
 
@@ -238,6 +239,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
                 return null;
             }
             if (checkType(frame, value)) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
                 throw new LayoutChangedException();
             }
             return next.execute(frame, variableFrame);
@@ -295,7 +297,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
         }
     }
 
-    public final class Unknown extends DescriptorLevel {
+    private final class Unknown extends DescriptorLevel {
 
         @Override
         public Object execute(VirtualFrame frame) {
@@ -312,7 +314,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
         }
     }
 
-    public static final class NextFrameFromDescriptorLevel extends DescriptorLevel {
+    private static final class NextFrameFromDescriptorLevel extends DescriptorLevel {
 
         private final FrameLevel next;
         private final StableValue<MaterializedFrame> enclosingFrameAssumption;
@@ -334,7 +336,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
         }
     }
 
-    public static final class NextFrameLevel extends FrameLevel {
+    private static final class NextFrameLevel extends FrameLevel {
 
         private final FrameLevel next;
         private final FrameDescriptor nextDescriptor;
@@ -371,7 +373,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
         }
     }
 
-    public static final class MultiAssumptionLevel extends FrameLevel {
+    private static final class MultiAssumptionLevel extends FrameLevel {
 
         private final FrameLevel next;
         @CompilationFinal private final Assumption[] assumptions;
@@ -448,8 +450,8 @@ public class ReadVariableNode extends RNode implements VisibilityController {
             // figure out how to get to the next frame or descriptor
             MaterializedFrame next = RArguments.getEnclosingFrame(current);
             FrameDescriptor nextDescriptor = next == null ? null : next.getFrameDescriptor();
-            StableValue<MaterializedFrame> enclosingFrameAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameAssumption(currentDescriptor, null, next);
-            StableValue<FrameDescriptor> enclosingDescriptorAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameDescriptorAssumption(currentDescriptor, null, nextDescriptor);
+            StableValue<MaterializedFrame> enclosingFrameAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameAssumption(current, currentDescriptor, null, next);
+            StableValue<FrameDescriptor> enclosingDescriptorAssumption = FrameSlotChangeMonitor.getOrInitializeEnclosingFrameDescriptorAssumption(current, currentDescriptor, null, nextDescriptor);
 
             levels.add(new ReadVariableLevel(currentDescriptor, frameSlot, valueAssumption, enclosingDescriptorAssumption, enclosingFrameAssumption, next));
 
@@ -459,12 +461,14 @@ public class ReadVariableNode extends RNode implements VisibilityController {
 
         FrameLevel lastLevel = null;
 
+        boolean complex = false;
         ListIterator<ReadVariableLevel> iter = levels.listIterator(levels.size());
         if (match) {
             ReadVariableLevel level = levels.get(levels.size() - 1);
             if (level.valueAssumption != null) {
                 lastLevel = new DescriptorStableMatch(level.valueAssumption);
             } else {
+                complex = true;
                 lastLevel = new Match(level.slot);
             }
             iter.previous();
@@ -479,12 +483,14 @@ public class ReadVariableNode extends RNode implements VisibilityController {
                 if (level.enclosingDescriptorAssumption != null) {
                     assumptions.add(level.enclosingDescriptorAssumption.getAssumption());
                 } else {
+                    complex = true;
                     lastLevel = new NextFrameLevel(lastLevel, level.nextDescriptor());
                 }
             } else {
                 if (level.enclosingFrameAssumption != null) {
                     lastLevel = new NextFrameFromDescriptorLevel(lastLevel, level.enclosingFrameAssumption);
                 } else {
+                    complex = true;
                     lastLevel = new NextFrameLevel(lastLevel, level.nextDescriptor());
                 }
             }
@@ -499,6 +505,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
                 if (level.valueAssumption != null && lastLevel instanceof DescriptorLevel) {
                     assumptions.add(level.valueAssumption.getAssumption());
                 } else {
+                    complex = true;
                     lastLevel = new Mismatch(lastLevel, level.slot);
                 }
             }
@@ -507,6 +514,10 @@ public class ReadVariableNode extends RNode implements VisibilityController {
             lastLevel = new MultiAssumptionLevel(lastLevel, assumptions.toArray(new Assumption[assumptions.size()]));
         }
 
+        if (FastROptions.PrintComplexLookups.getValue() && levels.size() > 1 && complex) {
+            System.out.println(identifier + " " + lastLevel);
+        }
+
         return lastLevel;
     }
 
@@ -590,7 +601,7 @@ public class ReadVariableNode extends RNode implements VisibilityController {
      * @param objArg The object to check for proper type
      * @return see above
      */
-    public boolean checkType(VirtualFrame frame, Object objArg) {
+    protected boolean checkType(VirtualFrame frame, Object objArg) {
         Object obj = objArg;
         if (isNullProfile.profile(obj == null)) {
             return false;
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 4d9ae16648c611df121e3357c394536529ca4cdd..35f78423e0994637ed67f07a4d52396dbc29abde 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
@@ -794,6 +794,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
             return emptyConstructor.get();
         }
         int length = Math.max(leftLength, rightLength);
+        reportWork(length);
         leftNACheck.enable(left);
         rightNACheck.enable(right);
         resultNACheck.enable(arithmetic.introducesNA());
@@ -849,6 +850,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
         if (emptyVector.profile(length == 0)) {
             return emptyConstructor.get();
         }
+        reportWork(length);
         resultNACheck.enable(arithmetic.introducesNA());
         ArrayT result = arrayConstructor.apply(length);
         for (int i = 0; i < length; ++i) {
@@ -866,6 +868,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode {
         if (emptyVector.profile(length == 0)) {
             return emptyConstructor.get();
         }
+        reportWork(length);
         resultNACheck.enable(arithmetic.introducesNA());
         ArrayT result = arrayConstructor.apply(source);
         for (int i = 0; i < length; ++i) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java
index 4e89bc2f7666cd505e4d942e6508c349ffafef9f..7f19cb614d64ad96435af9d9003897894686b11c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,9 +24,6 @@ package com.oracle.truffle.r.nodes.binary;
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.r.nodes.*;
-import com.oracle.truffle.r.runtime.*;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.data.model.*;
 
 @NodeChildren({@NodeChild(value = "left", type = RNode.class), @NodeChild(value = "right", type = RNode.class)})
 public abstract class BinaryNode extends RNode {
@@ -35,190 +32,4 @@ public abstract class BinaryNode extends RNode {
 
     protected abstract RNode getRight();
 
-    public static boolean isEmpty(RAbstractVector left, @SuppressWarnings("unused") Object right) {
-        return left.getLength() == 0;
-    }
-
-    public static boolean isEmpty(@SuppressWarnings("unused") Object left, RAbstractVector right) {
-        return right.getLength() == 0;
-    }
-
-    public static boolean isEmpty(RAbstractVector left, RAbstractVector right) {
-        return left.getLength() == 0 || right.getLength() == 0;
-    }
-
-    public static boolean notEmpty(RAbstractVector left, RAbstractVector right) {
-        return left.getLength() != 0 && right.getLength() != 0;
-    }
-
-    // int
-
-    public static boolean isNA(int left) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(int left, int right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(int left, double right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(double left, int right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(int left, byte right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(byte left, int right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(int left, String right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(String left, int right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(int left, RComplex right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(RComplex left, int right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(int left, @SuppressWarnings("unused") RRaw right) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(@SuppressWarnings("unused") RRaw left, int right) {
-        return RRuntime.isNA(right);
-    }
-
-    // double
-
-    public static boolean isNA(double left) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(double left, double right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(double left, byte right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(byte left, double right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(double left, String right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(String left, double right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(double left, RComplex right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(RComplex left, double right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(double left, @SuppressWarnings("unused") RRaw right) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(@SuppressWarnings("unused") RRaw left, double right) {
-        return RRuntime.isNA(right);
-    }
-
-    // logical
-
-    public static boolean isNA(byte left) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(byte left, byte right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(byte left, String right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(String left, byte right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(byte left, RComplex right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(RComplex left, byte right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(byte left, @SuppressWarnings("unused") RRaw right) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(@SuppressWarnings("unused") RRaw left, byte right) {
-        return RRuntime.isNA(right);
-    }
-
-    // string
-
-    public static boolean isNA(String left) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(String left, String right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(String left, RComplex right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(RComplex left, String right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(String left, @SuppressWarnings("unused") RRaw right) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(@SuppressWarnings("unused") RRaw left, String right) {
-        return RRuntime.isNA(right);
-    }
-
-    // complex
-
-    public static boolean isNA(RComplex left) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(RComplex left, RComplex right) {
-        return RRuntime.isNA(left) || RRuntime.isNA(right);
-    }
-
-    public static boolean isNA(RComplex left, @SuppressWarnings("unused") RRaw right) {
-        return RRuntime.isNA(left);
-    }
-
-    public static boolean isNA(@SuppressWarnings("unused") RRaw left, RComplex right) {
-        return RRuntime.isNA(right);
-    }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/ColonNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/ColonNode.java
index 824e290895d73fb8078567819a9d59b9ae8cf032..6d0f8ca3069a1bb7e74fdd5a642dc26db4b3f249 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/ColonNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/ColonNode.java
@@ -42,7 +42,7 @@ public abstract class ColonNode extends RNode implements VisibilityController {
     public abstract RNode getRight();
 
     @CreateCast({"left", "right"})
-    public RNode createCast(RNode child) {
+    protected RNode createCast(RNode child) {
         ColonCastNode ccn = ColonCastNodeGen.create(child);
         ccn.assignSourceSection(getSourceSection());
         return ccn;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryListNode.java
index a263b97d0abbe6e6f997791f5943e1d644896128..72d87b2b505a0419f90734543169eb620cff5c7b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryListNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryListNode.java
@@ -44,12 +44,11 @@ public abstract class CombineBinaryListNode extends CombineBinaryNode {
         return RDataFactory.createList(result, combineNames(left, right));
     }
 
-    protected RList extend(RList list, Object x) {
+    private RList extend(RList list, Object x) {
         final int ll = list.getLength();
         Object[] result = new Object[ll + 1];
         System.arraycopy(list.getDataWithoutCopying(), 0, result, 0, ll);
         result[ll] = x;
         return RDataFactory.createList(result, combineNames(list, false));
     }
-
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryNode.java
index 010e31bfbca1997d8f51906f8f41e5430d03f53b..7525bc6f591a4a2703378b5d486ce805d99a3ead 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CombineBinaryNode.java
@@ -97,7 +97,7 @@ public abstract class CombineBinaryNode extends BinaryNode {
         return RDataFactory.createStringVector(namesData, naCheck.neverSeenNA());
     }
 
-    public RVector genericCombine(RVector left, RVector right) {
+    protected RVector genericCombine(RVector left, RVector right) {
         int leftLength = left.getLength();
         int rightLength = right.getLength();
         RVector result = left.createEmptySameType(leftLength + rightLength, left.isComplete() && right.isComplete());
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
index 7d0383b2df4138608c00ff93b159a06547c2bb52..ec17d340b0820e5c3e0cb2765ee1eaeb4b7e2618 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java
@@ -153,7 +153,7 @@ public abstract class RBuiltinNode extends LeafCallNode implements VisibilityCon
         // Setup
         FrameDescriptor frameDescriptor = new FrameDescriptor();
         RBuiltinRootNode root = new RBuiltinRootNode(node, formals, frameDescriptor);
-        FrameSlotChangeMonitor.initializeFrameDescriptor(frameDescriptor, false);
+        FrameSlotChangeMonitor.initializeFunctionFrameDescriptor(frameDescriptor);
         return Truffle.getRuntime().createCallTarget(root);
     }
 
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 64897220fd3183dd4f22f465586af2586ad4deb7..c7baeca2fc26e647f0d9bb30e706e22c02555b12 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -119,7 +119,8 @@ public abstract class ForNode extends LoopNode {
     protected Object doSequence(VirtualFrame frame, RIntSequence range) {
         int count = 0;
         try {
-            for (int i = 0, pos = range.getStart(); i < range.getLength(); i++, pos += range.getStride()) {
+            // this loop is 1-based so that the loop counter folds with common 1:n sequences
+            for (int i = 1, pos = range.getStart(); i <= range.getLength(); i++, pos += range.getStride()) {
                 cvar.execute(frame, pos);
                 try {
                     body.execute(frame);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java
index cffeef08431bc36f7078d177b0950e04d207cb7f..d8a15169290899224b448cd01d4ac80a1348e452 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/IfNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +23,6 @@
 package com.oracle.truffle.r.nodes.control;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.api.utilities.*;
@@ -32,9 +31,9 @@ import com.oracle.truffle.r.nodes.unary.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.RDeparse.State;
 import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.env.*;
 
-public class IfNode extends RNode implements VisibilityController {
+public final class IfNode extends RNode implements VisibilityController {
 
     @Child private ConvertBooleanNode condition;
     @Child private RNode thenPart;
@@ -42,18 +41,14 @@ public class IfNode extends RNode implements VisibilityController {
 
     private final ConditionProfile conditionProfile = ConditionProfile.createCountingProfile();
 
-    protected IfNode(RNode condition, RNode thenPart, RNode elsePart) {
+    private IfNode(RNode condition, RNode thenPart, RNode elsePart) {
         this.condition = ConvertBooleanNode.create(condition);
         this.thenPart = thenPart;
         this.elsePart = elsePart;
     }
 
-    public static IfNode create(RNode condition, RNode thenPart, RNode elsePart) {
-        return new IfNode(condition, thenPart, elsePart);
-    }
-
     public static IfNode create(SourceSection src, RNode condition, RNode thenPart, RNode elsePart) {
-        IfNode i = create(condition, thenPart, elsePart);
+        IfNode i = new IfNode(condition, thenPart, elsePart);
         i.assignSourceSection(src);
         return i;
     }
@@ -80,11 +75,6 @@ public class IfNode extends RNode implements VisibilityController {
         return true;
     }
 
-    @CreateCast({"condition"})
-    public ConvertBooleanNode conditionToBoolean(RNode node) {
-        return ConvertBooleanNode.create(node);
-    }
-
     @Override
     public Object execute(VirtualFrame frame) {
         byte cond = condition.executeByte(frame);
@@ -146,6 +136,6 @@ public class IfNode extends RNode implements VisibilityController {
 
     @Override
     public RNode substitute(REnvironment env) {
-        return IfNode.create(condition.substitute(env), thenPart.substitute(env), elsePart.substitute(env));
+        return new IfNode(condition.substitute(env), thenPart.substitute(env), elsePart.substitute(env));
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/LoopNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/LoopNode.java
index e06297ed95b4b9b61d9ee44adbc33554b5e52e5d..9c031bc867552ddbe523cd400ea074fa870e02a0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/LoopNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/LoopNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,12 +29,8 @@ import com.oracle.truffle.r.nodes.*;
 public abstract class LoopNode extends RNode {
 
     protected final void reportLoopCount(int count) {
-        reportLoopCount(this, count);
-    }
-
-    public static void reportLoopCount(RNode loopNode, int count) {
         CompilerAsserts.neverPartOfCompilation();
-        Node current = loopNode.getParent();
+        Node current = this.getParent();
         while (current != null && !(current instanceof RootNode)) {
             current = current.getParent();
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReturnException.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReturnException.java
index c50bdeaf03e3b43301970b7af963a0bd4fa2e05a..4df7f1b518e6ecc50175fea11ebe21d5e86359e7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReturnException.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/ReturnException.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,7 +27,7 @@ import com.oracle.truffle.api.nodes.*;
 @SuppressWarnings("serial")
 public final class ReturnException extends ControlFlowException {
 
-    public final Object result;
+    private final Object result;
 
     public ReturnException(Object result) {
         this.result = result;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/SequenceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/SequenceNode.java
index d49caf8f2d75165c20712a44945e17840ddd45d4..953c63ed07f8d295b260c510fa8d6907b8f9b5a9 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/SequenceNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/control/SequenceNode.java
@@ -37,7 +37,7 @@ import com.oracle.truffle.r.runtime.env.*;
 
 public class SequenceNode extends RNode {
 
-    @Children protected final RNode[] sequence;
+    @Children private final RNode[] sequence;
 
     private final long[] timing;
 
@@ -46,7 +46,7 @@ public class SequenceNode extends RNode {
         this.timing = null;
     }
 
-    public SequenceNode(RNode[] sequence, SourceSection src) {
+    private SequenceNode(RNode[] sequence, SourceSection src) {
         this.sequence = sequence;
         this.timing = PerfHandler.initTiming(src, this);
         if (src != null) {
@@ -55,7 +55,7 @@ public class SequenceNode extends RNode {
     }
 
     public SequenceNode(SourceSection src, RNode node) {
-        this(node, src);
+        this(convert(node), src);
     }
 
     public SequenceNode(SourceSection src, RNode[] sequence) {
@@ -72,10 +72,6 @@ public class SequenceNode extends RNode {
         this(convert(node));
     }
 
-    protected SequenceNode(RNode node, SourceSection src) {
-        this(convert(node), src);
-    }
-
     public RNode[] getSequence() {
         return sequence;
     }
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 462de93d32ec3b815edefecfe273d2e5036c7da0..ecc3331b44beadb6f7110522873dbb3f036ece55 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -50,7 +50,7 @@ public final class WhileNode extends LoopNode {
         this.isRepeat = isRepeat;
     }
 
-    public static WhileNode create(RNode condition, RNode body, boolean isRepeat) {
+    private static WhileNode create(RNode condition, RNode body, boolean isRepeat) {
         return new WhileNode(condition, body, isRepeat);
     }
 
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 5f80cf690f3df5e1c1c0baed48126d1688925679..7904bb0c64e6cd8d8d48c75b14524a8c40848425 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
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.access.*;
 import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.nodes.function.PromiseNode.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 import com.oracle.truffle.r.runtime.data.RPromise.Closure;
@@ -311,6 +312,24 @@ public class ArgumentMatcher {
         }
     }
 
+    private static String getErrorForArgument(RNode[] suppliedArgs, int index) {
+        RNode node = suppliedArgs[index];
+        if (node instanceof VarArgNode) {
+            CompilerAsserts.neverPartOfCompilation();
+            VirtualFrame frame = Utils.getActualCurrentFrame();
+            try {
+                // TODO: this error handling code takes many assumptions about the argument types
+                RArgsValuesAndNames varArg = (RArgsValuesAndNames) frame.getObject(frame.getFrameDescriptor().findFrameSlot("..."));
+                RPromise promise = (RPromise) varArg.getValues()[((VarArgNode) node).getIndex()];
+                return ((Node) promise.getRep()).getSourceSection().getCode();
+            } catch (FrameSlotTypeException | ClassCastException e) {
+                throw RInternalError.shouldNotReachHere();
+            }
+        } else {
+            return node.getSourceSection().getCode();
+        }
+    }
+
     /**
      * Matches the supplied arguments to the formal ones and returns them as consolidated
      * {@code RNode[]}. Handles named args and varargs.<br/>
@@ -336,7 +355,7 @@ public class ArgumentMatcher {
 
         // Rearrange arguments
         MatchPermutation match = permuteArguments(suppliedSignature, formals, callSrc, argsSrc, false, index -> ArgumentsSignature.VARARG_NAME.equals(RMissingHelper.unwrapName(suppliedArgs[index])),
-                        index -> suppliedArgs[index].getSourceSection().getCode());
+                        index -> getErrorForArgument(suppliedArgs, index));
 
         RNode[] defaultArgs = formals.getDefaultArgs();
         RNode[] resArgs = new RNode[match.resultPermutation.length];
@@ -439,7 +458,7 @@ public class ArgumentMatcher {
      * @return An array of type <T> with the supplied arguments in the correct order
      */
     @TruffleBoundary
-    public static MatchPermutation permuteArguments(ArgumentsSignature signature, FormalArguments formals, SourceSection callSrc, SourceSection argsSrc, boolean forNextMethod,
+    private static MatchPermutation permuteArguments(ArgumentsSignature signature, FormalArguments formals, SourceSection callSrc, SourceSection argsSrc, boolean forNextMethod,
                     IntPredicate isVarSuppliedVarargs, IntFunction<String> errorString) {
         // assert Arrays.stream(suppliedNames).allMatch(name -> name == null || !name.isEmpty());
 
@@ -613,7 +632,7 @@ public class ArgumentMatcher {
      * @return A single suppliedArg and its corresponding defaultValue wrapped up into a
      *         {@link PromiseNode}
      */
-    public static EvalPolicy getEvalPolicy(RBuiltinRootNode builtinRootNode, int formalIndex) {
+    private static EvalPolicy getEvalPolicy(RBuiltinRootNode builtinRootNode, int formalIndex) {
         // This is for actual function calls. However, if the arguments are meant for a
         // builtin, we have to consider whether they should be forced or not!
         return builtinRootNode != null && builtinRootNode.evaluatesArg(formalIndex) ? EvalPolicy.INLINED : EvalPolicy.PROMISED;
@@ -633,7 +652,7 @@ public class ArgumentMatcher {
      *         {@link RMissing} in case neither is present!
      */
     @TruffleBoundary
-    public static RNode wrap(FormalArguments formals, RBuiltinRootNode builtinRootNode, ClosureCache closureCache, RNode suppliedArg, RNode defaultValue, int formalIndex, boolean isBuiltin,
+    private static RNode wrap(FormalArguments formals, RBuiltinRootNode builtinRootNode, ClosureCache closureCache, RNode suppliedArg, RNode defaultValue, int formalIndex, boolean isBuiltin,
                     boolean noOpt) {
         // Determine whether to choose supplied argument or default value
         RNode expr = null;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
index 7df5ae716d9f40d281419024a5bd0e4fc732d17a..6563d5ff14b00b1b3899d3b6261c946d615f18b8 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java
@@ -57,7 +57,12 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
      * If a supplied argument is a {@link ReadVariableNode} whose name is "...", this field contains
      * the index of the name. Otherwise it is an empty list.
      */
-    @CompilationFinal private final Integer[] varArgsSymbolIndices;
+    @CompilationFinal private final int[] varArgsSymbolIndices;
+
+    private static final int UNINITIALIZED = -1;
+    private static final int VARIABLE = -2;
+
+    @CompilationFinal private int cachedSignatureLength = UNINITIALIZED;
 
     private final IdentityHashMap<RNode, Closure> closureCache = new IdentityHashMap<>();
 
@@ -78,7 +83,7 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
      */
     private final boolean modeChangeForAll;
 
-    private CallArgumentsNode(RNode[] arguments, ArgumentsSignature signature, Integer[] varArgsSymbolIndices, boolean modeChange, boolean modeChangeForAll) {
+    private CallArgumentsNode(RNode[] arguments, ArgumentsSignature signature, int[] varArgsSymbolIndices, boolean modeChange, boolean modeChangeForAll) {
         super(arguments, signature);
         this.varArgsSymbolIndices = varArgsSymbolIndices;
         this.modeChange = modeChange;
@@ -119,7 +124,10 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
 
         // Setup and return
         SourceSection src = Utils.sourceBoundingBox(wrappedArgs);
-        Integer[] varArgsSymbolIndicesArr = varArgsSymbolIndices.toArray(new Integer[varArgsSymbolIndices.size()]);
+        int[] varArgsSymbolIndicesArr = new int[varArgsSymbolIndices.size()];
+        for (int i = 0; i < varArgsSymbolIndicesArr.length; i++) {
+            varArgsSymbolIndicesArr[i] = varArgsSymbolIndices.get(i);
+        }
         CallArgumentsNode callArgs = new CallArgumentsNode(wrappedArgs, signature, varArgsSymbolIndicesArr, modeChange, modeChangeForAll);
         callArgs.assignSourceSection(src);
         return callArgs;
@@ -147,10 +155,31 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
 
         // Unroll "..."s and insert their arguments into VarArgsSignature
         int times = varArgsSymbolIndices.length;
-        return createSignature(getVarargsAndNames(frame), times, true);
+        RArgsValuesAndNames varArgsAndNames = getVarargsAndNames(frame);
+
+        // "..." empty?
+        if (varArgsAndNames.isEmpty()) {
+            return VarArgsSignature.NO_VARARGS_GIVEN;
+        } else {
+            // Arguments wrapped into "..."
+            Object[] varArgs = varArgsAndNames.getValues();
+            Object[] content;
+            if (cachedSignatureLength != VARIABLE && cachedSignatureLength != varArgs.length) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                cachedSignatureLength = cachedSignatureLength == UNINITIALIZED ? varArgs.length : VARIABLE;
+            }
+            if (cachedSignatureLength == VARIABLE) {
+                content = new Object[varArgs.length];
+                createSignatureLoop(content, varArgs);
+            } else {
+                content = new Object[cachedSignatureLength];
+                createSignatureLoopUnrolled(content, varArgs, cachedSignatureLength);
+            }
+            return VarArgsSignature.create(content, times);
+        }
     }
 
-    private RArgsValuesAndNames getVarargsAndNames(VirtualFrame frame) {
+    public RArgsValuesAndNames getVarargsAndNames(VirtualFrame frame) {
         RArgsValuesAndNames varArgsAndNames;
         try {
             varArgsAndNames = (RArgsValuesAndNames) frame.getObject(varArgsSlotNode.executeFrameSlot(frame));
@@ -160,33 +189,46 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
         return varArgsAndNames;
     }
 
-    public static VarArgsSignature createSignature(RArgsValuesAndNames varArgsAndNames, int times, boolean allowConstants) {
-        Object[] content;
+    public static VarArgsSignature createSignature(RArgsValuesAndNames varArgsAndNames, int times) {
         // "..." empty?
         if (varArgsAndNames.isEmpty()) {
-            content = new Object[]{VarArgsSignature.NO_VARARGS};
+            return VarArgsSignature.NO_VARARGS_GIVEN;
         } else {
-
             // Arguments wrapped into "..."
             Object[] varArgs = varArgsAndNames.getValues();
-            content = new Object[varArgs.length];
-
-            // As we want to check on expression identity later on:
-            for (int i = 0; i < varArgs.length; i++) {
-                Object varArg = varArgs[i];
-                if (varArg instanceof RPromise) {
-                    // Unwrap expression (one instance per argument/call site)
-                    content[i] = ((RPromise) varArg).getRep();
-                } else if (RMissingHelper.isMissing(varArg)) {
-                    // Use static symbol for "missing" instead of ConstantNode.create
-                    content[i] = VarArgsSignature.NO_VARARGS;
-                } else {
-                    assert allowConstants;
-                    content[i] = varArg;
-                }
-            }
+            Object[] content = new Object[varArgs.length];
+
+            createSignatureLoop(content, varArgs);
+            return VarArgsSignature.create(content, times);
+        }
+    }
+
+    private static void createSignatureLoop(Object[] content, Object[] varArgs) {
+        // As we want to check on expression identity later on:
+        for (int i = 0; i < varArgs.length; i++) {
+            createSignatureLoopContents(content, varArgs, i);
+        }
+    }
+
+    @ExplodeLoop
+    private static void createSignatureLoopUnrolled(Object[] content, Object[] varArgs, int length) {
+        // As we want to check on expression identity later on:
+        for (int i = 0; i < length; i++) {
+            createSignatureLoopContents(content, varArgs, i);
+        }
+    }
+
+    private static void createSignatureLoopContents(Object[] content, Object[] varArgs, int i) {
+        Object varArg = varArgs[i];
+        if (varArg instanceof RPromise) {
+            // Unwrap expression (one instance per argument/call site)
+            content[i] = ((RPromise) varArg).getRep();
+        } else if (RMissingHelper.isMissing(varArg)) {
+            // Use static symbol for "missing" instead of ConstantNode.create
+            content[i] = VarArgsSignature.NO_VARARGS;
+        } else {
+            content[i] = varArg;
         }
-        return VarArgsSignature.create(content, times);
     }
 
     @ExplodeLoop
@@ -222,7 +264,7 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
                         // RMissing.instance. Both need to be wrapped into ConstantNodes, so
                         // they might get wrapped into new promises later on
                         Object varArgValue = varArgInfo.getValues()[j];
-                        values[index] = wrapVarArgValue(varArgValue);
+                        values[index] = wrapVarArgValue(varArgValue, j);
                         String newName = varArgInfo.getSignature().getName(j);
                         newNames[index] = newName;
                         index++;
@@ -241,9 +283,9 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
     }
 
     @TruffleBoundary
-    public static RNode wrapVarArgValue(Object varArgValue) {
+    public static RNode wrapVarArgValue(Object varArgValue, int varArgIndex) {
         if (varArgValue instanceof RPromise) {
-            return PromiseNode.createVarArg((RPromise) varArgValue);
+            return PromiseNode.createVarArg(varArgIndex);
         } else {
             return ConstantNode.create(varArgValue);
         }
@@ -256,6 +298,10 @@ public class CallArgumentsNode extends ArgumentsNode implements UnmatchedArgumen
         return varArgsSymbolIndices.length > 0;
     }
 
+    public int[] getVarArgsSymbolIndices() {
+        return varArgsSymbolIndices;
+    }
+
     @Override
     public IdentityHashMap<RNode, Closure> getContent() {
         return closureCache;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchNode.java
index 5c37954063d2c94df270c9bae55aa981ab28b5d1..49a53598905c27b1ec65dca129ca28e2b65ecf33 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchNode.java
@@ -21,20 +21,10 @@ public abstract class DispatchNode extends RNode {
 
     protected final String genericName;
 
-    public DispatchNode(String genericName) {
+    protected DispatchNode(String genericName) {
         this.genericName = genericName;
     }
 
-    static final class FunctionCall {
-        RFunction function;
-        CallArgumentsNode args;
-
-        FunctionCall(RFunction function, CallArgumentsNode args) {
-            this.function = function;
-            this.args = args;
-        }
-    }
-
     public abstract Object executeGeneric(VirtualFrame frame, RStringVector aType);
 
     @SuppressWarnings("unused")
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
index f7f1ba98f4dd996c9d051480e34131c6c6c36c5b..d1861fb90c93cb7b96299bb31714417475e734f1 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/PromiseHelperNode.java
@@ -31,6 +31,7 @@ import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
+import com.oracle.truffle.r.runtime.data.RPromise.VarargPromise;
 import com.oracle.truffle.r.runtime.data.RPromise.*;
 
 /**
@@ -114,6 +115,8 @@ public class PromiseHelperNode extends Node {
     @Child private PromiseHelperNode nextNode = null;
 
     private final ValueProfile promiseFrameProfile = ValueProfile.createClassProfile();
+    private final BranchProfile varArgProfile = BranchProfile.create();
+    private final BranchProfile multiVarArgProfile = BranchProfile.create();
 
     /**
      * Guarded by {@link #isInOriginFrame(VirtualFrame,RPromise)}.
@@ -135,30 +138,36 @@ public class PromiseHelperNode extends Node {
      * {@link RPromise#isEvaluated()}, propagation of CallSrc and dependency cycles. Actual
      * evaluation is delegated to {@link #generateValue(VirtualFrame, RPromise, SourceSection)}.
      *
-     * @param frame
-     * @param promise
-     * @param callSrc
      * @return The value the given Promise evaluates to
      */
     private Object doEvaluate(VirtualFrame frame, RPromise promise, SourceSection callSrc) {
-        if (isEvaluated(promise)) {
-            return promise.getValue();
+        RPromise current = promise;
+        if (current.getOptType() == OptType.VARARG) {
+            varArgProfile.enter();
+            current = ((VarargPromise) current).getVararg();
+            while (current.getOptType() == OptType.VARARG) {
+                multiVarArgProfile.enter();
+                current = ((VarargPromise) current).getVararg();
+            }
+        }
+        if (isEvaluated(current)) {
+            return current.getValue();
         }
 
         // Check for dependency cycle
-        if (isUnderEvaluation(promise)) {
+        if (isUnderEvaluation(current)) {
             throw RError.error(RError.Message.PROMISE_CYCLE);
         }
 
         // Evaluate guarded by underEvaluation
         try {
-            promise.setUnderEvaluation(true);
+            current.setUnderEvaluation(true);
 
-            Object obj = generateValue(frame, promise, callSrc);
-            setValue(obj, promise);
+            Object obj = generateValue(frame, current, callSrc);
+            setValue(obj, current);
             return obj;
         } finally {
-            promise.setUnderEvaluation(false);
+            current.setUnderEvaluation(false);
         }
     }
 
@@ -171,14 +180,15 @@ public class PromiseHelperNode extends Node {
      */
     private Object generateValue(VirtualFrame frame, RPromise promise, SourceSection callSrc) {
         OptType profiledOptType = optTypeProfile.profile(promise.getOptType());
-        if (profiledOptType == OptType.DEFAULT) {
-            return generateValueDefault(frame, promise, callSrc);
-        } else if (profiledOptType == OptType.PROMISED || profiledOptType == OptType.EAGER) {
-            return generateValueEager(frame, (EagerPromise) promise, callSrc);
-        } else if (profiledOptType == OptType.VARARG) {
-            return generateValueVararg((VarargPromise) promise, callSrc);
+        switch (profiledOptType) {
+            case DEFAULT:
+                return generateValueDefault(frame, promise, callSrc);
+            case EAGER:
+            case PROMISED:
+                return generateValueEager(frame, (EagerPromise) promise, callSrc);
+            default:
+                throw RInternalError.shouldNotReachHere("unexpected promise opt type");
         }
-        throw RInternalError.shouldNotReachHere();
     }
 
     private Object generateValueDefault(VirtualFrame frame, RPromise promise, SourceSection callSrc) {
@@ -215,7 +225,13 @@ public class PromiseHelperNode extends Node {
         } else if (promise.isValid()) {
 // promise.notifySuccess();
 
-            return getEagerValue(promise, callSrc);
+            OptType profiledOptType = optTypeProfile.profile(promise.getOptType());
+            if (profiledOptType == OptType.EAGER) {
+                return getEagerValue(promise);
+            } else if (profiledOptType == OptType.PROMISED) {
+                return getPromisedEagerValue(promise, callSrc);
+            }
+            throw RInternalError.shouldNotReachHere();
         } else {
             fallbackProfile.enter();
             promise.notifyFailure();
@@ -228,23 +244,6 @@ public class PromiseHelperNode extends Node {
         }
     }
 
-    @TruffleBoundary
-    private Object generateValueVararg(VarargPromise promise, SourceSection callSrc) {
-        RPromise nextPromise = promise.getVararg();
-        // TODO TruffleBoundary really needed? Null frame ok?
-        return checkNextNode().doEvaluate((VirtualFrame) null, nextPromise, callSrc);
-    }
-
-    private Object getEagerValue(EagerPromise promise, SourceSection callSrc) {
-        OptType profiledOptType = optTypeProfile.profile(promise.getOptType());
-        if (profiledOptType == OptType.EAGER) {
-            return getEagerValue(promise);
-        } else if (profiledOptType == OptType.PROMISED) {
-            return getPromisedEagerValue(promise, callSrc);
-        }
-        throw RInternalError.shouldNotReachHere();
-    }
-
     @TruffleBoundary
     private Object getPromisedEagerValue(EagerPromise promise, SourceSection callSrc) {
         RPromise nextPromise = (RPromise) promise.getEagerValue();
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 e63912c40c771d025ca81a4dff9d202c3fd334b9..8a20545deedc75c8e3306f55bbd2d61e4652a508 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
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.function;
 import static com.oracle.truffle.r.nodes.function.opt.EagerEvalHelper.*;
 
 import com.oracle.truffle.api.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
@@ -42,6 +43,7 @@ import com.oracle.truffle.r.runtime.data.RPromise.Closure;
 import com.oracle.truffle.r.runtime.data.RPromise.EvalPolicy;
 import com.oracle.truffle.r.runtime.data.RPromise.PromiseType;
 import com.oracle.truffle.r.runtime.data.RPromise.RPromiseFactory;
+import com.oracle.truffle.r.runtime.env.*;
 
 /**
  * This {@link RNode} implementations are used as a factory-nodes for {@link RPromise}s OR direct
@@ -134,13 +136,10 @@ public abstract class PromiseNode extends RNode {
     }
 
     /**
-     * @param promise
-     * @return Creates a {@link VarArgNode} for the given {@link RPromise}
+     * @return Creates a {@link VarArgNode} for the given
      */
-    public static VarArgNode createVarArg(RPromise promise) {
-        VarArgNode result = new VarArgNode(promise);
-        result.assignSourceSection(((RNode) promise.getRep()).getSourceSection());
-        return result;
+    public static VarArgNode createVarArg(int varArgIndex) {
+        return new VarArgNode(varArgIndex);
     }
 
     /**
@@ -148,15 +147,13 @@ public abstract class PromiseNode extends RNode {
      */
     private static final class PromisedNode extends PromiseNode {
 
-        private final ConditionProfile isSuppliedArgProfile = ConditionProfile.createBinaryProfile();
-
         private PromisedNode(RPromiseFactory factory) {
             super(factory);
         }
 
         @Override
         public Object execute(VirtualFrame frame) {
-            MaterializedFrame execFrame = isSuppliedArgProfile.profile(factory.getType() == PromiseType.ARG_SUPPLIED) ? frame.materialize() : null;
+            MaterializedFrame execFrame = factory.getType() == PromiseType.ARG_SUPPLIED ? frame.materialize() : null;
             return factory.createPromise(execFrame);
         }
     }
@@ -203,7 +200,11 @@ public abstract class PromiseNode extends RNode {
             // At this point we simply circumvent VarArgNode (by directly passing the contained
             // Promise); BUT we have to respect the RPromise! Thus we use a RPromise class which
             // knows that it contains a RPromise..
-            return factory.createVarargPromise(varargNode.getPromise());
+            return factory.createVarargPromise(varargNode.executeNonEvaluated(frame));
+        }
+
+        public RNode substitute(REnvironment env) {
+            return varargNode.substitute(env);
         }
 
         public VarArgNode getVarArgNode() {
@@ -321,43 +322,56 @@ public abstract class PromiseNode extends RNode {
      * In a certain sense this is the class corresponding class for GNU R's PROMSXP (AST equivalent
      * of RPromise, only needed for varargs in FastR TODO Move to separate package together with
      * other varargs classes)
-     *
-     * FIXME This class effectively captures frame-specific state since the {@link RPromise} value
-     * refers to a specific frame through the {@code execFrame} field. So subsequent calls to a
-     * function containing one of these nodes will return a stale value when the promise is
-     * evaluated. We need to find a better way. The current workaround is to call
-     * {@link #setPromise} to update the state.
      */
     public static final class VarArgNode extends RNode {
-        private RPromise promise;
-        private boolean isEvaluated = false;
 
-        private VarArgNode(RPromise promise) {
-            this.promise = promise;
+        @Child private FrameSlotNode varArgsSlotNode;
+        @Child private PromiseHelperNode promiseHelper;
+
+        private final int index;
+
+        private VarArgNode(int index) {
+            this.index = index;
+        }
+
+        public RArgsValuesAndNames getVarargsAndNames(VirtualFrame frame) {
+            if (varArgsSlotNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                varArgsSlotNode = insert(FrameSlotNode.create(ArgumentsSignature.VARARG_NAME));
+            }
+            RArgsValuesAndNames varArgsAndNames;
+            try {
+                varArgsAndNames = (RArgsValuesAndNames) frame.getObject(varArgsSlotNode.executeFrameSlot(frame));
+            } catch (FrameSlotTypeException | ClassCastException e) {
+                throw RInternalError.shouldNotReachHere("'...' should always be represented by RArgsValuesAndNames");
+            }
+            return varArgsAndNames;
         }
 
         @Override
         public Object execute(VirtualFrame frame) {
-            // ExpressionExecutorNode would be overkill, as this is only executed once, and not in
-            // the correct frame anyway
-            if (!isEvaluated) {
+            RPromise promise = executeNonEvaluated(frame);
+            if (promise.isEvaluated()) {
+                return promise.getValue();
+            }
+            if (promiseHelper == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                Object result = PromiseHelperNode.evaluateSlowPath(frame, promise);
-                isEvaluated = promise.isEvaluated();
-                return result;
+                promiseHelper = insert(new PromiseHelperNode());
             }
+            return promiseHelper.evaluate(frame, promise);
+        }
 
-            // Should easily compile to constant
-            return promise.getValue();
+        public RPromise executeNonEvaluated(VirtualFrame frame) {
+            return (RPromise) getVarargsAndNames(frame).getValues()[index];
         }
 
-        public RPromise getPromise() {
-            return promise;
+        public RNode substitute(REnvironment env) {
+            Object obj = ((RArgsValuesAndNames) env.get("...")).getValues()[index];
+            return obj instanceof RPromise ? (RNode) ((RPromise) obj).getRep() : ConstantNode.create(obj);
         }
 
-        public void setPromise(RPromise promise) {
-            isEvaluated = false;
-            this.promise = promise;
+        public int getIndex() {
+            return index;
         }
     }
 
@@ -394,12 +408,15 @@ public abstract class PromiseNode extends RNode {
      * This class is used for wrapping arguments into "..." ({@link RArgsValuesAndNames}).
      */
     public static final class VarArgsPromiseNode extends RNode {
-        @Children protected final RNode[] nodes;
+        @CompilationFinal private final Closure[] closures;
         private final ArgumentsSignature signature;
         protected final ClosureCache closureCache;
 
         public VarArgsPromiseNode(RNode[] nodes, ArgumentsSignature signature, ClosureCache closureCache) {
-            this.nodes = nodes;
+            this.closures = new Closure[nodes.length];
+            for (int i = 0; i < nodes.length; i++) {
+                this.closures[i] = closureCache.getOrCreateClosure(nodes[i]);
+            }
             this.signature = signature;
             this.closureCache = closureCache;
         }
@@ -407,10 +424,9 @@ public abstract class PromiseNode extends RNode {
         @Override
         @ExplodeLoop
         public Object execute(VirtualFrame frame) {
-            Object[] promises = new Object[nodes.length];
-            for (int i = 0; i < nodes.length; i++) {
-                Closure closure = closureCache.getOrCreateClosure(nodes[i]);
-                promises[i] = RDataFactory.createPromise(EvalPolicy.PROMISED, PromiseType.ARG_SUPPLIED, frame.materialize(), closure);
+            Object[] promises = new Object[closures.length];
+            for (int i = 0; i < closures.length; i++) {
+                promises[i] = RDataFactory.createPromise(EvalPolicy.PROMISED, PromiseType.ARG_SUPPLIED, frame.materialize(), closures[i]);
             }
             return new RArgsValuesAndNames(promises, signature);
         }
@@ -420,22 +436,26 @@ public abstract class PromiseNode extends RNode {
             // In support of match.call(expand.dots=FALSE)
             // GnuR represents this with a pairlist and deparses it as "list(a,b,..)"
             state.append("list(");
-            for (int i = 0; i < nodes.length; i++) {
+            for (int i = 0; i < closures.length; i++) {
                 String name = signature.getName(i);
                 if (name != null) {
                     state.append(name);
                     state.append(" = ");
                 }
-                nodes[i].deparse(state);
-                if (i < nodes.length - 1) {
+                ((RNode) closures[i].getExpr()).deparse(state);
+                if (i < closures.length - 1) {
                     state.append(", ");
                 }
             }
             state.append(')');
         }
 
-        public RNode[] getNodes() {
-            return nodes;
+        public RNode substitute(REnvironment env) {
+            return RASTUtils.substituteName("...", env);
+        }
+
+        public Closure[] getClosures() {
+            return closures;
         }
 
         public ArgumentsSignature getSignature() {
@@ -448,7 +468,7 @@ public abstract class PromiseNode extends RNode {
      * more complicated, as "..." might include values from an outer "...", which might resolve to
      * an empty argument list.
      */
-    public static final class InlineVarArgsPromiseNode extends RNode {
+    private static final class InlineVarArgsPromiseNode extends RNode {
         @Children private final RNode[] varargs;
         protected final ArgumentsSignature signature;
 
@@ -461,10 +481,6 @@ public abstract class PromiseNode extends RNode {
             assert varargs.length == signature.getLength();
         }
 
-        public RNode[] getVarArgs() {
-            return varargs;
-        }
-
         @Override
         @ExplodeLoop
         public Object execute(VirtualFrame frame) {
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 b9f9e958a40479b7ca8956fb67702a1932d0351f..ca299375091491d0014ba87877047cc1e1de2b8d 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
@@ -79,13 +79,13 @@ import com.oracle.truffle.r.runtime.env.*;
  *  U = {@link UninitializedCallNode}: Forms the uninitialized end of the function PIC
  *  D = {@link DispatchedCallNode}: Function fixed, no varargs
  *  G = {@link GenericCallNode}: Function arbitrary, no varargs (generic case)
- * 
+ *
  *  UV = {@link UninitializedCallNode} with varargs,
  *  UVC = {@link UninitializedVarArgsCacheCallNode} with varargs, for varargs cache
  *  DV = {@link DispatchedVarArgsCallNode}: Function fixed, with cached varargs
  *  DGV = {@link DispatchedGenericVarArgsCallNode}: Function fixed, with arbitrary varargs (generic case)
  *  GV = {@link GenericVarArgsCallNode}: Function arbitrary, with arbitrary varargs (generic case)
- * 
+ *
  * (RB = {@link RBuiltinNode}: individual functions that are builtins are represented by this node
  * which is not aware of caching). Due to {@link CachedCallNode} (see below) this is transparent to
  * the cache and just behaves like a D/DGV)
@@ -98,11 +98,11 @@ import com.oracle.truffle.r.runtime.env.*;
  * non varargs, max depth:
  * |
  * D-D-D-U
- * 
+ *
  * no varargs, generic (if max depth is exceeded):
  * |
  * D-D-D-D-G
- * 
+ *
  * varargs:
  * |
  * DV-DV-UV         <- function call target identity level cache
@@ -110,7 +110,7 @@ import com.oracle.truffle.r.runtime.env.*;
  *    DV
  *    |
  *    UVC           <- varargs signature level cache
- * 
+ *
  * varargs, max varargs depth exceeded:
  * |
  * DV-DV-UV
@@ -122,7 +122,7 @@ import com.oracle.truffle.r.runtime.env.*;
  *    DV
  *    |
  *    DGV
- * 
+ *
  * varargs, max function depth exceeded:
  * |
  * DV-DV-DV-DV-GV
@@ -763,7 +763,7 @@ public abstract class RCallNode extends RNode {
             }
 
             // If the signature does not match: delegate to next node!
-            if (cachedSignature.isNotEqualTo(currentSignature)) {
+            if (!cachedSignature.isEqualTo(currentSignature)) {
                 return next.execute(frame, currentFunction, currentSignature);
             }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnaryOpsGroupDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnaryOpsGroupDispatchNode.java
index b295d24608c328c3e0749751e6083d66e7db08ad..d95ca5c21ef877b0e8c8b1833ab3086cf0efd9b6 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnaryOpsGroupDispatchNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnaryOpsGroupDispatchNode.java
@@ -27,7 +27,8 @@ public class UnaryOpsGroupDispatchNode extends GroupDispatchNode {
     @Override
     protected Object callBuiltin(VirtualFrame frame, Object[] evaluatedArgs, ArgumentsSignature signature) {
         initBuiltin(frame);
-        Object[] argObject = RArguments.create(builtinFunc, callSrc, null, RArguments.getDepth(frame) + 1, new Object[]{evaluatedArgs[0], RMissing.instance});
+        Object[] args = ((HasSignature) builtinFunc.getRootNode()).getSignature().getLength() == 1 ? new Object[]{evaluatedArgs[0]} : new Object[]{evaluatedArgs[0], RMissing.instance};
+        Object[] argObject = RArguments.create(builtinFunc, callSrc, null, RArguments.getDepth(frame) + 1, args);
         return indirectCallNode.call(frame, builtinFunc.getTarget(), argObject);
     }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java
index a74a7af00c23d680b63777fd0158db8ecef04d67..42851297731ed2a5fb4ee9ac4951876a843df1b3 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java
@@ -199,6 +199,7 @@ final class UseMethodDispatchCachedNode extends S3DispatchCachedNode {
         int argCount = arguments.length;
         int argListSize = argCount;
 
+        // extract vararg signatures from the arguments
         ArgumentsSignature[] varArgSignatures = null;
         for (int i = 0; i < arguments.length; i++) {
             Object arg = arguments[i];
@@ -210,27 +211,12 @@ final class UseMethodDispatchCachedNode extends S3DispatchCachedNode {
                 argListSize += ((RArgsValuesAndNames) arg).length() - 1;
             }
         }
+
         long[] preparePermutation;
         ArgumentsSignature resultSignature;
         if (varArgSignatures != null) {
-            preparePermutation = new long[argListSize];
-            String[] argNames = new String[argListSize];
-            int index = 0;
-            for (int fi = 0; fi < argCount; ++fi) {
-                Object arg = arguments[fi];
-                if (arg instanceof RArgsValuesAndNames) {
-                    RArgsValuesAndNames varArgs = (RArgsValuesAndNames) arg;
-                    ArgumentsSignature varArgSignature = varArgs.getSignature();
-                    for (int i = 0; i < varArgs.length(); i++) {
-                        argNames[index] = varArgSignature.getName(i);
-                        preparePermutation[index++] = -((((long) fi) << 32) + i);
-                    }
-                } else {
-                    argNames[index] = signature.getName(fi);
-                    preparePermutation[index++] = fi;
-                }
-            }
-            resultSignature = ArgumentsSignature.get(argNames);
+            resultSignature = ArgumentsSignature.flattenNames(signature, varArgSignatures, argListSize);
+            preparePermutation = ArgumentsSignature.flattenIndexes(varArgSignatures, argListSize);
         } else {
             preparePermutation = new long[argCount];
             for (int i = 0; i < argCount; i++) {
@@ -239,7 +225,7 @@ final class UseMethodDispatchCachedNode extends S3DispatchCachedNode {
             resultSignature = signature;
         }
 
-        assert signature != null;
+        assert resultSignature != null;
         MatchPermutation permutation = ArgumentMatcher.matchArguments(result.targetFunction, resultSignature, getEncapsulatingSourceSection(), false);
 
         CheckReadsNode newCheckedReads = new CheckReadsNode(unsuccessfulReadsCaller, unsuccessfulReadsDef, result.successfulRead, result.targetFunction, result.clazz, result.targetFunctionName,
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/VarArgsSignature.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/VarArgsSignature.java
index ef545207eb35b0697a33b3959794036caba3c638..89eb9729a6ce7f5a0d914cc75bdd087ef7715b4b 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/VarArgsSignature.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/VarArgsSignature.java
@@ -56,6 +56,7 @@ public final class VarArgsSignature {
      */
     public static final RNode NO_VARARGS = ConstantNode.create(RArgsValuesAndNames.EMPTY);
     public static final VarArgsSignature TAKES_NO_VARARGS = new VarArgsSignature(null, 0);
+    public static final VarArgsSignature NO_VARARGS_GIVEN = new VarArgsSignature(new Object[]{NO_VARARGS}, 0);
 
     @CompilationFinal private final Object[] expressions;
     private final int times;
@@ -100,8 +101,4 @@ public final class VarArgsSignature {
         }
         return true;
     }
-
-    public boolean isNotEqualTo(VarArgsSignature other) {
-        return !isEqualTo(other);
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java
index ba50c1f4a1332ae1378844f848e99aeec3ba9a2a..4803e42caaa10839b43a924e6cb023c6cfcdb047 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java
@@ -122,7 +122,7 @@ public class RASTHelperImpl implements RASTHelper {
         } else if (node instanceof AccessFieldNode) {
             return 3;
         } else if (node instanceof VarArgsPromiseNode) {
-            return ((VarArgsPromiseNode) node).getNodes().length;
+            return ((VarArgsPromiseNode) node).getClosures().length;
         } else {
             // TODO fill out
             assert false : node;
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 0a29c09f506bb54cf4912b1a218b29b0af776f11..8c9ebc939949b3a8e3883c735b1c38a363d3557a 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
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.data.model.*;
 
 public abstract class CastListNode extends CastNode {
 
-    @Child CastListNode castListRecursive;
+    @Child private CastListNode castListRecursive;
 
     private final RAttributeProfiles attrProfiles = RAttributeProfiles.create();
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
index c2dce0b0b458074c1181c379cea02f8b4a6d12d6..7e1d4934d7bdf08d1ae7a8def6d332ebeb282914 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastNode.java
@@ -48,17 +48,13 @@ public abstract class CastNode extends UnaryNode {
 
     protected abstract boolean isAttrPreservation();
 
-    protected boolean isPreserveDimensions() {
-        return isDimensionsPreservation();
-    }
-
     protected RError throwCannotCoerceListError(String type) {
         listCoercionErrorBranch.enter();
         throw RError.error(getSourceSection(), RError.Message.LIST_COERCION, type);
     }
 
     protected int[] getPreservedDimensions(RAbstractContainer operand) {
-        int[] dimensions = isPreserveDimensions() ? operand.getDimensions() : null;
+        int[] dimensions = isDimensionsPreservation() ? operand.getDimensions() : null;
         int[] preservedDimensions = hasDimensionsProfile.profile(dimensions != null) ? dimensions : null;
         return preservedDimensions;
     }
@@ -70,7 +66,7 @@ public abstract class CastNode extends UnaryNode {
     }
 
     protected void preserveDimensionNames(RAbstractContainer operand, RVector ret) {
-        RList dimNames = isPreserveDimensions() ? operand.getDimNames() : null;
+        RList dimNames = isDimensionsPreservation() ? operand.getDimNames() : null;
         if (hasDimNamesProfile.profile(dimNames != null)) {
             ret.setDimNames((RList) dimNames.copy());
         }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
index d821c36c572ef5387595afc2b2850d6b6260bfa0..d87f14747387f5599649b7c7cc750a5dbe67e12c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastRawNode.java
@@ -233,7 +233,7 @@ public abstract class CastRawNode extends CastNode {
 
     @Fallback
     @TruffleBoundary
-    public int doOther(Object operand) {
+    protected int doOther(Object operand) {
         throw new ConversionFailedException(operand.getClass().getName());
     }
 }
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 3902423c615c13af0422cb5328528cf7fd3f1bf3..2923b5e323d8e454da4a2e5beaa2a060dfa9706d 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
@@ -27,6 +27,7 @@ import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
+import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.conn.*;
@@ -37,146 +38,48 @@ import com.oracle.truffle.r.runtime.env.*;
 @SuppressWarnings("unused")
 public abstract class TypeofNode extends UnaryNode {
 
-    public abstract RType execute(Object x);
-
-    @Specialization
-    protected RType typeof(RNull vector) {
-        return RType.Null;
-    }
-
-    @Specialization
-    protected RType typeof(byte x) {
-        return RType.Logical;
-    }
-
-    @Specialization
-    protected RType typeof(int s) {
-        return RType.Integer;
-    }
-
-    @Specialization
-    protected RType typeof(double x) {
-        return RType.Double;
-    }
-
-    @Specialization
-    protected RType typeof(RComplex x) {
-        return RType.Complex;
-    }
+    protected static final int NUMBER_OF_CACHED_CLASSES = 5;
 
-    @Specialization
-    protected RType typeof(RRaw x) {
-        return RType.Raw;
-    }
-
-    @Specialization
-    protected RType typeof(String x) {
-        return RType.Character;
-    }
-
-    @Specialization
-    protected RType typeof(RIntSequence vector) {
-        return RType.Integer;
-    }
+    public abstract RType execute(Object x);
 
     @Specialization
-    protected RType typeof(RLogicalVector vector) {
+    protected static RType doLogical(byte x) {
         return RType.Logical;
     }
 
     @Specialization
-    protected RType typeof(RAbstractIntVector vector) {
+    protected static RType doInt(int s) {
         return RType.Integer;
     }
 
     @Specialization
-    protected RType typeof(RAbstractDoubleVector vector) {
+    protected static RType doDouble(double x) {
         return RType.Double;
     }
 
     @Specialization
-    protected RType typeof(RStringVector vector) {
+    protected static RType doString(String x) {
         return RType.Character;
     }
 
-    @Specialization
-    protected RType typeof(RComplexVector vector) {
-        return RType.Complex;
-    }
-
-    @Specialization
-    protected RType typeof(RRawVector vector) {
-        return RType.Raw;
-    }
-
-    @Specialization
-    protected RType typeof(RList list) {
-        return RType.List;
-    }
-
-    @Specialization
-    protected RType typeof(REnvironment env) {
-        return RType.Environment;
-    }
-
-    @Specialization
-    protected RType typeof(RSymbol symbol) {
-        return RType.Symbol;
-    }
-
-    @Specialization
-    protected RType typeof(RExternalPtr symbol) {
-        return RType.ExternalPtr;
-    }
-
-    @Specialization
-    protected RType typeof(RLanguage language) {
-        return RType.Language;
-    }
-
-    @Specialization
-    protected RType typeof(RPromise promise) {
-        return RType.Promise;
-    }
-
-    @Specialization
-    protected RType typeof(RExpression symbol) {
-        return RType.Expression;
-    }
-
-    @Specialization
-    protected RType typeof(RPairList pairlist) {
-        return RType.PairList;
-    }
-
-    @Specialization(guards = "obj.isBuiltin()")
-    protected RType typeofBuiltin(RFunction obj) {
-        return RType.Builtin;
-    }
-
-    @Specialization(guards = "!obj.isBuiltin()")
-    protected RType typeofClosure(RFunction obj) {
-        return RType.Closure;
-    }
-
-    @Specialization
-    protected RType typeofFormula(RFormula f) {
-        return RType.Language;
+    @Specialization(guards = {"operand.getClass() == cachedClass"}, limit = "NUMBER_OF_CACHED_CLASSES")
+    protected static RType doCachedTyped(Object operand, //
+                    @Cached("getTypedValueClass(operand)") Class<? extends RTypedValue> cachedClass) {
+        return cachedClass.cast(operand).getRType();
     }
 
-    @Specialization
-    protected RType typeof(RConnection conn) {
-        return RType.Integer;
+    protected static Class<? extends RTypedValue> getTypedValueClass(Object operand) {
+        CompilerAsserts.neverPartOfCompilation();
+        if (operand instanceof RTypedValue) {
+            return ((RTypedValue) operand).getClass();
+        } else {
+            throw new AssertionError("Invalid untyped value " + operand.getClass() + ".");
+        }
     }
 
-    @Specialization
-    protected RType typeof(RDataFrame frame) {
-        return RType.List;
-    }
-
-    @Specialization
-    protected RType typeof(RFactor factor) {
-        return RType.Integer;
+    @Specialization(contains = {"doCachedTyped"})
+    protected static RType doGenericTyped(RTypedValue operand) {
+        return operand.getRType();
     }
 
 }
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 f7bab57746927bedfc09d8bb386724794b13bca2..e1a7b05f25754e835a17766c5792c0adcdab2eab 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
@@ -50,13 +50,13 @@ public abstract class UnaryArithmeticReduceNode extends UnaryNode {
     private final ConditionProfile naRmProfile = ConditionProfile.createBinaryProfile();
     private final BranchProfile warningProfile = BranchProfile.create();
 
-    public UnaryArithmeticReduceNode(ReduceSemantics semantics, BinaryArithmeticFactory factory) {
+    protected UnaryArithmeticReduceNode(ReduceSemantics semantics, BinaryArithmeticFactory factory) {
         this.factory = factory;
         this.semantics = semantics;
         this.arithmetic = factory.create();
     }
 
-    public UnaryArithmeticReduceNode(UnaryArithmeticReduceNode op) {
+    protected UnaryArithmeticReduceNode(UnaryArithmeticReduceNode op) {
         // we recreate the arithmetic each time this specialization specializes
         // it also makes sense for polymorphic variations of this node
         this(op.semantics, op.factory);
@@ -321,7 +321,7 @@ public abstract class UnaryArithmeticReduceNode extends UnaryNode {
     // "largest" String for the implementation of max function
 
     @SuppressWarnings("unused")
-    protected static String doStringVectorEmptyInternal(RStringVector operand, byte naRm, ReduceSemantics semantics, SourceSection sourceSection) {
+    private static String doStringVectorEmptyInternal(RStringVector operand, byte naRm, ReduceSemantics semantics, SourceSection sourceSection) {
         if (semantics.supportString) {
             if (semantics.getEmptyWarning() != null) {
                 RError.warning(semantics.emptyWarning);
@@ -407,15 +407,6 @@ public abstract class UnaryArithmeticReduceNode extends UnaryNode {
         public RError.Message getEmptyWarning() {
             return emptyWarning;
         }
-
-        public boolean supportsComplex() {
-            return supportComplex;
-        }
-
-        public boolean supportsString() {
-            return supportString;
-        }
-
     }
 
     @NodeChildren({@NodeChild("operand"), @NodeChild("naRm"), @NodeChild("offset")})
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
index a17351b6454a2b0a1c5dcb62209a371b57922aa0..6c8598889de2eb6f8ab673980f244efc164b88c5 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryNode.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,20 +24,15 @@ package com.oracle.truffle.r.nodes.unary;
 
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.r.nodes.*;
-import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.RDeparse.State;
-import com.oracle.truffle.r.runtime.data.*;
-import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.*;
+import com.oracle.truffle.r.runtime.env.*;
 
 @NodeChildren({@NodeChild("operand")})
 public abstract class UnaryNode extends RNode {
 
     public abstract RNode getOperand();
 
-    protected static boolean isNA(byte operand) {
-        return RRuntime.isNA(operand);
-    }
-
     protected static boolean isNA(int operand) {
         return RRuntime.isNA(operand);
     }
@@ -46,14 +41,6 @@ public abstract class UnaryNode extends RNode {
         return RRuntime.isNA(operand);
     }
 
-    protected static boolean isNaN(double operand) {
-        return Double.isNaN(operand);
-    }
-
-    protected static boolean isNA(RComplex c) {
-        return c.isNA();
-    }
-
     @Override
     public boolean isSyntax() {
         // TODO check, may be bi-modal
diff --git a/com.oracle.truffle.r.options/src/com/oracle/truffle/r/options/FastROptions.java b/com.oracle.truffle.r.options/src/com/oracle/truffle/r/options/FastROptions.java
index 9c64f3eed1a2dbb18a04632fee8a98f2aa7efd91..ca8a7f1ccb71c55edf16c2c0d1bdc6d97ca9d1bf 100644
--- a/com.oracle.truffle.r.options/src/com/oracle/truffle/r/options/FastROptions.java
+++ b/com.oracle.truffle.r.options/src/com/oracle/truffle/r/options/FastROptions.java
@@ -63,6 +63,8 @@ public class FastROptions {
     public static final OptionValue<Boolean> PerformanceWarnings = new OptionValue<>(false);
     @Option(help = "Load base package")
     public static final OptionValue<Boolean> LoadBase = new OptionValue<>(true);
+    @Option(help = "Print a message for each non-trivial variable lookup")
+    public static final OptionValue<Boolean> PrintComplexLookups = new OptionValue<>(false);
 
     // Promises optimizations
     @Option(help = "If enabled, overrides all other EagerEval switches (see EagerEvalHelper)")
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseException.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseException.java
deleted file mode 100644
index 125ab4d72b1fe4baa11afb4261036c1ace0a89cf..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseException.java
+++ /dev/null
@@ -1,24 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser;
-
-public class ParseException extends RuntimeException {
-
-    private static final long serialVersionUID = 1L;
-
-    public ParseException() {
-    }
-
-    public ParseException(String message) {
-        super(message);
-    }
-
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseUtil.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseUtil.java
index efb507ba441086eaac4d61a91575d7c1efec4fbc..d41c53fceb2950f9ef08aacd3f8c01359b79adbf 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseUtil.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ParseUtil.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -13,13 +13,11 @@ package com.oracle.truffle.r.parser;
 import org.antlr.runtime.*;
 
 import com.oracle.truffle.api.source.*;
-import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.parser.ast.*;
 
 public class ParseUtil {
 
-    @TruffleBoundary
-    public static String hexChar(String... chars) {
+    static String hexChar(String... chars) {
         int value = 0;
         for (int i = 0; i < chars.length; i++) {
             value = value * 16 + Integer.parseInt(chars[i], 16);
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 b9503012dfd7bf5bf5a78b2f53c2142e830db3e8..a66dc5e1a897082e8f05646cbdff8e1eb1cb56cd 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
@@ -62,6 +62,6 @@ public class ParserGeneration {
         "support strings in field accesses",
         "allow NULL= in switch",
         "support NA_complex_",
+        "simplified unary and binary operations"
     };
-
 }
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 187fea7934c69bd324b65fd9302194fe0d55a16c..f6c95b6b2d092b3fd4473ee45e98c5672f669b71 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,8 +29,9 @@ import com.oracle.truffle.api.impl.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.parser.ast.*;
 import com.oracle.truffle.r.parser.ast.Call.*;
-import com.oracle.truffle.r.parser.ast.UnaryOperation.*;
 import com.oracle.truffle.r.parser.ast.BinaryOperation.*;
+import com.oracle.truffle.r.parser.ast.Operation.*;
+import com.oracle.truffle.r.parser.ast.UnaryOperation.*;
 }
 
 @lexer::header {
@@ -359,7 +360,7 @@ and_expr returns [ASTNode v]
     ;
 
 not_expr returns [ASTNode v]
-    : t=NOT n_ l=not_expr { $v = UnaryOperation.create(sourceSection("not_expr", $t, $l.stop), UnaryOperator.NOT, $l.v); }
+    : t=NOT n_ l=not_expr { $v = UnaryOperation.create(sourceSection("not_expr", $t, $l.stop), Operator.UNARY_NOT, $l.v); }
     | b=comp_expr         { $v = $b.v; }
     ;
 
@@ -420,7 +421,7 @@ colon_expr returns [ASTNode v] // FIXME
         }
     }
     : l=unary_expression { $v = $l.v; }
-      ( ((COLON)=>op=COLON n_ r=unary_expression { hasColon = true; $v = BinaryOperation.create(sourceSection("colon_expr/binop", $op, $r.stop), BinaryOperator.COLON, $colon_expr.v, $r.v); }) )*
+      ( ((COLON)=>op=COLON n_ r=unary_expression { hasColon = true; $v = BinaryOperation.create(sourceSection("colon_expr/binop", $op, $r.stop), Operator.COLON, $colon_expr.v, $r.v); }) )*
     ;
 
 unary_expression returns [ASTNode v]
@@ -433,11 +434,11 @@ unary_expression returns [ASTNode v]
     }
     : p=PLUS n_ { plusOrMinus = true; }
       ( (number) => num=number { $v = num; }
-      | l=unary_expression     { $v = UnaryOperation.create(sourceSection("unary_expression/PLUS", $p, $l.stop), UnaryOperator.PLUS, $l.v); }
+      | l=unary_expression     { $v = UnaryOperation.create(sourceSection("unary_expression/PLUS", $p, $l.stop), Operator.UNARY_PLUS, $l.v); }
       )
     | m=MINUS n_ { plusOrMinus = true; }
       ( (number) => num=number { ((Constant) num).addNegativeSign(); $v = num; }
-      | l=unary_expression     { $v = UnaryOperation.create(sourceSection("unary_expression/MINUS", $m, $l.stop), UnaryOperator.MINUS, $l.v); }
+      | l=unary_expression     { $v = UnaryOperation.create(sourceSection("unary_expression/MINUS", $m, $l.stop), Operator.UNARY_MINUS, $l.v); }
       )
     | b=power_expr             { $v = $b.v; }
     ;
@@ -536,38 +537,38 @@ bool returns [ASTNode v]
     | t=NA    { $v = Constant.createBoolConstant(sourceSection("bool/NA", t), RRuntime.LOGICAL_NA); }
     ;
 
-or_operator returns [BinaryOperator v]
-    : OR            { $v = BinaryOperator.OR; }
-    | ELEMENTWISEOR { $v = BinaryOperator.ELEMENTWISEOR; }
+or_operator returns [Operator v]
+    : OR            { $v = Operator.OR; }
+    | ELEMENTWISEOR { $v = Operator.ELEMENTWISEOR; }
     ;
 
-and_operator returns [BinaryOperator v]
-    : AND            { $v = BinaryOperator.AND; }
-    | ELEMENTWISEAND { $v = BinaryOperator.ELEMENTWISEAND; }
+and_operator returns [Operator v]
+    : AND            { $v = Operator.AND; }
+    | ELEMENTWISEAND { $v = Operator.ELEMENTWISEAND; }
     ;
 
-comp_operator returns [BinaryOperator v]
-    : GT { $v = BinaryOperator.GT; }
-    | GE { $v = BinaryOperator.GE; }
-    | LT { $v = BinaryOperator.LT; }
-    | LE { $v = BinaryOperator.LE; }
-    | EQ { $v = BinaryOperator.EQ; }
-    | NE { $v = BinaryOperator.NE; }
+comp_operator returns [Operator v]
+    : GT { $v = Operator.GT; }
+    | GE { $v = Operator.GE; }
+    | LT { $v = Operator.LT; }
+    | LE { $v = Operator.LE; }
+    | EQ { $v = Operator.EQ; }
+    | NE { $v = Operator.NE; }
     ;
 
-add_operator returns [BinaryOperator v]
-    : PLUS  { $v = BinaryOperator.ADD; }
-    | MINUS { $v = BinaryOperator.SUB; }
+add_operator returns [Operator v]
+    : PLUS  { $v = Operator.ADD; }
+    | MINUS { $v = Operator.SUB; }
     ;
 
-mult_operator returns [BinaryOperator v]
-    : MULT { $v = BinaryOperator.MULT; }
-    | DIV  { $v = BinaryOperator.DIV; }
-    | MOD  { $v = BinaryOperator.MOD; }
+mult_operator returns [Operator v]
+    : MULT { $v = Operator.MULT; }
+    | DIV  { $v = Operator.DIV; }
+    | MOD  { $v = Operator.MOD; }
     ;
 
-power_operator returns [BinaryOperator v]
-    : CARET { $v = BinaryOperator.POW; }
+power_operator returns [Operator v]
+    : CARET { $v = Operator.POW; }
     ;
 
 args returns [List<ArgNode> v]
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ASTNode.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ASTNode.java
index 0863f98c29fb20712eb372ea2913fbee082698c4..a6763f9aa620b796b0e31c11a850f820b1f50664 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ASTNode.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ASTNode.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -42,8 +42,6 @@ public abstract class ASTNode {
     }
 
     public int getPrecedence() {
-        Class<?> clazz = getClass();
-        Precedence prec = clazz.getAnnotation(Precedence.class);
-        return prec == null ? Precedence.MIN : prec.value();
+        return Operation.MIN_PRECEDENCE;
     }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java
index 8f34456a41437e4053ebe8e3d14d7214f438477b..35c678aaee13a93f5f1df93b3c73960541e41cbb 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AccessVector.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -14,12 +14,12 @@ import java.util.*;
 
 import com.oracle.truffle.api.source.*;
 
-public class AccessVector extends Call {
+public final class AccessVector extends Call {
 
     private final ASTNode vector;
     private final boolean subset;
 
-    public AccessVector(SourceSection source, ASTNode vector, List<ArgNode> arguments, boolean subset) {
+    AccessVector(SourceSection source, ASTNode vector, List<ArgNode> arguments, boolean subset) {
         super(source, arguments);
         this.vector = vector;
         this.subset = subset;
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Add.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Add.java
deleted file mode 100644
index 99253f2b7ce7684808de2d9cf7c62281340ba2e1..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Add.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("+")
-@Precedence(Operation.ADD_PRECEDENCE)
-public class Add extends BinaryOperation {
-
-    public Add(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/And.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/And.java
deleted file mode 100644
index feb530aad56bcaeb75cf2c79f3c34419b127669c..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/And.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("&&")
-@Precedence(Operation.AND_PRECEDENCE)
-public class And extends BinaryOperation {
-
-    public And(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java
index 0a8964465f3ae0659b1bb5aa0cd7736bd1a6490f..f76d03c016a1bb0fd31e235a4ede7a7a49267360 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/AssignVariable.java
@@ -62,11 +62,11 @@ public abstract class AssignVariable extends ASTNode {
         return null;
     }
 
-    public static ASTNode writeVariable(SourceSection src, boolean isSuper, String name, ASTNode rhs) {
+    private static ASTNode writeVariable(SourceSection src, boolean isSuper, String name, ASTNode rhs) {
         return new SimpleAssignVariable(src, isSuper, name, rhs);
     }
 
-    public static ASTNode writeVector(@SuppressWarnings("unused") SourceSection src, boolean isSuper, AccessVector lhs, ASTNode rhs) {
+    private static ASTNode writeVector(@SuppressWarnings("unused") SourceSection src, boolean isSuper, AccessVector lhs, ASTNode rhs) {
         ASTNode first = lhs.getVector();
         if (first instanceof SimpleAccessVariable) {
             SimpleAccessVariable simpleAccessVariable = (SimpleAccessVariable) first;
@@ -97,11 +97,11 @@ public abstract class AssignVariable extends ASTNode {
         }
     }
 
-    public static ASTNode writeField(SourceSection src, boolean isSuper, FieldAccess lhs, ASTNode rhs) {
+    private static ASTNode writeField(SourceSection src, boolean isSuper, FieldAccess lhs, ASTNode rhs) {
         return new UpdateField(src, isSuper, lhs, rhs);
     }
 
-    public static ASTNode writeFunction(SourceSection src, boolean isSuper, FunctionCall lhs, ASTNode rhs) {
+    private static ASTNode writeFunction(SourceSection src, boolean isSuper, FunctionCall lhs, ASTNode rhs) {
         // FIXME Probably we need a special node, for now all assign function should return value
         if (lhs.isSymbol()) {
             String builtinName = lhs.getName() + "<-";
@@ -121,5 +121,4 @@ public abstract class AssignVariable extends ASTNode {
         }
         return lhs;
     }
-
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java
index 5d5881337524b9ae0da030f56c76a4c8149ff544..b5a811b4e77bd877dd4f799fbeb90fe35dd8333b 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/BinaryOperation.java
@@ -14,12 +14,12 @@ import java.util.*;
 
 import com.oracle.truffle.api.source.*;
 
-public abstract class BinaryOperation extends Operation {
+public final class BinaryOperation extends Operation {
 
     private final ASTNode rhs;
 
-    protected BinaryOperation(SourceSection source, ASTNode left, ASTNode right) {
-        super(source, left);
+    private BinaryOperation(SourceSection source, Operator op, ASTNode left, ASTNode right) {
+        super(source, op, left);
         this.rhs = right;
     }
 
@@ -27,98 +27,36 @@ public abstract class BinaryOperation extends Operation {
         return rhs;
     }
 
+    @Override
+    public <R> R accept(Visitor<R> v) {
+        return v.visit(this);
+    }
+
     @Override
     public <R> List<R> visitAll(Visitor<R> v) {
         return Arrays.asList(getLHS().accept(v), getRHS().accept(v));
     }
 
-    public static ASTNode create(SourceSection src, BinaryOperator op, ASTNode left, ASTNode right) {
-        switch (op) {
-            case ADD:
-                return new Add(src, left, right);
-            case SUB:
-                return new Sub(src, left, right);
-            case MULT:
-                return new Mult(src, left, right);
-            case DIV:
-                return new Div(src, left, right);
-            case MOD:
-                return new Mod(src, left, right);
-            case POW:
-                return new Pow(src, left, right);
-
-            case OR:
-                return new Or(src, left, right);
-            case AND:
-                return new And(src, left, right);
-            case ELEMENTWISEOR:
-                return new ElementwiseOr(src, left, right);
-            case ELEMENTWISEAND:
-                return new ElementwiseAnd(src, left, right);
-
-            case EQ:
-                return new EQ(src, left, right);
-            case GE:
-                return new GE(src, left, right);
-            case GT:
-                return new GT(src, left, right);
-            case NE:
-                return new NE(src, left, right);
-            case LE:
-                return new LE(src, left, right);
-            case LT:
-                return new LT(src, left, right);
-            case COLON:
-                return new Colon(src, left, right);
-        }
-        throw new Error("No node implemented for: '" + op + "' (" + left + ", " + right + ")");
+    public static ASTNode create(SourceSection src, Operator op, ASTNode left, ASTNode right) {
+        return new BinaryOperation(src, op, left, right);
     }
 
     public static ASTNode create(SourceSection src, String op, ASTNode left, ASTNode right) {
-        if ("%o%".equals(op)) {
-            return new OuterMult(src, left, right);
-        }
-        if ("%*%".equals(op)) {
-            return new MatMult(src, left, right);
-        }
-        if ("%/%".equals(op)) {
-            return new IntegerDiv(src, left, right);
-        }
-        if ("%in%".equals(op)) {
-            return new In(src, left, right);
+        switch (op) {
+            case "%o%":
+                return new BinaryOperation(src, Operator.OUTER_MULT, left, right);
+            case "%*%":
+                return new BinaryOperation(src, Operator.MATMULT, left, right);
+            case "%/%":
+                return new BinaryOperation(src, Operator.INTEGER_DIV, left, right);
+            case "%in%":
+                return new BinaryOperation(src, Operator.IN, left, right);
+            default:
+                // user-defined operator
+                List<ArgNode> args = new ArrayList<>();
+                args.add(ArgNode.create(left.getSource(), null, left));
+                args.add(ArgNode.create(right.getSource(), null, right));
+                return new FunctionCall(src, op, args);
         }
-        // user-defined operator
-        List<ArgNode> args = new ArrayList<>();
-        args.add(ArgNode.create(left.getSource(), null, left));
-        args.add(ArgNode.create(right.getSource(), null, right));
-        return new FunctionCall(src, op, args);
-    }
-
-    public enum BinaryOperator {
-        ASSIGN,
-        SUPER_ASSIGN,
-
-        ADD,
-        SUB,
-        MULT,
-        DIV,
-        MOD,
-
-        POW,
-
-        MODEL,
-        COLON,
-
-        GE,
-        GT,
-        LE,
-        LT,
-        EQ,
-        NE,
-
-        OR,
-        ELEMENTWISEOR,
-        AND,
-        ELEMENTWISEAND,
     }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Colon.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Colon.java
deleted file mode 100644
index 2b8037e10524c19fd46d3a2fe0f521aea5c92d5f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Colon.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName(":")
-@Precedence(Operation.COLON_PRECEDENCE)
-public class Colon extends BinaryOperation {
-
-    public Colon(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java
index 7d991ec1b3472cfcf7400e1bc4e24221ace6299e..40f40c1a8815808e9061d7fe1e0e485c86ca0f4f 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Constant.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -15,16 +15,15 @@ import java.util.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.r.runtime.*;
 
-@Precedence(Precedence.MAX)
 public final class Constant extends ASTNode {
 
     public enum ConstantType {
+// FORMULA,
         DOUBLE,
         COMPLEX,
         INT,
         BOOL,
         STRING,
-        FORMULA,
         NULL
     }
 
@@ -45,6 +44,11 @@ public final class Constant extends ASTNode {
         return type;
     }
 
+    @Override
+    public int getPrecedence() {
+        return Operation.MAX_PRECEDENCE;
+    }
+
     public String prettyValue() {
         return Arrays.toString(values);
     }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Div.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Div.java
deleted file mode 100644
index 275bac12d2b94ce0706e3fc7826832d664dd47cd..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Div.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("/")
-@Precedence(Operation.MULT_PRECEDENCE)
-public class Div extends BinaryOperation {
-
-    public Div(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/EQ.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/EQ.java
deleted file mode 100644
index dcd6c3be4d1cfe9198a3c80c6d8ea89c853b18c7..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/EQ.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("==")
-@Precedence(Operation.EQ_PRECEDENCE)
-public class EQ extends BinaryOperation {
-
-    public EQ(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ElementwiseAnd.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ElementwiseAnd.java
deleted file mode 100644
index 81a4d3913982e85acdcac047bd753810858965ea..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ElementwiseAnd.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("&")
-@Precedence(Operation.AND_PRECEDENCE)
-public class ElementwiseAnd extends BinaryOperation {
-
-    public ElementwiseAnd(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ElementwiseOr.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ElementwiseOr.java
deleted file mode 100644
index 4dca6a4bb940a7bb6724b8ae94ce9d5aff3e3859..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/ElementwiseOr.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("|")
-@Precedence(Operation.OR_PRECEDENCE)
-public class ElementwiseOr extends BinaryOperation {
-
-    public ElementwiseOr(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/For.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/For.java
index 11d31b521b12a74d16488f88a4313718589d4cae..66f976c846b35cb3d42a3b345015d175d50c2ffc 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/For.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/For.java
@@ -19,7 +19,7 @@ public class For extends Loop {
     private final String variable;
     private final ASTNode range;
 
-    public For(SourceSection source, String variable, ASTNode range, ASTNode body) {
+    For(SourceSection source, String variable, ASTNode range, ASTNode body) {
         super(source, body);
         this.variable = variable;
         this.range = range;
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
index 1b51ed3cbadca48e04e4609d7733dc3c6289b758..8882bdc162e2928ff1ff4a45354c8410abc11f5a 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/FunctionCall.java
@@ -28,11 +28,11 @@ public class FunctionCall extends Call {
         this.isReplacement = isReplacement;
     }
 
-    public FunctionCall(SourceSection src, String funName, List<ArgNode> arguments) {
+    FunctionCall(SourceSection src, String funName, List<ArgNode> arguments) {
         this(src, funName, arguments, false);
     }
 
-    public FunctionCall(SourceSection src, FunctionCall funCall, List<ArgNode> arguments) {
+    FunctionCall(SourceSection src, FunctionCall funCall, List<ArgNode> arguments) {
         this(src, funCall, arguments, false);
     }
 
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/GE.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/GE.java
deleted file mode 100644
index 2df08dfd3fe6873b001626d4ae50d89f0eb1e95f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/GE.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName(">=")
-@Precedence(Operation.COMPARE_PRECEDENCE)
-public class GE extends BinaryOperation {
-
-    public GE(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/GT.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/GT.java
deleted file mode 100644
index 0f59f8f0cde8811c825063681ad4a146a5603955..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/GT.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName(">")
-@Precedence(Operation.COMPARE_PRECEDENCE)
-public class GT extends BinaryOperation {
-
-    public GT(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/In.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/In.java
deleted file mode 100644
index 9d817ede40da952a544898e5a70f589399f7ced9..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/In.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("%in%")
-@Precedence(Operation.IN_PRECEDENCE)
-public class In extends BinaryOperation {
-
-    public In(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/IntegerDiv.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/IntegerDiv.java
deleted file mode 100644
index 5ddc37427da0251c0546dae929acb92f97918e10..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/IntegerDiv.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("%/%")
-@Precedence(Operation.INTEGER_DIV_PRECEDENCE)
-public class IntegerDiv extends BinaryOperation {
-
-    public IntegerDiv(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/LE.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/LE.java
deleted file mode 100644
index 21a459002b9b1762dc1ce5abf902c6aeb0b8e50f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/LE.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("<=")
-@Precedence(Operation.COMPARE_PRECEDENCE)
-public class LE extends BinaryOperation {
-
-    public LE(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/LT.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/LT.java
deleted file mode 100644
index 4aec919d74d92a0f6f38af88b4de5737a01df79e..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/LT.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("<")
-@Precedence(Operation.COMPARE_PRECEDENCE)
-public class LT extends BinaryOperation {
-
-    public LT(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/MatMult.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/MatMult.java
deleted file mode 100644
index c05dc2796bda03b2c28f2f9c2964022d7351c1a5..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/MatMult.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("%*%")
-@Precedence(Operation.MAT_MULT_PRECEDENCE)
-public class MatMult extends BinaryOperation {
-
-    public MatMult(SourceSection src, ASTNode l, ASTNode r) {
-        super(src, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Mod.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Mod.java
deleted file mode 100644
index d93e087e135ad020d664e08d30b7622dd290c990..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Mod.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("%%")
-@Precedence(Operation.MOD_PRECEDENCE)
-public class Mod extends BinaryOperation {
-
-    public Mod(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Mult.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Mult.java
deleted file mode 100644
index c572251bf20bef3b8adfe81103e30b3d88738242..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Mult.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("*")
-@Precedence(Operation.MULT_PRECEDENCE)
-public class Mult extends BinaryOperation {
-
-    public Mult(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/NE.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/NE.java
deleted file mode 100644
index 4d4bf377af575af834ccb0d4cfb166647bb4d87e..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/NE.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("!=")
-@Precedence(Operation.EQ_PRECEDENCE)
-public class NE extends BinaryOperation {
-
-    public NE(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/NodeVisitor.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/NodeVisitor.java
deleted file mode 100644
index 4e32474af40b4684253c993d7cf05d06ea49e5d8..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/NodeVisitor.java
+++ /dev/null
@@ -1,15 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-public interface NodeVisitor {
-    boolean visit(ASTNode node);
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Not.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Not.java
deleted file mode 100644
index 4f3b0f0cb4377c1af1924269cf5e8d6a5dfb3c48..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Not.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@Precedence(Operation.NOT_PRECEDENCE)
-@PrettyName("!")
-public class Not extends UnaryOperation {
-
-    public Not(SourceSection source, ASTNode operand) {
-        super(source, operand);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Operation.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Operation.java
index 0c05d315c6b0fd2351a976ddb76645a82ddc6f61..deee734faa5e97075057dee8958104cdf1b7b9d1 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Operation.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Operation.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -16,34 +16,103 @@ import com.oracle.truffle.api.source.*;
 
 public abstract class Operation extends ASTNode {
 
-    public static final int EQ_PRECEDENCE = 1;
-    public static final int OR_PRECEDENCE = EQ_PRECEDENCE + 1;
-    public static final int AND_PRECEDENCE = OR_PRECEDENCE + 1;
-    public static final int NOT_PRECEDENCE = AND_PRECEDENCE + 1;
-    public static final int COMPARE_PRECEDENCE = NOT_PRECEDENCE + 1;
+    static final int MIN_PRECEDENCE = 0;
+    static final int MAX_PRECEDENCE = 100;
 
-    public static final int ADD_PRECEDENCE = COMPARE_PRECEDENCE + 1;
-    public static final int SUB_PRECEDENCE = ADD_PRECEDENCE;
+    private static final int EQ_PRECEDENCE = 1;
+    private static final int OR_PRECEDENCE = EQ_PRECEDENCE + 1;
+    private static final int AND_PRECEDENCE = OR_PRECEDENCE + 1;
+    private static final int NOT_PRECEDENCE = AND_PRECEDENCE + 1;
+    private static final int COMPARE_PRECEDENCE = NOT_PRECEDENCE + 1;
 
-    public static final int MULT_PRECEDENCE = SUB_PRECEDENCE + 1;
+    private static final int ADD_PRECEDENCE = COMPARE_PRECEDENCE + 1;
+    private static final int SUB_PRECEDENCE = ADD_PRECEDENCE;
 
-    public static final int MAT_MULT_PRECEDENCE = MULT_PRECEDENCE + 1;
-    public static final int OUTER_MULT_PRECEDENCE = MAT_MULT_PRECEDENCE;
-    public static final int INTEGER_DIV_PRECEDENCE = MAT_MULT_PRECEDENCE;
-    public static final int IN_PRECEDENCE = MAT_MULT_PRECEDENCE;
-    public static final int MOD_PRECEDENCE = MAT_MULT_PRECEDENCE;
+    private static final int MULT_PRECEDENCE = SUB_PRECEDENCE + 1;
 
-    public static final int COLON_PRECEDENCE = MAT_MULT_PRECEDENCE + 1;
-    public static final int SIGN_PRECEDENCE = COLON_PRECEDENCE + 1;
-    public static final int POW_PRECEDENCE = SIGN_PRECEDENCE + 1;
+    private static final int MAT_MULT_PRECEDENCE = MULT_PRECEDENCE + 1;
+    private static final int OUTER_MULT_PRECEDENCE = MAT_MULT_PRECEDENCE;
+    private static final int INTEGER_DIV_PRECEDENCE = MAT_MULT_PRECEDENCE;
+    private static final int IN_PRECEDENCE = MAT_MULT_PRECEDENCE;
+    private static final int MOD_PRECEDENCE = MAT_MULT_PRECEDENCE;
+
+    private static final int COLON_PRECEDENCE = MAT_MULT_PRECEDENCE + 1;
+    private static final int SIGN_PRECEDENCE = COLON_PRECEDENCE + 1;
+    private static final int POW_PRECEDENCE = SIGN_PRECEDENCE + 1;
+
+    public enum Operator {
+        ADD("+", ADD_PRECEDENCE, false),
+        SUB("-", SUB_PRECEDENCE, false),
+        MULT("*", MULT_PRECEDENCE, false),
+        DIV("/", MULT_PRECEDENCE, false),
+        MOD("%%", MOD_PRECEDENCE, false),
+
+        POW("^", POW_PRECEDENCE, false),
+
+        COLON(":", COLON_PRECEDENCE, false),
+
+        GE(">=", COMPARE_PRECEDENCE, false),
+        GT(">", COMPARE_PRECEDENCE, false),
+        LE("<=", COMPARE_PRECEDENCE, false),
+        LT("<", COMPARE_PRECEDENCE, false),
+        EQ("==", EQ_PRECEDENCE, false),
+        NE("!=", EQ_PRECEDENCE, false),
+
+        OR("||", OR_PRECEDENCE, false),
+        ELEMENTWISEOR("|", OR_PRECEDENCE, false),
+        AND("&&", AND_PRECEDENCE, false),
+        ELEMENTWISEAND("&", AND_PRECEDENCE, false),
+
+        OUTER_MULT("%o%", OUTER_MULT_PRECEDENCE, false),
+        MATMULT("%*%", MAT_MULT_PRECEDENCE, false),
+        INTEGER_DIV("%/%", INTEGER_DIV_PRECEDENCE, false),
+        IN("%in%", IN_PRECEDENCE, false),
+
+        UNARY_PLUS("+", SIGN_PRECEDENCE, true),
+        UNARY_MINUS("-", SIGN_PRECEDENCE, true),
+        UNARY_NOT("!", NOT_PRECEDENCE, true);
+
+        private final String name;
+        private final int precedence;
+        private final boolean isUnary;
+
+        private Operator(String name, int precedence, boolean isUnary) {
+            this.name = name;
+            this.precedence = precedence;
+            this.isUnary = isUnary;
+        }
+
+        public String getName() {
+            return name;
+        }
+
+        public int getPrecedence() {
+            return precedence;
+        }
+
+        public boolean isUnary() {
+            return isUnary;
+        }
+    }
 
     private final ASTNode lhs;
+    private final Operator op;
 
-    protected Operation(SourceSection source, ASTNode left) {
+    protected Operation(SourceSection source, Operator op, ASTNode left) {
         super(source);
+        this.op = op;
         this.lhs = left;
     }
 
+    public Operator getOperator() {
+        return op;
+    }
+
+    @Override
+    public int getPrecedence() {
+        return op.getPrecedence();
+    }
+
     public ASTNode getLHS() {
         return lhs;
     }
@@ -52,10 +121,4 @@ public abstract class Operation extends ASTNode {
     public <R> List<R> visitAll(Visitor<R> v) {
         return Arrays.asList(getLHS().accept(v));
     }
-
-    public String getPrettyOperator() {
-        Class<?> clazz = getClass();
-        PrettyName op = clazz.getAnnotation(PrettyName.class);
-        return op == null ? clazz.getSimpleName() : op.value();
-    }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Or.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Or.java
deleted file mode 100644
index 5b482592b43547fbb2d31f55c33555e643a3218f..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Or.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("||")
-@Precedence(Operation.OR_PRECEDENCE)
-public class Or extends BinaryOperation {
-
-    public Or(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/OuterMult.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/OuterMult.java
deleted file mode 100644
index 42f33e2230cf4b4221966b6242d7ac1ced82a6ab..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/OuterMult.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("%o%")
-@Precedence(Operation.OUTER_MULT_PRECEDENCE)
-public class OuterMult extends BinaryOperation {
-
-    public OuterMult(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Pow.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Pow.java
deleted file mode 100644
index 487e38ebf09336ef48ac42598b9189b2b53d56ea..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Pow.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("^")
-@Precedence(Operation.POW_PRECEDENCE)
-public class Pow extends BinaryOperation {
-
-    public Pow(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Precedence.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Precedence.java
deleted file mode 100644
index b689deb9bd6b0248f7e27362f34ebbcf738f16e2..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Precedence.java
+++ /dev/null
@@ -1,22 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface Precedence {
-    int value() default 0;
-
-    int MIN = 0;
-    int MAX = Integer.MAX_VALUE - 100;
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/PrettyName.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/PrettyName.java
deleted file mode 100644
index 29c3d76811d91c6e112ec6554728f400957cf0ae..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/PrettyName.java
+++ /dev/null
@@ -1,19 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
-public @interface PrettyName {
-    String value();
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Repeat.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Repeat.java
index dabb6c4880a6cb37dfa8838c58ab2501834ed784..1f50f404b96d60f1801cef5058ff14e1583d2374 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Repeat.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Repeat.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -14,7 +14,7 @@ import com.oracle.truffle.api.source.*;
 
 public class Repeat extends Loop {
 
-    public Repeat(SourceSection source, ASTNode body) {
+    Repeat(SourceSection source, ASTNode body) {
         super(source, body);
     }
 
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Replacement.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Replacement.java
index 47ad92ad5471a15060dd4dd7c819de2866fff929..5abceb35a66dabf7f34d6f8b1f9ce16e460bb26e 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Replacement.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Replacement.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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 @@ public class Replacement extends AssignVariable {
 
     private final FunctionCall replacementFunctionCall;
 
-    public Replacement(SourceSection src, boolean isSuper, FunctionCall replacementFunctionCall, ASTNode rhs) {
+    Replacement(SourceSection src, boolean isSuper, FunctionCall replacementFunctionCall, ASTNode rhs) {
         super(src, isSuper, rhs);
         this.replacementFunctionCall = replacementFunctionCall;
     }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Sequence.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Sequence.java
index 81051210f3ac602591b09df386ae8d86c020aae6..351319791d13919ceaa97d40351840d0576ce29e 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Sequence.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Sequence.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -44,8 +44,4 @@ public final class Sequence extends ASTNode {
     public static ASTNode create(SourceSection src, ArrayList<ASTNode> exprs) {
         return new Sequence(src, exprs.toArray(new ASTNode[exprs.size()]));
     }
-
-    public static ASTNode create(SourceSection src, ASTNode[] exprs) {
-        return new Sequence(src, exprs);
-    }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessTempVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessTempVariable.java
index ef955a1f4c7fde4e94ed6df310bdae613e62f55a..69087ab077c5fb89ed35db0c3939ad5e0da97915 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessTempVariable.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessTempVariable.java
@@ -26,12 +26,11 @@ import java.util.*;
 
 import com.oracle.truffle.api.source.*;
 
-@Precedence(Precedence.MAX)
 public class SimpleAccessTempVariable extends AccessVariable {
 
     private final String tempSymbol;
 
-    public SimpleAccessTempVariable(SourceSection source, String tempSymbol) {
+    SimpleAccessTempVariable(SourceSection source, String tempSymbol) {
         super(source);
         this.tempSymbol = tempSymbol;
     }
@@ -40,6 +39,11 @@ public class SimpleAccessTempVariable extends AccessVariable {
         return tempSymbol;
     }
 
+    @Override
+    public int getPrecedence() {
+        return Operation.MAX_PRECEDENCE;
+    }
+
     @Override
     public <R> R accept(Visitor<R> v) {
         return v.visit(this);
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java
index a9603e133f156861a880ec43ba87ef725409953a..c95a38430b707a46fddbb9011037b02da8662d0d 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariable.java
@@ -14,13 +14,12 @@ import java.util.*;
 
 import com.oracle.truffle.api.source.*;
 
-@Precedence(Precedence.MAX)
 public class SimpleAccessVariable extends AccessVariable {
 
     private final String variable;
     private final boolean shouldCopyValue;
 
-    public SimpleAccessVariable(SourceSection source, String variable, boolean shouldCopyValue) {
+    SimpleAccessVariable(SourceSection source, String variable, boolean shouldCopyValue) {
         super(source);
         this.variable = variable;
         this.shouldCopyValue = shouldCopyValue;
@@ -30,6 +29,11 @@ public class SimpleAccessVariable extends AccessVariable {
         return variable;
     }
 
+    @Override
+    public int getPrecedence() {
+        return Operation.MAX_PRECEDENCE;
+    }
+
     public boolean shouldCopyValue() {
         return shouldCopyValue;
     }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariadicComponent.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariadicComponent.java
index 3aaa896aa7d48d43df82ce9a582acb6cd83c143d..f3ef5713b3f5516198958dcdcdcb3f3299150f29 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariadicComponent.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAccessVariadicComponent.java
@@ -31,7 +31,7 @@ public class SimpleAccessVariadicComponent extends AccessVariable {
     private final int index;
     private final String name;
 
-    public SimpleAccessVariadicComponent(SourceSection source, String name) {
+    SimpleAccessVariadicComponent(SourceSection source, String name) {
         super(source);
         index = getVariadicComponentIndex(name);
         this.name = name;
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java
index 07007ea53b15b88f915fd3075e55184f104fe7b3..cffd6aa28cf9ef8cb0b8e0657623bd93e97928b2 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/SimpleAssignVariable.java
@@ -16,7 +16,7 @@ public class SimpleAssignVariable extends AssignVariable {
 
     private final String variable;
 
-    public SimpleAssignVariable(SourceSection source, boolean isSuper, String variable, ASTNode rhs) {
+    SimpleAssignVariable(SourceSection source, boolean isSuper, String variable, ASTNode rhs) {
         super(source, isSuper, rhs);
         this.variable = variable;
     }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Sub.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Sub.java
deleted file mode 100644
index 3ba54fc5246809ef1a4f2fdbd006674f808466bc..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Sub.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@PrettyName("-")
-@Precedence(Operation.SUB_PRECEDENCE)
-public class Sub extends BinaryOperation {
-
-    public Sub(SourceSection source, ASTNode l, ASTNode r) {
-        super(source, l, r);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryMinus.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryMinus.java
deleted file mode 100644
index 057d2c6ff1605ae867ac0d9560f083e36d26d287..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryMinus.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@Precedence(Operation.SIGN_PRECEDENCE)
-@PrettyName("-")
-public class UnaryMinus extends UnaryOperation {
-
-    public UnaryMinus(SourceSection source, ASTNode operand) {
-        super(source, operand);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryOperation.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryOperation.java
index 298360f67f8427dfa96ab9386bc9073e1839e194..b7d3624b4f8497a45f8af41ec093e439c5b07ad8 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryOperation.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryOperation.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -12,28 +12,19 @@ package com.oracle.truffle.r.parser.ast;
 
 import com.oracle.truffle.api.source.*;
 
-public abstract class UnaryOperation extends Operation {
+public final class UnaryOperation extends Operation {
 
-    public UnaryOperation(SourceSection source, ASTNode op) {
-        super(source, op);
+    private UnaryOperation(SourceSection source, Operator op, ASTNode operand) {
+        super(source, op, operand);
     }
 
-    public static ASTNode create(SourceSection source, UnaryOperator op, ASTNode operand) {
-        switch (op) {
-            case PLUS:
-                return new UnaryPlus(source, operand);
-            case MINUS:
-                return new UnaryMinus(source, operand);
-            case NOT:
-                return new Not(source, operand);
-        }
-        throw new Error("No node implemented for: '" + op + "' (" + operand + ")");
+    public static ASTNode create(SourceSection source, Operator op, ASTNode operand) {
+        assert op.isUnary();
+        return new UnaryOperation(source, op, operand);
     }
 
-    public enum UnaryOperator {
-        REPEAT,
-        PLUS,
-        MINUS,
-        NOT
+    @Override
+    public <R> R accept(Visitor<R> v) {
+        return v.visit(this);
     }
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryPlus.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryPlus.java
deleted file mode 100644
index fc1f3371a9f11e95e7b57fc3d3dde13da4a6f062..0000000000000000000000000000000000000000
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UnaryPlus.java
+++ /dev/null
@@ -1,27 +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) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
- *
- * All rights reserved.
- */
-package com.oracle.truffle.r.parser.ast;
-
-import com.oracle.truffle.api.source.*;
-
-@Precedence(Operation.SIGN_PRECEDENCE)
-@PrettyName("+")
-public class UnaryPlus extends UnaryOperation {
-
-    public UnaryPlus(SourceSection source, ASTNode operand) {
-        super(source, operand);
-    }
-
-    @Override
-    public <R> R accept(Visitor<R> v) {
-        return v.visit(this);
-    }
-}
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java
index 9e8c101fca8f7dfd012534f582a7c6681b637668..e0b38df241c932898fd5d49a081bbfb78e69f22b 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateField.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -23,7 +23,7 @@ public class UpdateField extends ASTNode {
     private final ASTNode rhs;
     private final boolean isSuper;
 
-    public UpdateField(SourceSection src, boolean isSuper, FieldAccess vector, ASTNode rhs) {
+    UpdateField(SourceSection src, boolean isSuper, FieldAccess vector, ASTNode rhs) {
         super(src);
         this.vector = vector;
         this.rhs = rhs;
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java
index 655221730ab856e67aaa8afa3b374a08617a3065..a38bc4524c6ca2ce32ee1e87e0b5e87c039b0378 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/UpdateVector.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -18,7 +18,7 @@ public class UpdateVector extends ASTNode {
     private final ASTNode rhs;
     private final boolean isSuper;
 
-    public UpdateVector(boolean isSuper, AccessVector vector, ASTNode rhs) {
+    UpdateVector(boolean isSuper, AccessVector vector, ASTNode rhs) {
         super(null);
         this.vector = vector;
         this.rhs = rhs;
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java
index f1e0d3a61349ecad5638f8d72e5a6090bf40c0e1..90bb75ea767129310f9eaed68e6ee93285be2d9f 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/Visitor.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -26,53 +26,9 @@ public interface Visitor<R> {
 
     R visit(Next n);
 
-    R visit(EQ eq);
+    R visit(BinaryOperation op);
 
-    R visit(NE ne);
-
-    R visit(LE le);
-
-    R visit(GE ge);
-
-    R visit(LT lt);
-
-    R visit(GT gt);
-
-    R visit(Mult mult);
-
-    R visit(MatMult mult);
-
-    R visit(OuterMult mult);
-
-    R visit(IntegerDiv div);
-
-    R visit(In in);
-
-    R visit(Mod mod);
-
-    R visit(Pow pow);
-
-    R visit(Div div);
-
-    R visit(Add add);
-
-    R visit(Sub sub);
-
-    R visit(Colon col);
-
-    R visit(And and);
-
-    R visit(ElementwiseAnd and);
-
-    R visit(Or or);
-
-    R visit(ElementwiseOr or);
-
-    R visit(Not n);
-
-    R visit(UnaryMinus m);
-
-    R visit(UnaryPlus m);
+    R visit(UnaryOperation op);
 
     R visit(Constant constant);
 
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/While.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/While.java
index a42da7657e04a2d9f24f37bf48c7672b4b210c34..3466e2e02f24af37f5d037e728d0e2a1f5d092e6 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/While.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/ast/While.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -18,7 +18,7 @@ public class While extends Loop {
 
     private final ASTNode condition;
 
-    public While(SourceSection source, ASTNode condition, ASTNode expression) {
+    While(SourceSection source, ASTNode condition, ASTNode expression) {
         super(source, expression);
         this.condition = condition;
     }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/BasicVisitor.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/BasicVisitor.java
index 26ba12bc95e1f363e94ea4225177b6a85ca09166..a16892eaea556e41f48938b1d99d73fbfe01843f 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/BasicVisitor.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/BasicVisitor.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2012-2014, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -29,37 +29,29 @@ public class BasicVisitor<R> implements Visitor<R> {
         return visit((ASTNode) n);
     }
 
-    public R visit(Loop n) {
-        return visit((ASTNode) n);
-    }
-
     @Override
     public R visit(Repeat n) {
-        return visit((Loop) n);
+        return visit((ASTNode) n);
     }
 
     @Override
     public R visit(While n) {
-        return visit((Loop) n);
+        return visit((ASTNode) n);
     }
 
     @Override
     public R visit(For n) {
-        return visit((Loop) n);
-    }
-
-    public R visit(ControlStatement n) {
         return visit((ASTNode) n);
     }
 
     @Override
     public R visit(Next n) {
-        return visit((ControlStatement) n);
+        return visit((ASTNode) n);
     }
 
     @Override
     public R visit(Break n) {
-        return visit((ControlStatement) n);
+        return visit((ASTNode) n);
     }
 
     public R visit(Operation op) {
@@ -71,129 +63,10 @@ public class BasicVisitor<R> implements Visitor<R> {
     }
 
     @Override
-    public R visit(EQ op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(NE op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(LE op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(GE op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(LT op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(GT op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(Add op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(Sub op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(Mult op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(MatMult op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(OuterMult op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(IntegerDiv op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(In op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(Mod op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(Pow op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(Div op) {
-        return visit((BinaryOperation) op);
-    }
-
-    @Override
-    public R visit(Colon col) {
-        return visit((BinaryOperation) col);
-    }
-
-    @Override
-    public R visit(And and) {
-        return visit((BinaryOperation) and);
-    }
-
-    @Override
-    public R visit(ElementwiseAnd and) {
-        return visit((BinaryOperation) and);
-    }
-
-    @Override
-    public R visit(Or or) {
-        return visit((BinaryOperation) or);
-    }
-
-    @Override
-    public R visit(ElementwiseOr or) {
-        return visit((BinaryOperation) or);
-    }
-
     public R visit(UnaryOperation op) {
         return visit((ASTNode) op);
     }
 
-    @Override
-    public R visit(Not op) {
-        return visit((UnaryOperation) op);
-    }
-
-    @Override
-    public R visit(UnaryMinus op) {
-        return visit((UnaryOperation) op);
-    }
-
-    @Override
-    public R visit(UnaryPlus op) {
-        return visit((UnaryOperation) op);
-    }
-
     @Override
     public R visit(Constant c) {
         return visit((ASTNode) c);
@@ -267,5 +140,4 @@ public class BasicVisitor<R> implements Visitor<R> {
     public R visit(Formula n) {
         return visit((ASTNode) n);
     }
-
 }
diff --git a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/PrettyPrinter.java b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/PrettyPrinter.java
index 01f4c7d230b584b5508acb67bd10b2b257825322..ed5663981d36a0c88b107930b70079afd12836f1 100644
--- a/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/PrettyPrinter.java
+++ b/com.oracle.truffle.r.parser/src/com/oracle/truffle/r/parser/tools/PrettyPrinter.java
@@ -17,22 +17,16 @@ import com.oracle.truffle.r.parser.ast.*;
 
 public class PrettyPrinter extends BasicVisitor<Void> {
 
-    public static final boolean PARENTHESIS = false;
+    private static final boolean PARENTHESIS = false;
 
     private int level = 0;
     private final PrintStream out;
     private final StringBuilder buff = new StringBuilder();
-    private static final PrettyPrinter pp = getStringPrettyPrinter();
 
     public PrettyPrinter(PrintStream stream) {
         out = stream;
     }
 
-    public static String prettyPrint(ASTNode n) {
-        pp.print(n);
-        return pp.toString();
-    }
-
     public void print(ASTNode n) {
         n.accept(this);
         flush();
@@ -43,19 +37,6 @@ public class PrettyPrinter extends BasicVisitor<Void> {
         println("");
     }
 
-    private static PrettyPrinter getStringPrettyPrinter() {
-        final ByteArrayOutputStream os = new ByteArrayOutputStream();
-        return new PrettyPrinter(new PrintStream(os)) {
-
-            @Override
-            public String toString() {
-                String str = os.toString();
-                os.reset();
-                return str;
-            }
-        };
-    }
-
     private void inc() {
         level++;
     }
@@ -167,7 +148,7 @@ public class PrettyPrinter extends BasicVisitor<Void> {
             left.accept(this);
         }
         print(" ");
-        print(op.getPrettyOperator());
+        print(op.getOperator().getName());
         print(" ");
         if (right.getPrecedence() < precedence && !PARENTHESIS) { // FIXME should be <= if left
             // associative
@@ -188,7 +169,7 @@ public class PrettyPrinter extends BasicVisitor<Void> {
         if (PARENTHESIS) {
             print("(");
         }
-        print(op.getPrettyOperator());
+        print(op.getOperator().getName());
         op.getLHS().accept(this);
         if (PARENTHESIS) {
             print(")");
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 09fb909ea4ae19e3db005fa06b0e6f9499634004..58419b2db1919959a032e6c3659e7b189f4351d4 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
@@ -39,7 +39,7 @@ public final class ArgumentsSignature implements Iterable<String> {
     public static final int NO_VARARG = -1;
 
     @CompilationFinal private static final ArgumentsSignature[] EMPTY_SIGNATURES = new ArgumentsSignature[32];
-    public static final ArgumentsSignature VARARG_SIGNATURE = get(new String[]{VARARG_NAME});
+    public static final ArgumentsSignature VARARG_SIGNATURE = get(VARARG_NAME);
 
     static {
         for (int i = 0; i < EMPTY_SIGNATURES.length; i++) {
@@ -48,7 +48,7 @@ public final class ArgumentsSignature implements Iterable<String> {
     }
 
     @TruffleBoundary
-    public static ArgumentsSignature get(String[] names) {
+    public static ArgumentsSignature get(String... names) {
         assert names != null;
         ArgumentsSignature newSignature = new ArgumentsSignature(names);
         ArgumentsSignature oldSignature = signatures.putIfAbsent(newSignature, newSignature);
@@ -110,14 +110,6 @@ public final class ArgumentsSignature implements Iterable<String> {
         return nonNullCount;
     }
 
-    public boolean isVarArg(int index) {
-        return isVarArg[index];
-    }
-
-    public boolean isVarArgGetter(int index) {
-        return isVarArgGetter[index];
-    }
-
     public int getVarArgIndex() {
         assert varArgIndexes.length <= 1 : "cannot ask for _the_ vararg index if there are multiple varargs";
         return varArgIndexes.length == 0 ? NO_VARARG : varArgIndexes[0];
@@ -173,4 +165,40 @@ public final class ArgumentsSignature implements Iterable<String> {
     public String toString() {
         return "Signature " + Arrays.toString(names);
     }
+
+    /*
+     * Utility functions
+     */
+
+    public static long[] flattenIndexes(ArgumentsSignature[] varArgSignatures, int argListSize) {
+        long[] preparePermutation = new long[argListSize];
+        int index = 0;
+        for (int i = 0; i < varArgSignatures.length; i++) {
+            ArgumentsSignature varArgSignature = varArgSignatures[i];
+            if (varArgSignature != null) {
+                for (int j = 0; j < varArgSignature.getLength(); j++) {
+                    preparePermutation[index++] = -((((long) i) << 32) + j);
+                }
+            } else {
+                preparePermutation[index++] = i;
+            }
+        }
+        return preparePermutation;
+    }
+
+    public static ArgumentsSignature flattenNames(ArgumentsSignature signature, ArgumentsSignature[] varArgSignatures, int argListSize) {
+        String[] argNames = new String[argListSize];
+        int index = 0;
+        for (int i = 0; i < varArgSignatures.length; i++) {
+            ArgumentsSignature varArgSignature = varArgSignatures[i];
+            if (varArgSignature != null) {
+                for (int j = 0; j < varArgSignature.getLength(); j++) {
+                    argNames[index++] = varArgSignature.getName(j);
+                }
+            } else {
+                argNames[index++] = signature.getName(i);
+            }
+        }
+        return ArgumentsSignature.get(argNames);
+    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinComment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/HasSignature.java
similarity index 79%
rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinComment.java
rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/HasSignature.java
index 21978b4d6b5a2710d4461b6c3342f635d273dd63..ae2c743fbe29e0bc890841abc4a6f4896f9c0096 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinComment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/HasSignature.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,13 +20,8 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
-package com.oracle.truffle.r.nodes.builtin;
-
-import java.lang.annotation.*;
-
-@Retention(RetentionPolicy.RUNTIME)
-public @interface RBuiltinComment {
-
-    String value();
+package com.oracle.truffle.r.runtime;
 
+public interface HasSignature {
+    ArgumentsSignature getSignature();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
index 347a6b226870d98b477ee35c71a2cc9a1b8a89c0..741b265b64df51bebd5ae5ad5a063366a95c1319 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java
@@ -25,7 +25,7 @@ package com.oracle.truffle.r.runtime;
 import java.util.*;
 
 import com.oracle.truffle.api.*;
-import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
@@ -139,10 +139,15 @@ public final class RArguments {
         return INDEX_ARGUMENTS + (int) args[INDEX_N_ARGS];
     }
 
+    private static ArgumentsSignature getSignature(RFunction function) {
+        return ((HasSignature) function.getRootNode()).getSignature();
+    }
+
     private static void createHelper(Object[] a, REnvironment env, RFunction functionObj, SourceSection callSrc, MaterializedFrame callerFrame, int depth, MaterializedFrame enclosingFrame,
                     Object[] evaluatedArgs, ArgumentsSignature signature) {
         assert evaluatedArgs != null && signature != null : evaluatedArgs + " " + signature;
         assert evaluatedArgs.length == signature.getLength() : Arrays.toString(evaluatedArgs) + " " + signature;
+        assert signature == getSignature(functionObj) : signature + " vs. " + getSignature(functionObj);
         a[INDEX_ENVIRONMENT] = env;
         a[INDEX_FUNCTION] = functionObj;
         a[INDEX_CALL_SRC] = callSrc;
@@ -188,10 +193,6 @@ public final class RArguments {
         return a;
     }
 
-    public static Object[] create(RFunction functionObj, SourceSection callSrc, MaterializedFrame callerFrame, int depth) {
-        return create(functionObj, callSrc, callerFrame, depth, EMPTY_OBJECT_ARRAY);
-    }
-
     public static Object[] create(RFunction functionObj, SourceSection callSrc, MaterializedFrame callerFrame, int depth, Object[] evaluatedArgs) {
         if (functionObj != null) {
             return create(null, functionObj, callSrc, callerFrame, depth, functionObj.getEnclosingFrame(), evaluatedArgs, ArgumentsSignature.empty(evaluatedArgs.length));
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RGroupGenerics.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RGroupGenerics.java
index f71118676e27b3239ea632b678b5c9d1a0052ea5..cb31c420d522c7d92e2b7c92317b29adfe42d6bd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RGroupGenerics.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RGroupGenerics.java
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -14,8 +14,6 @@ import java.util.*;
 
 public class RGroupGenerics {
 
-    public static final String RDotGroup = ".Group";
-
     public static final String GROUP_MATH = "Math";
 
     public static final String GROUP_OPS = "Ops";
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 a2c2b3a13a046369a364825f14a9b25182ea6bcb..b7f99f862b102855cd9f6496268adf4e72c95cb7 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
@@ -50,6 +50,11 @@ public final class RInternalError extends Error {
         throw new RInternalError("not implemented");
     }
 
+    public static RuntimeException unimplemented(String message) {
+        CompilerDirectives.transferToInterpreter();
+        throw new RInternalError("not implemented: %s", message);
+    }
+
     public static RuntimeException shouldNotReachHere() {
         CompilerDirectives.transferToInterpreter();
         throw new RInternalError("should not reach here");
@@ -60,9 +65,9 @@ public final class RInternalError extends Error {
         throw new RInternalError(cause, "should not reach here");
     }
 
-    public static RuntimeException shouldNotReachHere(String msg) {
+    public static RuntimeException shouldNotReachHere(String message) {
         CompilerDirectives.transferToInterpreter();
-        throw new RInternalError("should not reach here: %s", msg);
+        throw new RInternalError("should not reach here: %s", message);
     }
 
     static void reportError(Throwable t, SourceSection source) {
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 da3ddf0bbf329d8ea8bae94a93bd7ea4a688d9a3..2afebc9c27dee0ce7fd2c9af301e7942ddf432ba 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
@@ -86,7 +86,6 @@ public class RRuntime {
     public static final String NAMES_ATTR_EMPTY_VALUE = "";
 
     public static final String LEVELS_ATTR_KEY = "levels";
-    public static final String LEVELS_ATTR_EMPTY_VALUE = "";
 
     public static final String NA_HEADER = "<NA>";
 
@@ -95,7 +94,6 @@ public class RRuntime {
     public static final String DIMNAMES_LIST_ELEMENT_NAME_PREFIX = "$dimnames";
 
     public static final String CLASS_ATTR_KEY = "class";
-    public static final String FACTOR_ATTR_KEY = "factor";
     public static final String PREVIOUS_ATTR_KEY = "previous";
     public static final String ROWNAMES_ATTR_KEY = "row.names";
 
@@ -104,10 +102,6 @@ public class RRuntime {
 
     public static final String CLASS_ORDERED = "ordered";
 
-    public static final String WHICH = "which";
-
-    public static final String WHAT = "what";
-
     public static final int LEN_METHOD_NAME = 512;
 
     public static final String RDotGeneric = ".Generic";
@@ -126,8 +120,6 @@ public class RRuntime {
 
     public static final String SYSTEM_DATE_FORMAT = "EEE MMM dd HH:mm:ss yyyy";
 
-    public static final String DROP_DIM_ARG_NAME = "drop";
-
     public static final String NULL = "NULL";
 
     @CompilationFinal private static final String[] numberStringCache = new String[4096];
@@ -146,7 +138,7 @@ public class RRuntime {
      */
     public static VirtualFrame createNonFunctionFrame() {
         FrameDescriptor frameDescriptor = new FrameDescriptor();
-        FrameSlotChangeMonitor.initializeFrameDescriptor(frameDescriptor, true);
+        FrameSlotChangeMonitor.initializeNonFunctionFrameDescriptor(frameDescriptor, false);
         return Truffle.getRuntime().createVirtualFrame(RArguments.createUnitialized(), frameDescriptor);
     }
 
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 82e66c1d6b91433ab04a7a74048acdc6951e426c..b3ce72817dd42a1c8e94263de351690562758ee3 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
@@ -11,7 +11,7 @@
  */
 package com.oracle.truffle.r.runtime;
 
-import com.oracle.truffle.api.CompilerDirectives.*;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 
 public enum RType {
     Any("any"),
@@ -72,4 +72,5 @@ public enum RType {
         }
         return null;
     }
+
 }
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 f7bac06a16b33ed71309ea939cc631d18ef017f5..b3901d82dc73b529c2f9b60292e5edfb23f267d9 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
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime;
 
 import java.io.*;
 import java.net.*;
-import java.nio.charset.*;
 import java.util.*;
 
 import com.oracle.truffle.api.*;
@@ -224,15 +223,6 @@ public final class Utils {
         }
     }
 
-    private static volatile Charset UTF8;
-
-    public static Charset getUTF8() {
-        if (UTF8 == null) {
-            UTF8 = Charset.forName("UTF-8");
-        }
-        return UTF8;
-    }
-
     /**
      * Retrieve a frame from the call stack. N.B. This method cannot not be used to get the current
      * frame, use {@link #getActualCurrentFrame()} for that.
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
index cc96688c2cf5f891422d9c208a2b8716a1e2787d..f23093c1c3a84ea8687b0a04aa06eb7d97c8d3e2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/RConnection.java
@@ -27,6 +27,7 @@ import java.nio.*;
 import java.util.*;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 import com.oracle.truffle.r.runtime.data.model.*;
 
@@ -35,12 +36,16 @@ import com.oracle.truffle.r.runtime.data.model.*;
  *
  * TODO Refactor the pushBack code into ConnectionsSupport
  */
-public abstract class RConnection implements RClassHierarchy, AutoCloseable {
+public abstract class RConnection implements RClassHierarchy, RTypedValue, AutoCloseable {
 
     private LinkedList<String> pushBack;
 
     public abstract String[] readLinesInternal(int n) throws IOException;
 
+    public RType getRType() {
+        return RType.Integer;
+    }
+
     private String readOneLineWithPushBack(String[] res, int ind) {
         String s = pushBack.pollLast();
         if (s == null) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
index cb57a43006febe8596f07338c8bfd239bce9778d..9089e2704268a44e4f8d410e5b760c414f695056 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,5 +39,4 @@ public abstract class RAttributeStorage {
         }
         return attributes;
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributes.java
index 3bb9053d8762aba754a1147951339e6aab66f608..e8e749d85b5f6458404be3e90c297c64af683726 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributes.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributes.java
@@ -69,7 +69,7 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> {
 
     private static final ConditionProfile statsProfile = ConditionProfile.createBinaryProfile();
 
-    public static RAttributes create() {
+    static RAttributes create() {
         return new RAttributes();
     }
 
@@ -229,7 +229,7 @@ public final class RAttributes implements Iterable<RAttributes.RAttribute> {
      * Collects data on the maximum size of the attribute set. So only interested in adding not
      * removing attributes.
      */
-    public static class PerfHandler implements RPerfStats.Handler {
+    private static class PerfHandler implements RPerfStats.Handler {
         private static final RPerfStats.Histogram hist = new RPerfStats.Histogram(5);
 
         @TruffleBoundary
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBounded.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBounded.java
index 1210c7d4de6b7b89f29da1bfb7520208705d2aae..5d799553f012c90654a97796b5e83b158af88e33 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBounded.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RBounded.java
@@ -30,10 +30,6 @@ public abstract class RBounded {
 
     public abstract int getLength();
 
-    public boolean isInBounds(int position) {
-        return position >= 1 && position <= getLength();
-    }
-
     public final void verifyDimensions(int[] newDimensions, SourceSection sourceSection) {
         int length = 1;
         for (int i = 0; i < newDimensions.length; i++) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
index 9dab516a13beabbd8fafc91712a320d2dc1beaae..53fdc1ce86df02a4aa5984dfd27b00101ed69092 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java
@@ -38,6 +38,11 @@ public final class RComplex extends RScalar {
         this.imaginaryPart = imaginaryPart;
     }
 
+    @Override
+    public RType getRType() {
+        return RType.Complex;
+    }
+
     public double getRealPart() {
         return realPart;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
index 99adefd80a852839177f50f8650bfed021527fc4..5b9270feed0e9fd0a0b008eb122c7e968a69dd25 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
@@ -127,11 +127,6 @@ public final class RComplexVector extends RVector implements RAbstractComplexVec
         return RDataFactory.createComplexVector(data, isComplete(), newDimensions);
     }
 
-    public RComplexVector removeLast() {
-        assert getLength() > 0;
-        return RDataFactory.createComplexVector(Arrays.copyOf(data, getLength() - 1), isComplete());
-    }
-
     @Override
     protected String getDataAtAsString(int index) {
         return getDataAt(index).toString();
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 b5969622a3a2c3366bb49836190ec3448ca9680b..736869292a76dd7af12516555a210bdc1d64a10d 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
@@ -337,26 +337,6 @@ public final class RDataFactory {
         return traceDataCreated(new RFactor(vector, ordered));
     }
 
-    public static RVector createObjectVector(Object[] data, boolean completeVector) {
-        if (data.length < 1) {
-            return null;
-        }
-        if (data[0] instanceof Double) {
-            double[] result = new double[data.length];
-            for (int i = 0; i < data.length; ++i) {
-                result[i] = (double) data[i];
-            }
-            return RDataFactory.createDoubleVector(result, completeVector);
-        } else if (data[0] instanceof Byte) {
-            byte[] result = new byte[data.length];
-            for (int i = 0; i < data.length; ++i) {
-                result[i] = (byte) data[i];
-            }
-            return RDataFactory.createLogicalVector(result, completeVector);
-        }
-        throw Utils.fail("unimplemented object vector type: " + data[0].getClass().getSimpleName());
-    }
-
     public static RSymbol createSymbol(String name) {
         return traceDataCreated(new RSymbol(name));
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFrame.java
index 9f6e4a3819af8baa27c8418e773702f75b01d0db..5b83186b0534f96d2a776ba19cb6911c6a2e4cc3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFrame.java
@@ -33,6 +33,10 @@ public final class RDataFrame implements RShareable, RAbstractContainer {
         this.vector = vector;
     }
 
+    public RType getRType() {
+        return RType.List;
+    }
+
     public RVector getVector() {
         return vector;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
index 008f66db6f02161d67862fdc5d7363af297c67a9..cbb2cb8b3bc430c655a373de8c1d7843978ec5ba 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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.data;
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
+import com.oracle.truffle.r.runtime.*;
 
 @ValueType
 public final class RDouble extends RScalar {
@@ -38,6 +39,11 @@ public final class RDouble extends RScalar {
         return value;
     }
 
+    @Override
+    public RType getRType() {
+        return RType.Double;
+    }
+
     @Override
     public String toString() {
         CompilerAsserts.neverPartOfCompilation();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
index 4a0c9df0aaf36ffaf1e38d860bbe1cc74cfed4ec..0cf055b54616c1c8dd9d04a61448a727d77e62b3 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleSequence.java
@@ -45,7 +45,7 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV
         return stride;
     }
 
-    protected RDoubleVector populateVectorData(double[] result) {
+    private RDoubleVector populateVectorData(double[] result) {
         double current = start;
         for (int i = 0; i < getLength(); ++i) {
             result[i] = current;
@@ -65,16 +65,6 @@ public final class RDoubleSequence extends RSequence implements RAbstractDoubleV
         return internalCreateVector().toString();
     }
 
-    public RDoubleSequence removeLast() {
-        assert getLength() >= 1;
-        return RDataFactory.createDoubleSequence(getStart(), getStride(), getLength() - 1);
-    }
-
-    public RDoubleSequence removeFirst() {
-        assert getLength() >= 1;
-        return RDataFactory.createDoubleSequence(getStart() + 1, getStride(), getLength() - 1);
-    }
-
     @Override
     public double getDataAt(int index) {
         assert index >= 0 && index < getLength();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
index c3de40ac49ee7021e7a9be48b750cab0f4548457..b7d206f93d0a2cf9439bb99f55286feee1de3924 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
@@ -75,16 +75,6 @@ public final class RDoubleVector extends RVector implements RAbstractDoubleVecto
         return Arrays.toString(Arrays.stream(data).mapToObj(v -> RRuntime.doubleToString(v)).toArray(String[]::new));
     }
 
-    public RIntVector trimToIntVector() {
-        // TODO: Correct trim
-        double[] doubleData = this.data;
-        int[] intData = new int[doubleData.length];
-        for (int i = 0; i < doubleData.length; ++i) {
-            intData[i] = (int) doubleData[i];
-        }
-        return RDataFactory.createIntVector(intData, RDataFactory.INCOMPLETE_VECTOR, this.dimensions);
-    }
-
     @Override
     protected boolean internalVerify() {
         if (isComplete()) {
@@ -140,16 +130,6 @@ public final class RDoubleVector extends RVector implements RAbstractDoubleVecto
         return RDataFactory.createDoubleVector(data, isComplete(), newDimensions);
     }
 
-    public RDoubleVector removeLast() {
-        assert getLength() > 0;
-        return RDataFactory.createDoubleVector(Arrays.copyOf(data, getLength() - 1), isComplete());
-    }
-
-    public RDoubleVector removeFirst() {
-        assert getLength() > 0;
-        return RDataFactory.createDoubleVector(Arrays.copyOfRange(data, 1, getLength()), isComplete());
-    }
-
     @Override
     protected String getDataAtAsString(int index) {
         return RRuntime.doubleToString(data[index]);
@@ -170,7 +150,7 @@ public final class RDoubleVector extends RVector implements RAbstractDoubleVecto
 
     }
 
-    public static double[] resizeData(double[] newData, double[] oldData, int oldDataLength, boolean fillNA) {
+    static double[] resizeData(double[] newData, double[] oldData, int oldDataLength, boolean fillNA) {
         if (newData.length > oldDataLength) {
             if (fillNA) {
                 for (int i = oldDataLength; i < newData.length; ++i) {
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 3d5b81c21f9810ef5be42ec05f209b0869765569..b886be702fdf78e3e27b32cd6d3fe010b45432f9 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.model.*;
 
 public class RExpression implements RShareable, RAbstractContainer {
@@ -32,6 +33,10 @@ public class RExpression implements RShareable, RAbstractContainer {
         this.data = data;
     }
 
+    public RType getRType() {
+        return RType.Expression;
+    }
+
     public RList getList() {
         return data;
     }
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 83e1eb0ceedfbff734946311afb3e45958d0ad26..c1a047430d42aae46d8d964f34342deb92a00982 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
@@ -22,10 +22,12 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
+import com.oracle.truffle.r.runtime.*;
+
 /**
  * The rarely seen {@code externalptr} type.
  */
-public class RExternalPtr extends RAttributeStorage implements RAttributable {
+public class RExternalPtr extends RAttributeStorage implements RAttributable, RTypedValue {
     public final long value;
     public final String tag;
 
@@ -34,4 +36,8 @@ public class RExternalPtr extends RAttributeStorage implements RAttributable {
         this.tag = tag;
     }
 
+    public RType getRType() {
+        return RType.ExternalPtr;
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java
index 915dde27ce93d03ec634e52e806aa55a7569186c..ce7570096d21f6299e8dabc3b79ad53ba1bb4fc6 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.model.*;
 
 public final class RFactor implements RShareable, RAbstractContainer {
@@ -35,6 +36,10 @@ public final class RFactor implements RShareable, RAbstractContainer {
         this.ordered = ordered;
     }
 
+    public RType getRType() {
+        return RType.Integer;
+    }
+
     public RIntVector getVector() {
         return vector;
     }
@@ -146,14 +151,6 @@ public final class RFactor implements RShareable, RAbstractContainer {
         return this;
     }
 
-    public int getElementIndexByName(RAttributeProfiles attrProfiles, String name) {
-        return vector.getElementIndexByName(attrProfiles, name);
-    }
-
-    public int getElementIndexByNameInexact(RAttributeProfiles attrProfiles, String name) {
-        return vector.getElementIndexByNameInexact(attrProfiles, name);
-    }
-
     public void setLevels(Object newLevels) {
         vector.setLevels(newLevels);
     }
@@ -171,5 +168,4 @@ public final class RFactor implements RShareable, RAbstractContainer {
         RVector levels = vector.getLevels();
         return levels == null ? 0 : levels.getLength();
     }
-
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFormula.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFormula.java
index bc6b6d9735659c2f00cb4fa1a1bc65248dcc8e71..7da3447c733e574522235567ecaf08d827bf53d8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFormula.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFormula.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,6 +23,7 @@
 package com.oracle.truffle.r.runtime.data;
 
 import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.r.runtime.*;
 
 /**
  * Represents a formula, i.e., an expression of the form {@code response ~ model}.
@@ -44,6 +45,11 @@ public class RFormula extends RScalar {
         this.model = model;
     }
 
+    @Override
+    public RType getRType() {
+        return RType.Language;
+    }
+
     public SourceSection getSource() {
         return source;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
index a039309b94e978583752fe0dc0417067180e1227..79facba1abbb3259b05b65d8762fd5a7faa439d5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFunction.java
@@ -48,7 +48,7 @@ public final class RFunction extends RScalar implements RAttributable {
     private final boolean containsDispatch;
 
     @CompilationFinal private StableValue<MaterializedFrame> enclosingFrame;
-    protected RAttributes attributes;
+    private RAttributes attributes;
 
     RFunction(String name, RootCallTarget target, RBuiltin builtin, MaterializedFrame enclosingFrame, boolean containsDispatch) {
         this.name = name;
@@ -58,6 +58,11 @@ public final class RFunction extends RScalar implements RAttributable {
         this.enclosingFrame = new StableValue<>(enclosingFrame, "RFunction enclosing frame");
     }
 
+    @Override
+    public RType getRType() {
+        return isBuiltin() ? RType.Builtin : RType.Closure;
+    }
+
     public boolean isBuiltin() {
         return builtin != null;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInt.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInt.java
index b14eb5edd0a94e9f3a4ea1807e3e96067c8f77a1..bdd54643c4d47c4618d5c86ad3d69b64cf018d0f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInt.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInt.java
@@ -30,7 +30,7 @@ public final class RInt extends RScalar {
 
     private final int value;
 
-    RInt(byte value) {
+    private RInt(byte value) {
         this.value = value;
     }
 
@@ -38,6 +38,11 @@ public final class RInt extends RScalar {
         return value;
     }
 
+    @Override
+    public RType getRType() {
+        return RType.Integer;
+    }
+
     @Override
     public String toString() {
         return RRuntime.intToString(value);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
index 62f29de3522959e10b907da94f24d7c16d843d63..75cb217efc4a79a1bbf58f79a5ba9fa1662ae085 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntSequence.java
@@ -45,7 +45,7 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector
         return stride;
     }
 
-    protected RIntVector populateVectorData(int[] result) {
+    private RIntVector populateVectorData(int[] result) {
         int current = start;
         for (int i = 0; i < getLength(); ++i) {
             result[i] = current;
@@ -65,16 +65,6 @@ public final class RIntSequence extends RSequence implements RAbstractIntVector
         return internalCreateVector().toString();
     }
 
-    public RIntSequence removeLast() {
-        assert getLength() >= 1;
-        return RDataFactory.createIntSequence(getStart(), getStride(), getLength() - 1);
-    }
-
-    public RIntSequence removeFirst() {
-        assert getLength() >= 1;
-        return RDataFactory.createIntSequence(getStart() + 1, getStride(), getLength() - 1);
-    }
-
     public int getDataAt(int index) {
         assert index >= 0 && index < getLength();
         return start + stride * index;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
index 01624cb7494c6ff3c2c4f5cf49d1e27d34a205a0..1a7e620543d550be87e2c8f63813cdf7547b29c8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
@@ -91,16 +91,6 @@ public final class RIntVector extends RVector implements RAbstractIntVector {
         return true;
     }
 
-    public RIntVector removeLast() {
-        assert getLength() > 0;
-        return RDataFactory.createIntVector(Arrays.copyOf(data, getLength() - 1), isComplete());
-    }
-
-    public RIntVector removeFirst() {
-        assert getLength() > 0;
-        return RDataFactory.createIntVector(Arrays.copyOfRange(data, 1, getLength()), isComplete());
-    }
-
     public int[] getDataCopy() {
         return Arrays.copyOf(data, data.length);
     }
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 772c90c4579ba13a9df6d53c230d33c539c8a683..c7f1926a1bb6935a69c572f931873ae8c4d9efe0 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
@@ -56,6 +56,10 @@ public class RLanguage extends RLanguageRep implements RAbstractContainer, RAttr
         super(rep);
     }
 
+    public RType getRType() {
+        return RType.Language;
+    }
+
     public RAttributes getAttributes() {
         return attributes;
     }
@@ -131,10 +135,6 @@ public class RLanguage extends RLanguageRep implements RAbstractContainer, RAttr
         return false;
     }
 
-    public RList asList() {
-        return RContext.getRASTHelper().asList(this);
-    }
-
     public RLanguage copy() {
         RLanguage l = new RLanguage(getRep());
         l.attributes = attributes;
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 532fa433bb6cd717f4c6c62cd9ee45e65925182f..8963e070cb4c0503ad52bcbac903761a812b4f68 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
@@ -47,6 +47,10 @@ public final class RList extends RVector implements RAbstractVector {
         this.data = data;
     }
 
+    public RType getRType() {
+        return RType.List;
+    }
+
     private RList(Object[] data, boolean isComplete, int[] dims) {
         this(data, isComplete, dims, null);
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
index f4e86c794d629d102c868013231af873692c7a1e..976d5d1d7be788f904a9c5b034c296a0cb260204 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -38,6 +38,11 @@ public final class RLogical extends RScalar {
         return value;
     }
 
+    @Override
+    public RType getRType() {
+        return RType.Logical;
+    }
+
     @Override
     public String toString() {
         return RRuntime.logicalToString(value);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RMissing.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RMissing.java
index 5f658772bd2af08966139c95c03664ac860a636d..93f58a7f57318c15f3d9617c71d621bbcbf442b2 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RMissing.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RMissing.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,8 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
+import com.oracle.truffle.r.runtime.*;
+
 /**
  * See singleton {@link #instance}.
  */
@@ -35,6 +37,11 @@ public final class RMissing extends RScalar {
     private RMissing() {
     }
 
+    @Override
+    public RType getRType() {
+        return RType.Null;
+    }
+
     @Override
     public String toString() {
         return "missing";
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java
index ff60955cdf0b9d1743c2092b0f15fe125ffe8fc6..a43f589d9b504c7594c19583e8958c8667df507a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RNull.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,4 +35,9 @@ public final class RNull extends RScalar {
     public String toString() {
         return RRuntime.NULL;
     }
+
+    @Override
+    public RType getRType() {
+        return RType.Null;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
index 3952fb0ad14e0ce7570e2884debecaa72c167de7..acd47e767aa6a51f070458e43c169b3ce32c70eb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPairList.java
@@ -50,6 +50,10 @@ public class RPairList extends RAttributeStorage implements RAttributable, RAbst
         this.type = type;
     }
 
+    public RType getRType() {
+        return RType.PairList;
+    }
+
     @Override
     public String toString() {
         CompilerAsserts.neverPartOfCompilation();
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 cc33accc134da828eecd9d09a6de632b0e5ad4b5..805ce158bd341af27c0759325ce5dbf875d768fe 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
@@ -27,7 +27,6 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.frame.*;
-import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.env.*;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.FrameSlotInfo;
@@ -39,7 +38,7 @@ import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor.FrameSlotIn
  * which is used for manual method dispatch.
  */
 @ValueType
-public class RPromise extends RLanguageRep {
+public class RPromise extends RLanguageRep implements RTypedValue {
 
     /**
      * The policy used to evaluate a promise.
@@ -105,14 +104,14 @@ public class RPromise extends RLanguageRep {
     /**
      * @see EvalPolicy
      */
-    protected final EvalPolicy evalPolicy;
+    private final EvalPolicy evalPolicy;
 
     /**
      * @see PromiseType
      */
-    protected final PromiseType type;
+    private final PromiseType type;
 
-    protected final OptType optType;
+    private final OptType optType;
 
     /**
      * @see #getFrame()
@@ -128,12 +127,12 @@ public class RPromise extends RLanguageRep {
     /**
      * When {@code null} the promise has not been evaluated.
      */
-    protected Object value = null;
+    private Object value = null;
 
     /**
      * A flag to indicate the promise has been evaluated.
      */
-    protected boolean isEvaluated = false;
+    private boolean isEvaluated = false;
 
     /**
      * A flag which is necessary to avoid cyclic evaluation. Manipulated by
@@ -201,6 +200,10 @@ public class RPromise extends RLanguageRep {
         this.closure = null;
     }
 
+    public RType getRType() {
+        return RType.Promise;
+    }
+
     public final boolean isInlined() {
         return evalPolicy == EvalPolicy.INLINED;
     }
@@ -235,17 +238,6 @@ public class RPromise extends RLanguageRep {
         }
     }
 
-    @TruffleBoundary
-    protected final Object doEvalArgument(SourceSection callSrc) {
-        assert execFrame != null;
-        return RContext.getEngine().evalPromise(this, callSrc);
-    }
-
-    @TruffleBoundary
-    protected final Object doEvalArgument(MaterializedFrame frame) {
-        return RContext.getEngine().evalPromise(this, frame);
-    }
-
     /**
      * @param frame
      * @return Whether the given {@link RPromise} is in its origin context and thus can be resolved
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
index e7339d6919368129d4b68b0938361ff340cea7b2..5617c23dfcaa6a2fa8999c54e477645fd94ef66a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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.data;
 
 import com.oracle.truffle.api.*;
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
+import com.oracle.truffle.r.runtime.*;
 
 @ValueType
 public final class RRaw extends RScalar {
@@ -38,6 +39,11 @@ public final class RRaw extends RScalar {
         return value;
     }
 
+    @Override
+    public RType getRType() {
+        return RType.Raw;
+    }
+
     @Override
     public String toString() {
         CompilerAsserts.neverPartOfCompilation();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
index a625889bac83ca8960609752836e28252f9bea5a..88eabdfc89cbefd7aeaa52d38d0d266f8cf27255 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
@@ -110,16 +110,6 @@ public final class RRawVector extends RVector implements RAbstractRawVector {
         return RDataFactory.createRawVector(data, newDimensions);
     }
 
-    public RRawVector removeLast() {
-        assert getLength() > 0;
-        return RDataFactory.createRawVector(Arrays.copyOf(data, getLength() - 1));
-    }
-
-    public RRawVector removeFirst() {
-        assert getLength() > 0;
-        return RDataFactory.createRawVector(Arrays.copyOfRange(data, 1, getLength()));
-    }
-
     @Override
     protected String getDataAtAsString(int index) {
         return getDataAt(index).toString();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalar.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalar.java
index ac5d0796bbdf3c49c85a67b6d0b88fb9434d030e..1b810ad32f51968aa31b355ab828b38224c6bb37 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalar.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,5 +25,6 @@ package com.oracle.truffle.r.runtime.data;
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
 
 @ValueType
-public class RScalar {
+public abstract class RScalar implements RTypedValue {
+
 }
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 12bce787d4a97aaaf085360cdf62ad2da079bc39..98819eb584937d71c6e0e99ee466692aa8293fb7 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
@@ -161,7 +161,7 @@ public final class RStringVector extends RVector implements RAbstractStringVecto
         this.data = createResizedData(size, RRuntime.STRING_NA);
     }
 
-    public void resizeWithEmpty(int size) {
+    void resizeWithEmpty(int size) {
         this.data = createResizedData(size, RRuntime.NAMES_ATTR_EMPTY_VALUE);
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
index 18bcc6691308e71ef47166124f0d374cb1a951b5..4dad25d49cc76adff0664b9c56d9fd4aaeb758af 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSymbol.java
@@ -23,13 +23,14 @@
 package com.oracle.truffle.r.runtime.data;
 
 import com.oracle.truffle.api.CompilerDirectives.ValueType;
+import com.oracle.truffle.r.runtime.*;
 
 /**
  * Denotes an R "symbol" or "name". Its rep is a {@code String} but it's a different type in the
  * Truffle sense.
  */
 @ValueType
-public class RSymbol extends RAttributeStorage implements RAttributable {
+public class RSymbol extends RAttributeStorage implements RAttributable, RTypedValue {
 
     public static final RSymbol MISSING = RDataFactory.createSymbol("");
 
@@ -39,6 +40,10 @@ public class RSymbol extends RAttributeStorage implements RAttributable {
         this.name = name;
     }
 
+    public RType getRType() {
+        return RType.Symbol;
+    }
+
     public String getName() {
         return name;
     }
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
new file mode 100644
index 0000000000000000000000000000000000000000..595fb4dbb36574f101a48e594e5f35e7e5cfbf4f
--- /dev/null
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypedValue.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * 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;
+
+import com.oracle.truffle.r.runtime.*;
+
+/**
+ * Interface for R values that are publicly flowing through the interpreter. Be aware that also the
+ * primitive values {@link Integer}, {@link Double}, {@link Byte} and {@link String} flow but are
+ * not implementing this interface.
+ */
+public interface RTypedValue {
+
+    RType getRType();
+
+}
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
index a5d05da25512c5d010372358933fef7781676594..be3f6273df820aef06ad99b7ab6f6663c6194fcf 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java
@@ -51,7 +51,7 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV
     private int matrixDimension;
     protected int[] dimensions;
     protected RStringVector names;
-    protected RList dimNames;
+    private RList dimNames;
     private RAttributes attributes;
     private boolean shared;
     private boolean temporary = true;
@@ -87,10 +87,6 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV
         }
     }
 
-    protected RVector(boolean complete, int length, int[] dimensions) {
-        this(complete, length, dimensions, null);
-    }
-
     public void setComplete(boolean complete) {
         this.complete = complete;
     }
@@ -133,8 +129,8 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV
     }
 
     /*
-     * Version without profiles is used by RDeparse and for internal attribute coopying (both are
-     * not performance-critical)
+     * Version without profiles is used by RDeparse and for internal attribute copying (both are not
+     * performance-critical)
      */
     public final RStringVector getNames() {
         if (names == null) {
@@ -632,21 +628,6 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV
         return RDataFactory.createStringVector(values, this.isComplete());
     }
 
-    public final boolean isInBounds(int firstPosition, int secondPosition) {
-        assert isMatrix();
-        return firstPosition >= 1 && firstPosition <= matrixDimension && (convertToIndex(secondPosition) * matrixDimension + firstPosition) <= getLength();
-    }
-
-    public static int convertToIndex(int position) {
-        return position - 1;
-    }
-
-    public final int convertToIndex(int firstPosition, int secondPosition) {
-        assert isMatrix();
-        assert isInBounds(firstPosition, secondPosition);
-        return convertToIndex(firstPosition) + convertToIndex(secondPosition) * matrixDimension;
-    }
-
     public final RAttributable copyAttributesFrom(RAttributeProfiles attrProfiles, RAbstractContainer vector) {
         // it's meant to be used on a "fresh" vector with only dimensions potentially set
         assert (this.names == null);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java
index 1c082f82108c668cf516334aec7125a03a6ab33b..4bc764f3dd8cff99e33f21a16e6d2fbcf7a0a060 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractComplexVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,4 +39,9 @@ public interface RAbstractComplexVector extends RAbstractVector {
         }
         return true;
     }
+
+    default RType getRType() {
+        return RType.Complex;
+    }
+
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
index 82c3f5547570f94d33ecee0eca6e3170e6f0b1ed..0e0a46a4214e10e0749a332186296c2484d2f97f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java
@@ -24,7 +24,7 @@ package com.oracle.truffle.r.runtime.data.model;
 
 import com.oracle.truffle.r.runtime.data.*;
 
-public interface RAbstractContainer extends RAttributable, RClassHierarchy {
+public interface RAbstractContainer extends RAttributable, RClassHierarchy, RTypedValue {
 
     boolean isComplete();
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java
index e6c33808488210230aa557ed2a11b9ded8b71f39..4c2bff3917c930298a079f80557810a1c1e654a4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractDoubleVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,4 +39,8 @@ public interface RAbstractDoubleVector extends RAbstractVector {
         }
         return true;
     }
+
+    default RType getRType() {
+        return RType.Double;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java
index 8816c9b84a6a207db09df43cc5ebc5df7755152d..58d9a2920ca300b329683e4327f18fd0cae9fd1d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractIntVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,4 +39,8 @@ public interface RAbstractIntVector extends RAbstractVector {
         }
         return true;
     }
+
+    default RType getRType() {
+        return RType.Integer;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java
index 4006121efda1dd2531926610f83e871cb3f9b3f7..4482f930b278e38da0a1aa01b1242a577301817c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractLogicalVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,4 +39,8 @@ public interface RAbstractLogicalVector extends RAbstractVector {
         }
         return true;
     }
+
+    default RType getRType() {
+        return RType.Logical;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java
index a7a57b11f18438fa4dd7b868df747c49c6d599a8..b92af9564d356bf85248d8a49e1136bdc3bd2ce0 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractRawVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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 @@
  */
 package com.oracle.truffle.r.runtime.data.model;
 
+import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 
 public interface RAbstractRawVector extends RAbstractVector {
@@ -33,4 +34,8 @@ public interface RAbstractRawVector extends RAbstractVector {
     default boolean checkCompleteness() {
         return true;
     }
+
+    default RType getRType() {
+        return RType.Raw;
+    }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java
index afa2918e9fab45b679d7ffb79cb66f13c76aa749..150c52dd43f387e1f54f98f864d80a3ba47cd608 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractStringVector.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
  * 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,4 +39,8 @@ public interface RAbstractStringVector extends RAbstractVector {
         }
         return true;
     }
+
+    default RType getRType() {
+        return RType.Character;
+    }
 }
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 6d3781b19cc9515f60861c0b9a8d5a5fc52a2f8c..afa1bea5da06fb2e42fe518e9957ef4122f6dba5 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
@@ -79,15 +79,7 @@ import com.oracle.truffle.r.runtime.env.frame.*;
  * most one for a function frame, allowing equality to be tested using {@code ==}.
  *
  */
-public abstract class REnvironment extends RAttributeStorage implements RAttributable {
-
-    /**
-     * Controls whether a separate frame, with a different enclosing frame is created to the
-     * "namespace:base" environment. This is correct semantics and required to resolve unqualified
-     * references to names between packages, but requires a fix to {@link FrameSlotChangeMonitor} to
-     * work. TODO Remove once fix in place.
-     */
-    private static final boolean NS_BASE_FRAME = false;
+public abstract class REnvironment extends RAttributeStorage implements RAttributable, RTypedValue {
 
     public static class PutException extends RErrorException {
         private static final long serialVersionUID = 1L;
@@ -99,7 +91,7 @@ public abstract class REnvironment extends RAttributeStorage implements RAttribu
 
     private static final REnvFrameAccess defaultFrameAccess = new REnvFrameAccessBindingsAdapter();
 
-    public static final String UNNAMED = new String("");
+    private static final String UNNAMED = new String("");
     private static final String NAME_ATTR_KEY = "name";
 
     private static final Empty emptyEnv = new Empty();
@@ -114,9 +106,13 @@ public abstract class REnvironment extends RAttributeStorage implements RAttribu
 
     protected REnvironment parent;
     private final String name;
-    final REnvFrameAccess frameAccess;
+    protected final REnvFrameAccess frameAccess;
     private boolean locked;
 
+    public RType getRType() {
+        return RType.Environment;
+    }
+
     /**
      * Value returned by {@code emptyenv()}.
      */
@@ -139,30 +135,10 @@ public abstract class REnvironment extends RAttributeStorage implements RAttribu
      * environment is created the value is stored in the associated frame. Therefore {@code env}
      * could never match lazy {@code null}.
      */
-    public static boolean isFrameForEnv(Frame frame, REnvironment env) {
+    private static boolean isFrameForEnv(Frame frame, REnvironment env) {
         return RArguments.getEnvironment(frame) == env;
     }
 
-    /**
-     * Looks up the search path for an environment that is associated with {@code frame}.
-     *
-     * @param frame
-     * @return the corresponding {@link REnvironment} or {@code null} if not found. If the
-     *         environment is {@code base} the "namespace:base" instance is returned.
-     */
-    public static REnvironment lookupEnvForFrame(MaterializedFrame frame) {
-        for (REnvironment env : searchPath) {
-            if (isFrameForEnv(frame, env)) {
-                if (env == baseEnv) {
-                    return baseEnv.getNamespace();
-                } else {
-                    return env;
-                }
-            }
-        }
-        return null;
-    }
-
     /**
      * Check whether the given frame is indeed the frame stored in the global environment.
      */
@@ -472,7 +448,7 @@ public abstract class REnvironment extends RAttributeStorage implements RAttribu
     /**
      * The basic constructor; just assigns the essential fields.
      */
-    protected REnvironment(REnvironment parent, String name, REnvFrameAccess frameAccess) {
+    private REnvironment(REnvironment parent, String name, REnvFrameAccess frameAccess) {
         this.parent = parent;
         this.name = name;
         this.frameAccess = frameAccess;
@@ -481,7 +457,7 @@ public abstract class REnvironment extends RAttributeStorage implements RAttribu
     /**
      * An environment associated with an already materialized frame.
      */
-    protected REnvironment(REnvironment parent, String name, MaterializedFrame frame) {
+    private REnvironment(REnvironment parent, String name, MaterializedFrame frame) {
         this(parent, name, new REnvTruffleFrameAccess(frame));
         // Associate frame with the environment
         RArguments.setEnvironment(frame, this);
@@ -654,9 +630,7 @@ public abstract class REnvironment extends RAttributeStorage implements RAttribu
         private BaseNamespace(REnvironment parent, String name, REnvFrameAccess frameAccess) {
             super(parent, name, frameAccess);
             namespaceRegistry.safePut(name, this);
-            if (NS_BASE_FRAME) {
-                RArguments.setEnvironment(frameAccess.getFrame(), this);
-            }
+            RArguments.setEnvironment(frameAccess.getFrame(), this);
         }
 
         @Override
@@ -674,15 +648,8 @@ public abstract class REnvironment extends RAttributeStorage implements RAttribu
              * We create the NSBaseMaterializedFrame using globalFrame as the enclosing frame. The
              * namespaceEnv parent field will change to globalEnv after the latter is created
              */
-            MaterializedFrame nsFrame = new NSBaseMaterializedFrame(baseFrame, globalFrame);
-            REnvFrameAccess baseFrameAccess = NS_BASE_FRAME ? new REnvTruffleFrameAccess(nsFrame) : this.frameAccess;
+            REnvFrameAccess baseFrameAccess = new REnvTruffleFrameAccess(new NSBaseMaterializedFrame(baseFrame, globalFrame));
             this.namespaceEnv = new BaseNamespace(emptyEnv, "base", baseFrameAccess);
-            if (!NS_BASE_FRAME) {
-                // This is important so that "environment(func)" gives the correct
-                // answer for functions defined in base. The sharing of the
-                // frame would otherwise report "package:base"
-                RArguments.setEnvironment(baseFrame, this.namespaceEnv);
-            }
         }
 
         @Override
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 4ffb15dfde046a90b57de758bb750aced58bfe51..9a89c3540ee5d45cc184a5452756102cc06e5794 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
@@ -46,6 +46,11 @@ import com.oracle.truffle.r.runtime.data.*;
  */
 public final class FrameSlotChangeMonitor {
 
+    public static final FrameDescriptor NAMESPACE_BASE_MARKER_FRAME_DESCRIPTOR = new FrameDescriptor();
+
+    private static final int MAX_FUNCTION_INVALIDATION_COUNT = 2;
+    private static final int MAX_INVALIDATION_COUNT = 1;
+
     @SuppressWarnings("unused")
     private static void out(String format, Object... args) {
 // System.out.println(String.format(format, args));
@@ -66,11 +71,13 @@ public final class FrameSlotChangeMonitor {
     private static final class FrameSlotInfoImpl extends FrameSlotInfo {
         @CompilationFinal private StableValue<Object> stableValue;
         private final Object identifier;
+        private int invalidationCount;
 
         public FrameSlotInfoImpl(boolean isSingletonFrame, Object identifier) {
             this.identifier = identifier;
             if (isSingletonFrame) {
                 stableValue = new StableValue<>(null, identifier.toString());
+                invalidationCount = 0;
             } else {
                 stableValue = null;
             }
@@ -84,7 +91,8 @@ public final class FrameSlotChangeMonitor {
             if (stableValue != null && stableValue.getValue() != value) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 stableValue.getAssumption().invalidate();
-                if (stableValue.getValue() == null && value instanceof RFunction) {
+                int maxInvalidationCount = value instanceof RFunction ? MAX_FUNCTION_INVALIDATION_COUNT : MAX_INVALIDATION_COUNT;
+                if (invalidationCount++ < maxInvalidationCount) {
                     out("setting singleton value %s = %s", identifier, value.getClass());
                     stableValue = new StableValue<>(value, identifier.toString());
                 } else {
@@ -210,8 +218,8 @@ public final class FrameSlotChangeMonitor {
     public static void invalidateEnclosingFrame(Frame frame) {
         CompilerAsserts.neverPartOfCompilation();
         MaterializedFrame enclosingFrame = RArguments.getEnclosingFrame(frame);
-        getOrInitializeEnclosingFrameAssumption(frame.getFrameDescriptor(), null, enclosingFrame);
-        getOrInitializeEnclosingFrameDescriptorAssumption(frame.getFrameDescriptor(), null, enclosingFrame == null ? null : enclosingFrame.getFrameDescriptor());
+        getOrInitializeEnclosingFrameAssumption(frame, frame.getFrameDescriptor(), null, enclosingFrame);
+        getOrInitializeEnclosingFrameDescriptorAssumption(frame, frame.getFrameDescriptor(), null, enclosingFrame == null ? null : enclosingFrame.getFrameDescriptor());
     }
 
     private static final WeakHashMap<FrameDescriptor, StableValue<MaterializedFrame>> descriptorEnclosingFrameAssumptions = new WeakHashMap<>();
@@ -220,10 +228,25 @@ public final class FrameSlotChangeMonitor {
 
     private static int rewriteFrameDescriptorAssumptionsCount;
 
-    public static synchronized void initializeFrameDescriptor(FrameDescriptor frameDescriptor, boolean frameCreated) {
+    /**
+     * Initializes the internal data structures for a newly created frame descriptor that is
+     * intended to be used for a non-function frame (and thus will only ever be used for one frame).
+     *
+     * The namespace:base environment needs to be handled specially, because it shares a frame (and
+     * thus, also a frame descriptor) with the package:base environment.
+     */
+    public static synchronized void initializeNonFunctionFrameDescriptor(FrameDescriptor originalFrameDescriptor, boolean isNamespaceBase) {
+        FrameDescriptor frameDescriptor = isNamespaceBase ? NAMESPACE_BASE_MARKER_FRAME_DESCRIPTOR : originalFrameDescriptor;
+        descriptorEnclosingFrameAssumptions.put(frameDescriptor, StableValue.invalidated());
+        descriptorEnclosingDescriptorAssumptions.put(frameDescriptor, StableValue.invalidated());
+        if (!isNamespaceBase) {
+            descriptorSingletonAssumptions.put(originalFrameDescriptor, Boolean.FALSE);
+        }
+    }
+
+    public static synchronized void initializeFunctionFrameDescriptor(FrameDescriptor frameDescriptor) {
         descriptorEnclosingFrameAssumptions.put(frameDescriptor, StableValue.invalidated());
         descriptorEnclosingDescriptorAssumptions.put(frameDescriptor, StableValue.invalidated());
-        descriptorSingletonAssumptions.put(frameDescriptor, frameCreated ? Boolean.TRUE : Boolean.FALSE);
     }
 
     public static synchronized StableValue<MaterializedFrame> getEnclosingFrameAssumption(FrameDescriptor descriptor) {
@@ -234,9 +257,17 @@ public final class FrameSlotChangeMonitor {
         return descriptorEnclosingDescriptorAssumptions.get(descriptor);
     }
 
-    public static synchronized StableValue<FrameDescriptor> getOrInitializeEnclosingFrameDescriptorAssumption(FrameDescriptor frameDescriptor, StableValue<FrameDescriptor> value,
+    /**
+     * Special handling (return a marker frame) for the namespace:base environment.
+     */
+    private static FrameDescriptor handleBaseNamespaceEnv(Frame frame, FrameDescriptor originalFrameDescriptor) {
+        return frame instanceof NSBaseMaterializedFrame ? NAMESPACE_BASE_MARKER_FRAME_DESCRIPTOR : originalFrameDescriptor;
+    }
+
+    public static synchronized StableValue<FrameDescriptor> getOrInitializeEnclosingFrameDescriptorAssumption(Frame frame, FrameDescriptor originalFrameDescriptor, StableValue<FrameDescriptor> value,
                     FrameDescriptor newValue) {
         CompilerAsserts.neverPartOfCompilation();
+        FrameDescriptor frameDescriptor = handleBaseNamespaceEnv(frame, originalFrameDescriptor);
         if (value != null) {
             value.getAssumption().invalidate();
         }
@@ -256,8 +287,10 @@ public final class FrameSlotChangeMonitor {
         return currentValue;
     }
 
-    public static synchronized StableValue<MaterializedFrame> getOrInitializeEnclosingFrameAssumption(FrameDescriptor frameDescriptor, StableValue<MaterializedFrame> value, MaterializedFrame newValue) {
+    public static synchronized StableValue<MaterializedFrame> getOrInitializeEnclosingFrameAssumption(Frame frame, FrameDescriptor originalFrameDescriptor, StableValue<MaterializedFrame> value,
+                    MaterializedFrame newValue) {
         CompilerAsserts.neverPartOfCompilation();
+        FrameDescriptor frameDescriptor = handleBaseNamespaceEnv(frame, originalFrameDescriptor);
         if (value != null) {
             value.getAssumption().invalidate();
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
index f469f0fa141195bc6e0c8a282439d8f6fec565b7..54ecd16d67fe5e73e5d2d6b2da7cb8de18c0ded8 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/NSBaseMaterializedFrame.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.runtime.env.frame;
 
 import java.util.*;
+import java.util.concurrent.atomic.*;
 
 import com.oracle.truffle.api.CompilerDirectives.*;
 import com.oracle.truffle.api.frame.*;
@@ -35,13 +36,19 @@ import com.oracle.truffle.r.runtime.*;
  */
 public final class NSBaseMaterializedFrame implements MaterializedFrame {
 
+    private static final AtomicLong INSTANCE_COUNT = new AtomicLong();
+
     private final MaterializedFrame packageBaseFrame;
     @CompilationFinal private final Object[] arguments;
 
     public NSBaseMaterializedFrame(MaterializedFrame packageBaseFrame, MaterializedFrame globalFrame) {
         this.packageBaseFrame = packageBaseFrame;
         this.arguments = Arrays.copyOf(packageBaseFrame.getArguments(), packageBaseFrame.getArguments().length);
+        FrameSlotChangeMonitor.initializeNonFunctionFrameDescriptor(getFrameDescriptor(), true);
         RArguments.setEnclosingFrame(this, globalFrame);
+        if (INSTANCE_COUNT.incrementAndGet() > 1) {
+            throw RInternalError.shouldNotReachHere("more than one namespace:base environment crated");
+        }
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvMaterializedFrame.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvMaterializedFrame.java
index 0bef9b0f45dd95ee16b3bbe1fd04fc6c61826a5a..057ad71901fc71bceae2ffff1b72cf0de691dfcb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvMaterializedFrame.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/REnvMaterializedFrame.java
@@ -38,7 +38,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment.*;
  * code from Truffle, but the relevant classes are final. Life would be easier if the environment
  * was immutable. No attempt is currently being made to make variable access efficient.
  */
-public class REnvMaterializedFrame implements MaterializedFrame {
+public final class REnvMaterializedFrame implements MaterializedFrame {
     private final Map<Object, Object> map;
     private final FrameDescriptor descriptor;
     @CompilationFinal private final Object[] arguments;
@@ -46,7 +46,7 @@ public class REnvMaterializedFrame implements MaterializedFrame {
 
     public REnvMaterializedFrame(UsesREnvMap env) {
         descriptor = new FrameDescriptor();
-        FrameSlotChangeMonitor.initializeFrameDescriptor(descriptor, true);
+        FrameSlotChangeMonitor.initializeNonFunctionFrameDescriptor(descriptor, false);
         REnvMapFrameAccess frameAccess = env.getFrameAccess();
         map = frameAccess.getMap();
         tags = new byte[map.size()];
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java
index 0b50331ee0ff3b2db8a038a73154979a44bc09ab..af64e0c2b744533d75fc7e44b8116cb713bb40e5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/RFrameSlot.java
@@ -22,11 +22,6 @@
  */
 package com.oracle.truffle.r.runtime.env.frame;
 
-import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
-import com.oracle.truffle.api.frame.*;
-
 public enum RFrameSlot {
     OnExit;
-
-    @CompilationFinal public static final FrameSlotKind[] SLOT_KINDS = {FrameSlotKind.Object, FrameSlotKind.Byte, FrameSlotKind.Int, FrameSlotKind.Double};
 }
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 d21d17b1364e8892a6f9d864c96442244bd7d6b6..0ad5f60d9ea33bf5fa2255e635d025e7a6207e8b 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
@@ -6,7 +6,7 @@
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
  * Copyright (c) 2012-2013, Purdue University
- * Copyright (c) 2013, 2014, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2015, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -491,9 +491,9 @@ public abstract class BinaryArithmetic extends Operation {
 
     public static class Pow extends BinaryArithmetic {
 
-        BranchProfile everSeenExponentOtherThanTwo = BranchProfile.create();
-        BranchProfile everSeenNonIntegralExponent = BranchProfile.create();
-        BranchProfile everSeenNegativeExponent = BranchProfile.create();
+        private final BranchProfile everSeenExponentOtherThanTwo = BranchProfile.create();
+        private final BranchProfile everSeenNonIntegralExponent = BranchProfile.create();
+        private final BranchProfile everSeenNegativeExponent = BranchProfile.create();
 
         public Pow() {
             super(false, false, false);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java
index e587a29cf9734bcfe29e5946e73ad8526c17d6eb..953d4a72f38b913f2b89b10de859189b8b74c979 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/na/NACheck.java
@@ -40,8 +40,8 @@ public final class NACheck {
 
     private final BranchProfile conversionOverflowReached = BranchProfile.create();
 
-    @CompilationFinal int state;
-    @CompilationFinal boolean seenNaN;
+    @CompilationFinal private int state;
+    @CompilationFinal private boolean seenNaN;
 
     public static NACheck create() {
         return new NACheck();
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 23f5d45c72cad0a2e10a80aef6532c79f0acb7b1..6393d04f1e3e1506b5ac977a0396e06c34859570 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,9 +22,11 @@
  */
 package com.oracle.truffle.r.test.generate;
 
-import com.oracle.truffle.api.CompilerDirectives.*;
+import java.util.concurrent.*;
+
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.engine.*;
-import com.oracle.truffle.r.options.FastROptions;
+import com.oracle.truffle.r.options.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.ffi.*;
 
@@ -99,6 +101,8 @@ public final class FastRSession implements RSession {
     private final ConsoleHandler consoleHandler;
     private static FastRSession singleton;
 
+    private EvalThread evalThread;
+
     public static FastRSession create() {
         if (singleton == null) {
             singleton = new FastRSession();
@@ -122,26 +126,60 @@ public final class FastRSession implements RSession {
     public String eval(String expression) {
         consoleHandler.reset();
 
-        // run the script in a different thread and kill it after the timeout
-        Thread thread = new Thread() {
-            @Override
-            public void run() {
-                REngine.getInstance().parseAndEvalTest(expression, true);
-            }
-        };
-        thread.start();
-        try {
-            thread.join(TIMEOUT);
-        } catch (InterruptedException e) {
-            e.printStackTrace();
+        EvalThread thread = evalThread;
+        if (thread == null || !thread.isAlive()) {
+            thread = new EvalThread();
+            thread.setName("FastR evaluation");
+            thread.start();
+            evalThread = thread;
         }
-        if (thread.isAlive()) {
-            consoleHandler.println("<timeout>");
-            thread.stop();
+
+        thread.push(expression);
+
+        try {
+            thread.await(TIMEOUT);
+        } catch (InterruptedException e1) {
+            if (thread.isAlive()) {
+                consoleHandler.println("<timeout>");
+                thread.stop();
+            }
         }
         return consoleHandler.buffer.toString();
     }
 
+    private static final class EvalThread extends Thread {
+
+        private String expression;
+        private final Semaphore entry = new Semaphore(0);
+        private final Semaphore exit = new Semaphore(0);
+
+        public void push(String exp) {
+            this.expression = exp;
+            this.entry.release();
+        }
+
+        public void await(int millisTimeout) throws InterruptedException {
+            this.exit.tryAcquire(millisTimeout, TimeUnit.MILLISECONDS);
+        }
+
+        @Override
+        public void run() {
+            while (true) {
+                try {
+                    entry.acquire();
+                } catch (InterruptedException e) {
+                    break;
+                }
+                try {
+                    REngine.getInstance().parseAndEvalTest(expression, true);
+                } finally {
+                    exit.release();
+                }
+            }
+        }
+
+    }
+
     public String name() {
         return "FastR";
     }
diff --git a/mx.fastr/imports b/mx.fastr/imports
index da65b7a8ac70f3d94507e0c645f8c78532b2fc63..a245d97b6b3fc9962722591b0d121164f5bfab5e 100644
--- a/mx.fastr/imports
+++ b/mx.fastr/imports
@@ -1 +1 @@
-graal,dc7189b2bb5fe9569cce923beb261334435ae267,http://hg.openjdk.java.net/graal/graal
+graal,905afef74a2ecdd1cc34635458f2a402183b3000,http://hg.openjdk.java.net/graal/graal