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..c92c4fc6cb3aabb152e70429e9ae2bae6305d8b9 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,34 @@ 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.isShared()) {
+            } else if (shareable.isTemporary()) {
+                shareable.markNonTemporary();
+            } else {
+                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);
     }
 
     /**