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 a6b47df08fbe1e6680aceccc60eb82e8b5dbc14e..2175be7d030ab6664ce01b7a2e5ab52691aa31f8 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
@@ -164,35 +164,33 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
     }
 
     @ExplodeLoop
-    public RArgsValuesAndNames evaluateFlatten(VirtualFrame frame, RArgsValuesAndNames varArgs) {
-        int size = arguments.length;
-        ArgumentsSignature resultSignature = null;
+    public ArgumentsSignature flattenNames(RArgsValuesAndNames varArgs) {
         String[] names = null;
-        if (containsVarArgsSymbol()) {
-            size += (varArgs.getLength() - 1) * varArgsSymbolIndices.length;
-            names = new String[size];
-        } else {
-            resultSignature = signature;
+        if (!containsVarArgsSymbol()) {
+            return signature;
         }
-        Object[] values = new Object[size];
+        int size = arguments.length + (varArgs.getLength() - 1) * varArgsSymbolIndices.length;
+        names = new String[size];
         int vargsSymbolsIndex = 0;
         int index = 0;
         for (int i = 0; i < arguments.length; i++) {
             if (vargsSymbolsIndex < varArgsSymbolIndices.length && varArgsSymbolIndices[vargsSymbolsIndex] == i) {
-                index = flattenVarArgs(frame, varArgs, names, values, index);
+                index = flattenVarArgNames(varArgs, names, index);
                 vargsSymbolsIndex++;
             } else {
-                values[index] = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame);
-                if (names != null) {
-                    names[index] = signature.getName(i);
-                }
-                index++;
+                names[index++] = signature.getName(i);
             }
         }
-        if (resultSignature == null) {
-            resultSignature = ArgumentsSignature.get(names);
+        return ArgumentsSignature.get(names);
+    }
+
+    private static int flattenVarArgNames(RArgsValuesAndNames varArgInfo, String[] names, int startIndex) {
+        int index = startIndex;
+        for (int j = 0; j < varArgInfo.getLength(); j++) {
+            names[index] = varArgInfo.getSignature().getName(j);
+            index++;
         }
-        return new RArgsValuesAndNames(values, resultSignature);
+        return index;
     }
 
     @ExplodeLoop
@@ -216,7 +214,7 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
         return values;
     }
 
-    private int flattenVarArgs(VirtualFrame frame, RArgsValuesAndNames varArgInfo, String[] names, Object[] values, int startIndex) {
+    private int flattenVarArgsObject(VirtualFrame frame, RArgsValuesAndNames varArgInfo, Object[] values, int startIndex) {
         int index = startIndex;
         for (int j = 0; j < varArgInfo.getLength(); j++) {
             if (promiseHelper == null) {
@@ -224,7 +222,6 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
                 promiseHelper = insert(new PromiseCheckHelperNode());
             }
             values[index] = promiseHelper.checkEvaluate(frame, varArgInfo.getArgument(j));
-            names[index] = varArgInfo.getSignature().getName(j);
             index++;
         }
         return index;
@@ -265,17 +262,4 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum
         }
         return result;
     }
-
-    private int flattenVarArgsObject(VirtualFrame frame, RArgsValuesAndNames varArgInfo, Object[] values, int startIndex) {
-        int index = startIndex;
-        for (int j = 0; j < varArgInfo.getLength(); j++) {
-            if (promiseHelper == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                promiseHelper = insert(new PromiseCheckHelperNode());
-            }
-            values[index] = promiseHelper.checkEvaluate(frame, varArgInfo.getArgument(j));
-            index++;
-        }
-        return index;
-    }
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
index 2f927add9f63457dbc41c674363a543a23317eca..3fd1262d5da9de9454e1510cf9bebcd44c0eb255 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/FunctionDefinitionNode.java
@@ -129,6 +129,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
      * Profiling for catching {@link ReturnException}s.
      */
     private final BranchProfile returnProfile = BranchProfile.create();
+    private final ConditionProfile returnTopLevelProfile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile returnHereProfile = ConditionProfile.createBinaryProfile();
 
     public static FunctionDefinitionNode create(SourceSection src, FrameDescriptor frameDesc, SourceSection[] argSourceSections, SaveArgumentsNode saveArguments, RSyntaxNode body,
@@ -262,7 +263,7 @@ public final class FunctionDefinitionNode extends RRootNode implements RSyntaxNo
         } catch (ReturnException ex) {
             returnProfile.enter();
             int depth = ex.getDepth();
-            if (returnHereProfile.profile(depth != -1 && RArguments.getDepth(frame) != depth)) {
+            if (returnTopLevelProfile.profile(depth != -1) && returnHereProfile.profile(RArguments.getDepth(frame) != depth)) {
                 throw ex;
             } else {
                 return ex.getResult();
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 e117aeaedcbcc941d2f6a5c5e2af6f7673d4fdfd..5f38938b8713280ce8c5e9e997d92d557178e2d4 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
@@ -138,6 +138,7 @@ public class PromiseHelperNode extends RBaseNode {
     private final ValueProfile multiVarArgsOptTypeProfile = ValueProfile.createIdentityProfile();
     private final ValueProfile promiseFrameProfile = ValueProfile.createClassProfile();
     private final BranchProfile varArgProfile = BranchProfile.create();
+    private final ConditionProfile chckPromiseMismatch = ConditionProfile.createBinaryProfile();
 
     /**
      * Guarded by {@link #isInOriginFrame(VirtualFrame,RPromise)}.
@@ -236,13 +237,20 @@ public class PromiseHelperNode extends RBaseNode {
      * can occur so we don't need the {@link PromiseEvalFrame} (even if the frames are different).
      *
      */
-    private static Frame checkCreatePromiseEvalFrame(Frame frame, Frame promiseFrame, RPromise promise) {
-        if (frame != null && RArguments.getDepth(frame) != RArguments.getDepth(promiseFrame)) {
+    private Frame checkCreatePromiseEvalFrame(Frame frame, Frame promiseFrame, RPromise promise) {
+        if (frame != null && chckPromiseMismatch.profile(RArguments.getDepth(frame) != RArguments.getDepth(promiseFrame))) {
             return PromiseEvalFrame.create(frame, promiseFrame.materialize(), promise);
         } else {
             return promiseFrame;
         }
+    }
 
+    private static Frame checkCreatePromiseEvalFrameSlowPath(Frame frame, Frame promiseFrame, RPromise promise) {
+        if (frame != null && RArguments.getDepth(frame) != RArguments.getDepth(promiseFrame)) {
+            return PromiseEvalFrame.create(frame, promiseFrame.materialize(), promise);
+        } else {
+            return promiseFrame;
+        }
     }
 
     private Object generateValueEager(VirtualFrame frame, OptType optType, EagerPromise promise) {
@@ -313,7 +321,7 @@ public class PromiseHelperNode extends RBaseNode {
                 Frame promiseFrame = promise.getFrame();
                 assert promiseFrame != null;
                 try {
-                    Frame promiseEvalFrame = checkCreatePromiseEvalFrame(frame, promiseFrame, promise);
+                    Frame promiseEvalFrame = checkCreatePromiseEvalFrameSlowPath(frame, promiseFrame, promise);
                     if (PromiseEvalFrameDebug.enabled) {
                         PromiseEvalFrameDebug.doPromiseEval(true, frame, promiseFrame, promise);
                     }
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 7117b9d93ec754301f8f7e949ca6323419441b4a..944d1f1fb24625ea734dbefbbfa81d8b06ec6bc5 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
@@ -68,7 +68,6 @@ import com.oracle.truffle.r.nodes.function.RCallNodeGen.FunctionDispatchNodeGen;
 import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.NoGenericMethodException;
 import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result;
 import com.oracle.truffle.r.nodes.function.call.PrepareArguments;
-import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
 import com.oracle.truffle.r.runtime.Arguments;
@@ -409,12 +408,12 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
                     @Cached("createPromiseHelper()") PromiseCheckHelperNode promiseHelperNode, //
                     @Cached("createUninitializedExplicitCall()") FunctionDispatch call) {
 
-        RArgsValuesAndNames argAndNames = explicitArgs != null ? (RArgsValuesAndNames) explicitArgs.execute(frame) : callArguments.evaluateFlatten(frame, lookupVarArgs(frame));
+        Object[] args = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getArguments() : callArguments.evaluateFlattenObjects(frame, lookupVarArgs(frame));
 
         RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin());
         RDispatch dispatch = builtin.getDispatch();
 
-        RStringVector typeX = classHierarchyNodeX.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(0)));
+        RStringVector typeX = classHierarchyNodeX.execute(promiseHelperNode.checkEvaluate(frame, args[0]));
         Result resultX = null;
         if (implicitTypeProfileX.profile(typeX != null)) {
             try {
@@ -424,8 +423,8 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
             }
         }
         Result resultY = null;
-        if (argAndNames.getLength() > 1 && dispatch == RDispatch.OPS_GROUP_GENERIC) {
-            RStringVector typeY = classHierarchyNodeY.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(1)));
+        if (args.length > 1 && dispatch == RDispatch.OPS_GROUP_GENERIC) {
+            RStringVector typeY = classHierarchyNodeY.execute(promiseHelperNode.checkEvaluate(frame, args[1]));
             if (implicitTypeProfileY.profile(typeY != null)) {
                 try {
                     resultY = dispatchLookupY.execute(frame, builtin.getName(), typeY, dispatch.getGroupGenericName(), frame.materialize(), null);
@@ -460,20 +459,24 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
                 }
             }
         }
-        S3Args s3Args;
-        RFunction resultFunction;
+        final S3Args s3Args;
+        final RFunction resultFunction;
+        final ArgumentsSignature argsSignature;
         if (result == null) {
             s3Args = null;
             resultFunction = function;
+            argsSignature = ArgumentsSignature.empty(args.length);
         } else {
             if (resultIsBuiltinProfile.profile(result.function.isBuiltin())) {
                 s3Args = null;
+                argsSignature = ArgumentsSignature.empty(args.length);
             } else {
                 s3Args = new S3Args(builtin.getName(), result.clazz, dotMethod, frame.materialize(), null, result.groupMatch ? dispatch.getGroupGenericName() : null);
+                argsSignature = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getSignature() : callArguments.flattenNames(lookupVarArgs(frame));
             }
             resultFunction = result.function;
         }
-        return call.execute(frame, resultFunction, argAndNames, s3Args);
+        return call.execute(frame, resultFunction, new RArgsValuesAndNames(args, argsSignature), s3Args);
     }
 
     protected class ForeignCall extends Node {
@@ -964,7 +967,6 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
     private static final class DispatchedCallNode extends LeafCallNode {
 
         @Child private DirectCallNode call;
-        @Child private RArgumentsNode argsNode;
         @Child private RFastPathNode fastPath;
 
         private final ArgumentsSignature signature;
@@ -989,17 +991,16 @@ public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCal
                 fastPath = null;
             }
 
-            if (argsNode == null) {
+            if (call == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                argsNode = insert(RArgumentsNode.create());
                 call = insert(Truffle.getRuntime().createDirectCallNode(cachedFunction.getTarget()));
                 if (needsSplitting(cachedFunction)) {
                     call.cloneCallTarget();
                 }
             }
-            MaterializedFrame callerFrame = CompilerDirectives.inInterpreter() || originalCall.needsCallerFrame ? frame.materialize() : null;
-            Object[] argsObject = argsNode.execute(cachedFunction, originalCall.createCaller(frame, cachedFunction), callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame),
-                            orderedArguments, signature, s3Args);
+            MaterializedFrame callerFrame = /* CompilerDirectives.inInterpreter() || */originalCall.needsCallerFrame ? frame.materialize() : null;
+            Object[] argsObject = RArguments.create(cachedFunction, originalCall.createCaller(frame, cachedFunction), callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame),
+                            orderedArguments, signature, cachedFunction.getEnclosingFrame(), s3Args);
             return call.call(frame, argsObject);
         }
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java
index 9de276c9d04a3b1133b0e61060d795002058e336..721826a0a6a8c6e36ef3a5b5a0f19530873f0698 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/OptVariablePromiseBaseNode.java
@@ -28,6 +28,7 @@ import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.InvalidAssumptionException;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.access.FrameSlotNode;
 import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
 import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
@@ -51,6 +52,7 @@ public abstract class OptVariablePromiseBaseNode extends PromiseNode implements
     private final int wrapIndex;
 
     private final ConditionProfile promiseEvalFrameProfile = ConditionProfile.createBinaryProfile();
+    private final ValueProfile frameProfile = ValueProfile.createClassProfile();
 
     public OptVariablePromiseBaseNode(RPromiseFactory factory, ReadVariableNode rvn, int wrapIndex) {
         super(factory);
@@ -71,7 +73,7 @@ public abstract class OptVariablePromiseBaseNode extends PromiseNode implements
     public Object execute(VirtualFrame initialFrame) {
         VirtualFrame frame;
         if (promiseEvalFrameProfile.profile(initialFrame instanceof PromiseEvalFrame)) {
-            frame = SubstituteVirtualFrame.create(((PromiseEvalFrame) initialFrame).getOriginalFrame());
+            frame = frameProfile.profile(SubstituteVirtualFrame.create(((PromiseEvalFrame) initialFrame).getOriginalFrame()));
         } else {
             frame = initialFrame;
         }
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 69da8f799bce1ea6f825880c4359a1292fceeb39..af7d7af6ec7e74c8c527523e9c58216cd6736c29 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
@@ -29,6 +29,7 @@ import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.FrameSlot;
 import com.oracle.truffle.api.frame.FrameSlotTypeException;
 import com.oracle.truffle.api.frame.MaterializedFrame;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.RArguments;
 
 /**
@@ -38,6 +39,8 @@ import com.oracle.truffle.r.runtime.RArguments;
  */
 public final class NSBaseMaterializedFrame implements MaterializedFrame {
 
+    private static final ValueProfile frameProfile = ValueProfile.createClassProfile();
+
     private final MaterializedFrame packageBaseFrame;
     @CompilationFinal private final Object[] arguments;
 
@@ -52,6 +55,10 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame {
         RArguments.initializeEnclosingFrame(this, globalFrame);
     }
 
+    private MaterializedFrame getPackageBaseFrame() {
+        return frameProfile.profile(packageBaseFrame);
+    }
+
     public void updateGlobalFrame(MaterializedFrame globalFrame) {
         RArguments.setEnclosingFrame(this, globalFrame);
     }
@@ -62,7 +69,7 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame {
 
     @Override
     public FrameDescriptor getFrameDescriptor() {
-        return packageBaseFrame.getFrameDescriptor();
+        return getPackageBaseFrame().getFrameDescriptor();
     }
 
     @Override
@@ -81,111 +88,111 @@ public final class NSBaseMaterializedFrame implements MaterializedFrame {
 
     @Override
     public Object getObject(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getObject(slot);
+        return getPackageBaseFrame().getObject(slot);
     }
 
     @Override
     public void setObject(FrameSlot slot, Object value) {
-        packageBaseFrame.setObject(slot, value);
+        getPackageBaseFrame().setObject(slot, value);
     }
 
     @Override
     public byte getByte(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getByte(slot);
+        return getPackageBaseFrame().getByte(slot);
     }
 
     @Override
     public void setByte(FrameSlot slot, byte value) {
-        packageBaseFrame.setByte(slot, value);
+        getPackageBaseFrame().setByte(slot, value);
     }
 
     @Override
     public boolean getBoolean(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getBoolean(slot);
+        return getPackageBaseFrame().getBoolean(slot);
     }
 
     @Override
     public void setBoolean(FrameSlot slot, boolean value) {
-        packageBaseFrame.setBoolean(slot, value);
+        getPackageBaseFrame().setBoolean(slot, value);
     }
 
     @Override
     public int getInt(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getInt(slot);
+        return getPackageBaseFrame().getInt(slot);
     }
 
     @Override
     public void setInt(FrameSlot slot, int value) {
-        packageBaseFrame.setInt(slot, value);
+        getPackageBaseFrame().setInt(slot, value);
     }
 
     @Override
     public long getLong(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getLong(slot);
+        return getPackageBaseFrame().getLong(slot);
     }
 
     @Override
     public void setLong(FrameSlot slot, long value) {
-        packageBaseFrame.setLong(slot, value);
+        getPackageBaseFrame().setLong(slot, value);
     }
 
     @Override
     public float getFloat(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getFloat(slot);
+        return getPackageBaseFrame().getFloat(slot);
     }
 
     @Override
     public void setFloat(FrameSlot slot, float value) {
-        packageBaseFrame.setFloat(slot, value);
+        getPackageBaseFrame().setFloat(slot, value);
     }
 
     @Override
     public double getDouble(FrameSlot slot) throws FrameSlotTypeException {
-        return packageBaseFrame.getDouble(slot);
+        return getPackageBaseFrame().getDouble(slot);
     }
 
     @Override
     public void setDouble(FrameSlot slot, double value) {
-        packageBaseFrame.setDouble(slot, value);
+        getPackageBaseFrame().setDouble(slot, value);
     }
 
     @Override
     public Object getValue(FrameSlot slot) {
-        return packageBaseFrame.getValue(slot);
+        return getPackageBaseFrame().getValue(slot);
     }
 
     @Override
     public boolean isObject(FrameSlot slot) {
-        return packageBaseFrame.isObject(slot);
+        return getPackageBaseFrame().isObject(slot);
     }
 
     @Override
     public boolean isByte(FrameSlot slot) {
-        return packageBaseFrame.isByte(slot);
+        return getPackageBaseFrame().isByte(slot);
     }
 
     @Override
     public boolean isBoolean(FrameSlot slot) {
-        return packageBaseFrame.isBoolean(slot);
+        return getPackageBaseFrame().isBoolean(slot);
     }
 
     @Override
     public boolean isInt(FrameSlot slot) {
-        return packageBaseFrame.isInt(slot);
+        return getPackageBaseFrame().isInt(slot);
     }
 
     @Override
     public boolean isLong(FrameSlot slot) {
-        return packageBaseFrame.isLong(slot);
+        return getPackageBaseFrame().isLong(slot);
     }
 
     @Override
     public boolean isFloat(FrameSlot slot) {
-        return packageBaseFrame.isFloat(slot);
+        return getPackageBaseFrame().isFloat(slot);
     }
 
     @Override
     public boolean isDouble(FrameSlot slot) {
-        return packageBaseFrame.isDouble(slot);
+        return getPackageBaseFrame().isDouble(slot);
     }
 }