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 218c85fb302cb5341c0f4bf8f7a07b4fc223ea7d..c91b540d984603509828bab1babf4d7ee0d53cef 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
@@ -368,7 +368,7 @@ final class REngine implements RContext.Engine {
     }
 
     private static class PromiseStatement extends RNode implements RSyntaxNode {
-        private final RNode promise;
+        @Child private RNode promise;
 
         PromiseStatement(RNode promise) {
             this.promise = promise;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
index fee526fb24d93758304126acada6cba2369a575b..8cb0169ecb68770aa7d627e3972e24a94c121f84 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsCharacter.java
@@ -156,7 +156,7 @@ public abstract class AsCharacter extends RBuiltinNode {
         controlVisibility();
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode(NAME, getSuppliedSignature()));
+            dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.get(""), true));
         }
         try {
             return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container});
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 8a78269e7a9d538261d39efa68b1ccc60c04ed80..f75dc25d65fe10354c0e4caa559104e036ccd766 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
@@ -78,7 +78,7 @@ public abstract class Bind extends RPrecedenceBuiltinNode {
     protected Object allDataFrame(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args) {
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode(getBindType(), SIGNATURE));
+            dcn = insert(new UseMethodInternalNode(getBindType(), SIGNATURE, false));
         }
         try {
             return dcn.execute(frame, ((RDataFrame) args.getArgument(0)).getClassHierarchy(), new Object[]{deparseLevel, args});
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 db06401b4990b145ba609d1d72d195c0975f5345..d4e6dc37dd2bbce00a09ec31770a220b6bc2054b 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
@@ -97,7 +97,7 @@ public abstract class Dim extends RBuiltinNode {
         controlVisibility();
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode(NAME, getSuppliedSignature()));
+            dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.get(""), true));
         }
         try {
             return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container});
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
index ae0cc13814cb1f6c93c92ec7f3c1870f993d5caa..e91c5ea498b407852ecb66ff8dc7e527166a5bbf 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java
@@ -71,7 +71,7 @@ public abstract class DimNames extends RBuiltinNode {
         controlVisibility();
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode(NAME, getSuppliedSignature()));
+            dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.get(""), true));
         }
         try {
             return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container});
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 2bed762f38e730e726beb4dee1ef0975af53899e..3c4b5a86dd127f57ae307880b647fc56af8753a8 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
@@ -279,7 +279,7 @@ public class InfixEmulationFunctions {
         protected Object getObj(VirtualFrame frame, RAbstractContainer x, RArgsValuesAndNames inds, RAbstractLogicalVector dropVec) {
             if (dcn == null || noDrop) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dcn = insert(new UseMethodInternalNode(NAME, SIGNATURE));
+                dcn = insert(new UseMethodInternalNode(NAME, SIGNATURE, true));
                 noDrop = false;
             }
             try {
@@ -298,7 +298,7 @@ public class InfixEmulationFunctions {
         protected Object getObj(VirtualFrame frame, RAbstractContainer x, RArgsValuesAndNames inds, RMissing dropVec) {
             if (dcn == null || !noDrop) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dcn = insert(new UseMethodInternalNode(NAME, SIGNATURE_NODROP));
+                dcn = insert(new UseMethodInternalNode(NAME, SIGNATURE_NODROP, true));
                 noDrop = true;
             }
             try {
@@ -406,7 +406,7 @@ public class InfixEmulationFunctions {
             }
             if (dcn == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dcn = insert(new UseMethodInternalNode(NAME, SIGNATURE));
+                dcn = insert(new UseMethodInternalNode(NAME, SIGNATURE, true));
             }
             try {
                 return dcn.execute(frame, x.getClassHierarchy(), new Object[]{x, inds, exactVec});
@@ -505,7 +505,7 @@ public class InfixEmulationFunctions {
         protected Object updateObj(VirtualFrame frame, RAbstractContainer x, RArgsValuesAndNames args) {
             if (dcn == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dcn = insert(new UseMethodInternalNode(NAME, SIGNATURE));
+                dcn = insert(new UseMethodInternalNode(NAME, SIGNATURE, true));
             }
             try {
                 return dcn.execute(frame, x.getClassHierarchy(), new Object[]{x, args});
@@ -540,7 +540,7 @@ public class InfixEmulationFunctions {
         protected Object updateObj(VirtualFrame frame, RAbstractContainer x, RArgsValuesAndNames args) {
             if (dcn == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.empty(2)));
+                dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.empty(2), true));
             }
             try {
                 return dcn.execute(frame, x.getClassHierarchy(), new Object[]{x, args});
@@ -641,7 +641,7 @@ public class InfixEmulationFunctions {
             }
             if (dcn == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.get("", "")));
+                dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.get("", ""), true));
             }
             try {
                 return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container, field});
@@ -688,7 +688,7 @@ public class InfixEmulationFunctions {
             }
             if (dcn == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
-                dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.get("", "", "")));
+                dcn = insert(new UseMethodInternalNode(NAME, ArgumentsSignature.get("", "", ""), true));
             }
             try {
                 return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container, field, value});
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
index 3a6f867400c59f53b68905152c0969ba38431d1d..5d1eac015336adf550e5350f22abfaddcdca1b68 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLength.java
@@ -54,7 +54,7 @@ public abstract class UpdateLength extends RInvisibleBuiltinNode {
     protected Object updateLengthObject(VirtualFrame frame, RAbstractContainer container, RAbstractIntVector lengthVector) {
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode("length<-", getSuppliedSignature()));
+            dcn = insert(new UseMethodInternalNode("length<-", getSuppliedSignature(), true));
         }
         try {
             return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container, lengthVector});
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 b2fc92a3cbf777892f89bc146118b2ec6fd553ee..221ea020fc0d3041e44c4ec3789460d2e99a81c9 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
@@ -101,7 +101,7 @@ public abstract class AccessFieldNode extends RNode implements RSyntaxNode {
     protected Object accessField(VirtualFrame frame, RAbstractContainer container, String field) {
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode("$", ArgumentsSignature.get("", "")));
+            dcn = insert(new UseMethodInternalNode("$", ArgumentsSignature.get("", ""), true));
         }
         try {
             return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container, field});
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 ee91fa1566f0c3dcba3e12168fd2677f9fb939bc..5ead259fd410d5f203a27dc2d70c3f29866d059c 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
@@ -90,7 +90,7 @@ public abstract class UpdateFieldNode extends UpdateNode implements RSyntaxNode
     protected Object accessField(VirtualFrame frame, RAbstractContainer container, Object value, String field) {
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode("$<-", ArgumentsSignature.get("", "", "")));
+            dcn = insert(new UseMethodInternalNode("$<-", ArgumentsSignature.get("", "", ""), true));
         }
         try {
             return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container, field, value});
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java
index e966ba5a89c5a1bc05a8cd06d18777281f7cbd50..ba5a37c0e39f5567927be6b80185ff1a1b1b786d 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/WriteVariableNode.java
@@ -25,6 +25,7 @@ package com.oracle.truffle.r.nodes.access;
 import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.source.*;
 import com.oracle.truffle.r.nodes.*;
