diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
index 588b62059700f448f74fa5895cd41fbd96e957ad..f34298e87262cbdbebedb105b912514ccbe1cfbc 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.builtin.base;
 import com.oracle.truffle.api.dsl.*;
 import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.nodes.builtin.*;
+import com.oracle.truffle.r.nodes.control.RLengthNode;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.*;
 import com.oracle.truffle.r.runtime.data.model.*;
@@ -138,12 +139,12 @@ public abstract class AnyNA extends RBuiltinNode {
     @Specialization
     protected byte isNA(RList list, //
                     @Cached("createRecursive()") AnyNA recursive, //
-                    @Cached("createClassProfile()") ValueProfile elementProfile) {
+                    @Cached("createClassProfile()") ValueProfile elementProfile, //
+                    @Cached("create()") RLengthNode length) {
         controlVisibility();
         for (int i = 0; i < list.getLength(); i++) {
             Object value = elementProfile.profile(list.getDataAt(i));
-            if (value instanceof Byte || value instanceof Integer || value instanceof Double || value instanceof RComplex || value instanceof RScalar ||
-                            (value instanceof RAbstractContainer && ((RAbstractContainer) value).getLength() == 1)) {
+            if (length.executeInteger(value) == 1) {
                 byte result = recursive.execute(value);
                 if (result == RRuntime.LOGICAL_TRUE) {
                     return RRuntime.LOGICAL_TRUE;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
index c41434b4ae6f59f1b88de9460efaa198e1f89654..e6e5f6d68cca2ca8979585a43ac501cacc01b81d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java
@@ -534,7 +534,5 @@ public class BasePackage extends RBuiltinPackage {
         addFastPath(baseFrame, "pmin", FastPathFactory.EVALUATE_ARGS);
         addFastPath(baseFrame, "cbind", FastPathFactory.FORCED_EAGER_ARGS);
         addFastPath(baseFrame, "rbind", FastPathFactory.FORCED_EAGER_ARGS);
-// addFastPath(baseFrame, "cbind.data.frame", FastPathFactory.FORCED_EAGER_ARGS);
-// addFastPath(baseFrame, "rbind.data.frame", FastPathFactory.FORCED_EAGER_ARGS);
     }
 }
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 ab394b0a0bc19ee76120ac99b01126cba387112c..e6c2175704a67dffaa2028632a344a03f20cf090 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
@@ -131,50 +131,37 @@ public class InfixEmulationFunctions {
     @NodeChild(value = "op")
     protected abstract static class PromiseEvaluator extends RNode {
 
-        protected abstract Object execute(VirtualFrame frame, Object op);
-
-        @Child private PromiseHelperNode promiseHelper;
-        @Child private PromiseEvaluator evalRecursive;
-
-        protected Object evalRecursive(VirtualFrame frame, Object op) {
-            if (evalRecursive == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                evalRecursive = insert(PromiseEvaluatorNodeGen.create(null));
-            }
-            return evalRecursive.execute(frame, op);
+        protected PromiseEvaluator create() {
+            return PromiseEvaluatorNodeGen.create(null);
         }
 
+        protected abstract Object execute(VirtualFrame frame, Object op);
+
         @Specialization(guards = {"!isRPromise(op)", "!isRArgsValuesAndNames(op)"})
         protected Object eval(Object op) {
             return op;
         }
 
         @Specialization
-        protected Object eval(VirtualFrame frame, RPromise p) {
-            if (promiseHelper == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                promiseHelper = insert(new PromiseHelperNode());
-            }
+        protected Object eval(VirtualFrame frame, RPromise p, //
+                        @Cached("new()") PromiseHelperNode promiseHelper) {
             return promiseHelper.evaluate(frame, p);
         }
 
-        @Specialization(guards = "!argsEmpty(args)")
-        protected RArgsValuesAndNames eval(VirtualFrame frame, RArgsValuesAndNames args) {
+        @Specialization(guards = "!args.isEmpty()")
+        protected RArgsValuesAndNames eval(VirtualFrame frame, RArgsValuesAndNames args, //
+                        @Cached("create()") PromiseEvaluator evalRecursive) {
             Object[] values = args.getArguments();
             for (int i = 0; i < values.length; i++) {
-                values[i] = evalRecursive(frame, values[i]);
+                values[i] = evalRecursive.execute(frame, values[i]);
             }
             return args;
         }
 
-        @Specialization(guards = "argsEmpty(args)")
+        @Specialization(guards = "args.isEmpty()")
         protected RArgsValuesAndNames evalEmpty(RArgsValuesAndNames args) {
             return args;
         }
-
-        protected boolean argsEmpty(RArgsValuesAndNames args) {
-            return args.isEmpty();
-        }
     }
 
     public abstract static class AccessArrayBuiltin extends RBuiltinNode {
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 33ab0665fcfb19b8623ee899ee6787fc76b9bf24..9f89a8bae7bf4b0dca628e4aa75795693a866c2f 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
@@ -266,7 +266,7 @@ public abstract class Match extends RBuiltinNode {
         return RDataFactory.createIntVector(result, setCompleteState(matchAll, nomatch));
     }
 
-    @Specialization()
+    @Specialization
     protected RIntVector match(RAbstractIntVector x, RAbstractLogicalVector table, Object nomatchObj, @SuppressWarnings("unused") Object incomparables) {
         controlVisibility();
         int nomatch = castInt(nomatchObj);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
index 6af4211c0cd71a3be0586483b456c8c595f57769..d9d8315dc19c347dc4f6129139fed19a536b43dd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TrigExpFunctions.java
@@ -51,6 +51,7 @@ public class TrigExpFunctions {
         }
 
         protected double op(@SuppressWarnings("unused") double x) {
+            // not abstract because this would confuse the DSL annotation processor
             throw RInternalError.shouldNotReachHere("this method needs to be implemented in subclasses");
         }
 
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 a65dbc2ae0a26e890167c5e3c7aa75a66b9c4747..8340526e313bd3bbd74333064ff14946f6eb7994 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
@@ -142,15 +142,6 @@ public final class RTruffleVisitor extends BasicVisitor<RSyntaxNode> {
 
     @Override
     public RSyntaxNode visit(Function func) {
-// FastPathFactory f = EvaluatedArgumentsVisitor.process(func);
-// if (f != null) {
-// System.out.println("////////////////////////////////");
-// if (func.getDebugName() != null) {
-// System.out.println("// " + func.getDebugName());
-// }
-// System.out.println(func.getSource().getCode());
-// System.out.println("names: " + f + "\n");
-// }
         RootCallTarget callTarget = null;
         try {
             callTarget = createFunctionCallTarget(func);
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 5a54b08ad797cf5268242394a573dedd98d565c5..65ffe8de46ee7b9c3fc4055dad9cd39d37b1d048 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
@@ -86,12 +86,12 @@ import com.oracle.truffle.r.runtime.nodes.*;
  *  U = {@link UninitializedCallNode}: Forms the uninitialized end of the function PIC
  *  D = {@link DispatchedCallNode}: Function fixed, no varargs
  *  G = {@link GenericCallNode}: Function arbitrary
- * 
+ *
  *  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)
- * 
+ *
  * (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)
@@ -104,11 +104,11 @@ import com.oracle.truffle.r.runtime.nodes.*;
  * 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
@@ -116,7 +116,7 @@ import com.oracle.truffle.r.runtime.nodes.*;
  *    DV
  *    |
  *    UVC           <- varargs signature level cache
- * 
+ *
  * varargs, max varargs depth exceeded:
  * |
  * DV-DV-UV
@@ -128,7 +128,7 @@ import com.oracle.truffle.r.runtime.nodes.*;
  *    DV
  *    |
  *    DGV
- * 
+ *
  * varargs, max function depth exceeded:
  * |
  * DV-DV-DV-DV-GV
@@ -166,6 +166,8 @@ public final class RCallNode extends RNode implements RSyntaxNode {
     private static final int FUNCTION_INLINE_CACHE_SIZE = 4;
     private static final int VARARGS_INLINE_CACHE_SIZE = 4;
 
+    private static final Object[] defaultTempIdentifiers = new Object[]{new Object(), new Object(), new Object(), new Object()};
+
     @Child private RNode functionNode;
     @Child private PromiseHelperNode promiseHelper;
     @Child private RootCallNode call;
@@ -203,8 +205,6 @@ public final class RCallNode extends RNode implements RSyntaxNode {
     private final SyntaxArguments arguments;
     private final ArgumentsSignature signature;
 
-    private final Object tempIdentifier = new Object();
-
     private final ValueProfile builtinProfile = ValueProfile.createIdentityProfile();
     private final ConditionProfile implicitTypeProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile resultIsBuiltinProfile = ConditionProfile.createBinaryProfile();
@@ -213,6 +213,8 @@ public final class RCallNode extends RNode implements RSyntaxNode {
     private final BranchProfile errorProfile = BranchProfile.create();
     private final ConditionProfile isRFunctionProfile = ConditionProfile.createBinaryProfile();
 
+    private int tempIdentifier;
+
     @Child private Node foreignCall;
     @CompilationFinal private int foreignCallArgCount;
     @Child private CallArgumentsNode foreignCallArguments;
@@ -267,13 +269,28 @@ public final class RCallNode extends RNode implements RSyntaxNode {
             if (builtin.getDispatch() == RDispatch.INTERNAL_GENERIC) {
                 if (internalDispatchCall == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
-                    dispatchTempSlot = insert(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), tempIdentifier, true));
-                    internalDispatchCall = insert(new UninitializedCallNode(this, tempIdentifier));
+                    dispatchTempSlot = insert(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), defaultTempIdentifiers[0], true));
+                    internalDispatchCall = insert(new UninitializedCallNode(this, defaultTempIdentifiers[0]));
                     dispatchArgument = insert(NodeUtil.cloneNode(arguments.v[0].asRNode()));
                     dispatchLookup = insert(S3FunctionLookupNode.create(true, false));
                     classHierarchyNode = insert(ClassHierarchyNodeGen.create(false));
                 }
                 FrameSlot slot = dispatchTempSlot.executeFrameSlot(frame);
+                try {
+                    if (frame.isObject(slot) && frame.getObject(slot) != null) {
+                        CompilerDirectives.transferToInterpreterAndInvalidate();
+                        // keep the complete loop in the slow path
+                        do {
+                            tempIdentifier++;
+                            Object identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : new Object();
+                            dispatchTempSlot.replace(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), identifier, true));
+                            internalDispatchCall.replace(new UninitializedCallNode(this, identifier));
+                            slot = dispatchTempSlot.executeFrameSlot(frame);
+                        } while (frame.isObject(slot) && frame.getObject(slot) != null);
+                    }
+                } catch (FrameSlotTypeException e) {
+                    throw RInternalError.shouldNotReachHere();
+                }
                 try {
                     Object dispatch = dispatchArgument.execute(frame);
                     frame.setObject(slot, dispatch);
@@ -816,8 +833,6 @@ public final class RCallNode extends RNode implements RSyntaxNode {
             this.fastPath = function.getFastPath() == null ? null : function.getFastPath().create();
             if (fastPath == null) {
                 this.call = Truffle.getRuntime().createDirectCallNode(function.getTarget());
-            } else {
-// System.out.println("created fast path " + fastPath);
             }
         }
 
@@ -830,7 +845,6 @@ public final class RCallNode extends RNode implements RSyntaxNode {
                 }
                 CompilerDirectives.transferToInterpreterAndInvalidate();
                 fastPath = null;
-// System.out.println("falling back to method execution");
                 call = insert(Truffle.getRuntime().createDirectCallNode(callTarget));
             }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
index 509fdaf3ecde3458552ff8e8d43c37aaa95ae8b9..fb258a3dd7f7ee6c17c2106873339e6dc165e28c 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/BinaryMapNode.java
@@ -125,7 +125,7 @@ public final class BinaryMapNode extends RBaseNode {
         int[] leftDimensions = left.getDimensions();
         int[] rightDimensions = right.getDimensions();
         int leftLength = leftDimensions.length;
-        int rightLength = leftDimensions.length;
+        int rightLength = rightDimensions.length;
         if (leftLength != rightLength) {
             return true;
         }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/FastPathFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/FastPathFactory.java
index e5b4d03fb40500fd8ef2935e306eaca5bff869f0..ae926e03902f4783eead60a70b156a00161d36ff 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/FastPathFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/FastPathFactory.java
@@ -25,7 +25,10 @@ package com.oracle.truffle.r.runtime.data;
 import com.oracle.truffle.r.runtime.nodes.*;
 
 /**
- * This implies that all arguments can be evaluated eagerly.
+ * This interface can be used to provide a fast path, implemented in Java, for an R function. This
+ * may be useful for cases in which there is a significantly simpler implementation for a known
+ * configuration of arguments. Returning {@code null} from the fast path node will revert the call
+ * site so that it calls the normal R code again.
  */
 @FunctionalInterface
 public interface FastPathFactory {
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 201d764c35a9741970e67ded5bed49ef28c217e8..0acbdafe954d70ef93bd6d71248274c59cef9ba0 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
@@ -906,6 +906,10 @@ public abstract class BinaryArithmetic extends Operation {
 
     private static class Max extends BinaryArithmetic {
 
+        private final BranchProfile incomparableProfile = BranchProfile.create();
+        private final BranchProfile zeroProfile = BranchProfile.create();
+        private final ConditionProfile compareProfile = ConditionProfile.createBinaryProfile();
+
         public Max() {
             super(true, true, true);
         }
@@ -924,11 +928,13 @@ public abstract class BinaryArithmetic extends Operation {
         public double op(double left, double right) {
             // explicit checks, since Math.max uses a non-final static field
             if (left != left) {
+                incomparableProfile.enter();
                 return left;
             } else if (left == 0.0d && right == 0.0d && Double.doubleToRawLongBits(left) == Double.doubleToRawLongBits(-0.0d)) {
+                zeroProfile.enter();
                 return right;
             } else {
-                return left >= right ? left : right;
+                return compareProfile.profile(left >= right) ? left : right;
             }
         }
 
@@ -947,6 +953,10 @@ public abstract class BinaryArithmetic extends Operation {
 
     private static class Min extends BinaryArithmetic {
 
+        private final BranchProfile incomparableProfile = BranchProfile.create();
+        private final BranchProfile zeroProfile = BranchProfile.create();
+        private final ConditionProfile compareProfile = ConditionProfile.createBinaryProfile();
+
         public Min() {
             super(true, true, true);
         }
@@ -963,13 +973,15 @@ public abstract class BinaryArithmetic extends Operation {
 
         @Override
         public double op(double left, double right) {
-            // explicit checks, since Math.max uses a non-final static field
+            // explicit checks, since Math.min uses a non-final static field
             if (left != left) {
+                incomparableProfile.enter();
                 return left;
             } else if (left == 0.0d && right == 0.0d && Double.doubleToRawLongBits(right) == Double.doubleToRawLongBits(-0.0d)) {
+                zeroProfile.enter();
                 return right;
             } else {
-                return left <= right ? left : right;
+                return compareProfile.profile(left <= right) ? left : right;
             }
         }