+import com.oracle.truffle.r.options.*;
 import com.oracle.truffle.r.runtime.*;
 
 /**
@@ -62,7 +63,11 @@ public abstract class WriteVariableNode extends RNode {
      * Variant for saving function arguments, i.e. from {@link RArguments} into the frame.
      */
     public static WriteVariableNode createArgSave(String name, RNode rhs) {
-        return WriteLocalFrameVariableNode.create(name, rhs, Mode.REGULAR);
+        if (FastROptions.InvisibleArgs.getValue()) {
+            return WriteLocalFrameVariableNode.create(name, rhs, Mode.INVISIBLE);
+        } else {
+            return WriteLocalFrameVariableNode.create(name, rhs, Mode.REGULAR);
+        }
     }
 
     /**
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 e0738e98c8d06bbda7e5cc7f9220e2a7f19e6674..7f7a1a65e49acb7249554f43d204d47d8f32d8c1 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
@@ -287,13 +287,13 @@ public abstract class AccessArrayNode extends RNode implements RSyntaxNode {
             if (dropDim != RMissing.instance) {
                 if (dcnDrop == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
-                    dcnDrop = insert(new UseMethodInternalNode("[", DROP_SIGNATURE));
+                    dcnDrop = insert(new UseMethodInternalNode("[", DROP_SIGNATURE, true));
                 }
                 return dcnDrop.execute(frame, container.getClassHierarchy(), new Object[]{container, inds, dropDim});
             } else {
                 if (dcn == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
-                    dcn = insert(new UseMethodInternalNode("[", SIGNATURE));
+                    dcn = insert(new UseMethodInternalNode("[", SIGNATURE, true));
                 }
                 return dcn.execute(frame, container.getClassHierarchy(), new Object[]{container, inds});
             }
@@ -306,7 +306,7 @@ public abstract class AccessArrayNode extends RNode implements RSyntaxNode {
     protected Object accessObject(VirtualFrame frame, RAbstractContainer container, Object exact, int recLevel, Object position, Object dropDim) {
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode("[[", EXACT_SIGNATURE));
+            dcn = insert(new UseMethodInternalNode("[[", EXACT_SIGNATURE, true));
         }
         try {
             Object inds = position instanceof Object[] ? new RArgsValuesAndNames((Object[]) position, ArgumentsSignature.empty(((Object[]) position).length)) : position;
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 1dbf83443dd8a41056741a9bb5db52f8bcf7b126..5d82cd8596530b2cbf3877bf9846b608557ccc28 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
@@ -262,7 +262,7 @@ public abstract class UpdateArrayHelperNode extends UpdateNode implements RSynta
     protected Object updateObjectSubset(VirtualFrame frame, Object v, Object value, Object positions, RAbstractContainer container) {
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode("[<-", VALUE_SIGNATURE));
+            dcn = insert(new UseMethodInternalNode("[<-", VALUE_SIGNATURE, true));
         }
         try {
             Object inds = positions instanceof Object[] ? new RArgsValuesAndNames((Object[]) positions, ArgumentsSignature.empty(((Object[]) positions).length)) : positions;
@@ -276,7 +276,7 @@ public abstract class UpdateArrayHelperNode extends UpdateNode implements RSynta
     protected Object updateObject(VirtualFrame frame, Object v, Object value, Object positions, RAbstractContainer container) {
         if (dcn == null) {
             CompilerDirectives.transferToInterpreterAndInvalidate();
-            dcn = insert(new UseMethodInternalNode("[[<-", VALUE_SIGNATURE));
+            dcn = insert(new UseMethodInternalNode("[[<-", VALUE_SIGNATURE, true));
         }
         try {
             Object inds = positions instanceof Object[] ? new RArgsValuesAndNames((Object[]) positions, ArgumentsSignature.empty(((Object[]) positions).length)) : positions;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java
index 6161a5f1bb457c591dc5a459ad8f626bd46db993..1b4b3b32d9255988e793afec5cf2b435800f475a 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java
@@ -10,9 +10,12 @@
  */
 package com.oracle.truffle.r.nodes.function;
 
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.frame.*;
+import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.nodes.*;
 import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result;
+import com.oracle.truffle.r.options.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.RArguments.S3Args;
 import com.oracle.truffle.r.runtime.data.*;
@@ -22,17 +25,44 @@ public final class UseMethodInternalNode extends RNode implements VisibilityCont
     @Child private S3FunctionLookupNode lookup = S3FunctionLookupNode.create(false, false);
     @Child private CallMatcherNode callMatcher = CallMatcherNode.create(false, false);
 
+    @CompilationFinal private final BranchProfile[] everSeenShared;
+    @CompilationFinal private final BranchProfile[] everSeenTemporary;
+    @CompilationFinal private final BranchProfile[] everSeenNonTemporary;
+
     private final String generic;
     private final ArgumentsSignature signature;
+    private final boolean wrap;
 
-    public UseMethodInternalNode(String generic, ArgumentsSignature signature) {
+    public UseMethodInternalNode(String generic, ArgumentsSignature signature, boolean wrap) {
         this.generic = generic;
         this.signature = signature;
+        this.wrap = wrap && FastROptions.InvisibleArgs.getValue();
+        if (this.wrap) {
+            int len = signature.getLength();
+            everSeenShared = new BranchProfile[len];
+            everSeenTemporary = new BranchProfile[len];
+            everSeenNonTemporary = new BranchProfile[len];
+            for (int i = 0; i < signature.getLength(); i++) {
+                everSeenShared[i] = BranchProfile.create();
+                everSeenTemporary[i] = BranchProfile.create();
+                everSeenNonTemporary[i] = BranchProfile.create();
+            }
+        } else {
+            everSeenShared = null;
+            everSeenTemporary = null;
+            everSeenNonTemporary = null;
+        }
     }
 
     public Object execute(VirtualFrame frame, RStringVector type, Object[] arguments) {
         controlVisibility();
         Result lookupResult = lookup.execute(frame, generic, type, null, frame.materialize(), null);
+        if (wrap) {
+            assert arguments != null && arguments.length == signature.getLength();
+            for (int i = 0; i < arguments.length; i++) {
+                Utils.transitionState(arguments[i], everSeenShared[i], everSeenTemporary[i], everSeenNonTemporary[i]);
+            }
+        }
         S3Args s3Args = new S3Args(generic, lookupResult.clazz, lookupResult.targetFunctionName, frame.materialize(), null, null);
         return callMatcher.execute(frame, signature, arguments, lookupResult.function, s3Args);
     }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
index 9152401994bc26b499aebe482e810a66b254ebcd..31d4cd5b8f683c97ad0b55058f00ddb89e5e96d2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentNode.java
@@ -99,17 +99,7 @@ public final class WrapArgumentNode extends RNode implements RSyntaxNode {
             }
 
             if (vector != null) {
-                // mark vector as wrapped only if changing its mode to shared; otherwise make sure
-                // that it can be seen as "truly" shared by marking vector unwrapped
-                if (vector.isShared()) {
-                    everSeenShared.enter();
-                } else if (vector.isTemporary()) {
-                    everSeenTemporary.enter();
-                    vector.markNonTemporary();
-                } else {
-                    everSeenNonTemporary.enter();
-                    vector.makeShared();
-                }
+                Utils.transitionState(vector, everSeenShared, everSeenTemporary, everSeenNonTemporary);
             }
         }
         return result;
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 1c7ef74e065eb7b66a52a5bbcf8c83a4cdef57e0..d4fedab9f113b67ad1480bd060203ff5dd17b268 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
@@ -69,6 +69,8 @@ public class FastROptions {
     public static final OptionValue<Boolean> IgnoreVisibility = new OptionValue<>(false);
     @Option(help = "Load R package sources index")
     public static final OptionValue<Boolean> LoadPkgSourcesIndex = new OptionValue<>(true);
+    @Option(help = "Argument writes do not trigger state transitions")
+    public static final OptionValue<Boolean> InvisibleArgs = new OptionValue<>(false);
 
     // Promises optimizations
     @Option(help = "If enabled, overrides all other EagerEval switches (see EagerEvalHelper)")
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 969211546d72bba4243ac5bc78000673c08cd422..5bd9cfbb264fe09e0dea1093c1468e8cd35ab618 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
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.frame.*;
 import com.oracle.truffle.api.frame.FrameInstance.FrameAccess;
 import com.oracle.truffle.api.nodes.*;
 import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.runtime.RContext.ConsoleHandler;
 import com.oracle.truffle.r.runtime.conn.*;
 import com.oracle.truffle.r.runtime.data.*;
@@ -745,4 +746,33 @@ public final class Utils {
         return r;
     }
 
+    public static void transitionState(RShareable shareable, BranchProfile everSeenShared, BranchProfile everSeenTemporary, BranchProfile everSeenNonTemporary) {
+        if (shareable.isShared()) {
+            everSeenShared.enter();
+        } else if (shareable.isTemporary()) {
+            everSeenTemporary.enter();
+            shareable.markNonTemporary();
+        } else {
+            everSeenNonTemporary.enter();
+            shareable.makeShared();
+        }
+    }
+
+    public static void transitionStateSlowPath(Object o) {
+        if (o instanceof RShareable) {
+            RShareable shareable = (RShareable) o;
+            if (shareable.isTemporary()) {
+                shareable.markNonTemporary();
+            } else if (!shareable.isShared()) {
+                shareable.makeShared();
+            }
+        }
+    }
+
+    public static void transitionState(Object o, BranchProfile everSeenShared, BranchProfile everSeenTemporary, BranchProfile everSeenNonTemporary) {
+        if (o instanceof RShareable) {
+            transitionState((RShareable) o, everSeenShared, everSeenTemporary, everSeenNonTemporary);
+        }
+    }
+
 }
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 792489a1035c27661040d18c993cc6a78b73cf91..fc75d7130ba44953d80d773aee2644a72a9750f7 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
@@ -173,10 +173,7 @@ public class RPromise extends RLanguageRep implements RTypedValue {
         assert newValue != null;
         this.value = newValue;
 
-        // set NAMED = 2
-        if (newValue instanceof RShareable) {
-            ((RShareable) newValue).makeShared();
-        }
+        Utils.transitionStateSlowPath(newValue);
     }
 
     /**
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 b36381b86ffdb6fd69b19dce4cbf14c965d445fd..53af1f7c889492d367fc2cc60168dcdb1c1d99c2 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
@@ -22,8 +22,10 @@
  */
 package com.oracle.truffle.r.runtime.data;
 
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.source.*;
+import com.oracle.truffle.api.utilities.*;
 import com.oracle.truffle.r.runtime.*;
 import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute;
 import com.oracle.truffle.r.runtime.data.model.*;
@@ -411,9 +413,8 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV
     public final RVector makeShared() {
         if (temporary) {
             temporary = false;
-        } else {
-            shared = true;
         }
+        shared = true;
         return this;
     }
 
@@ -552,6 +553,7 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV
     public final RVector copy() {
         RVector result = internalCopy();
         setAttributes(result);
+        incCopyCount();
         return result;
     }
 
@@ -820,4 +822,41 @@ public abstract class RVector extends RBounded implements RShareable, RAbstractV
     public final RShareable materializeToShareable() {
         return materialize();
     }
+
+    private static final ConditionProfile statsProfile = ConditionProfile.createBinaryProfile();
+
+    @CompilationFinal private static PerfHandler stats;
+
+    private static void incCopyCount() {
+        if (statsProfile.profile(stats != null)) {
+            stats.record(null);
+        }
+    }
+
+    static {
+        RPerfStats.register(new PerfHandler());
+    }
+
+    private static class PerfHandler implements RPerfStats.Handler {
+
+        private static int count;
+
+        void record(@SuppressWarnings("unused") Object data) {
+            count++;
+        }
+
+        public void initialize(String optionData) {
+            stats = this;
+            count = 0;
+        }
+
+        public String getName() {
+            return "vectorcopies";
+        }
+
+        public void report() {
+            RPerfStats.out().printf("NUMBER OF VECTOR COPIES: %d\n", count);
+        }
+    }
+
 }