diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
index ef88564b409673c60b1b9e05f9a8c9565d8854ed..41a244f231512aea273734c48b29acbdf8bb28d7 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.api.object.DynamicObject;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -53,6 +54,7 @@ public abstract class Attributes extends RBuiltinNode {
 
     private final BranchProfile rownamesBranch = BranchProfile.create();
     @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
+    @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
 
     @Specialization
     protected Object attributesNull(RAbstractContainer container, //
@@ -117,7 +119,7 @@ public abstract class Attributes extends RBuiltinNode {
             }
         }
         RList result = RDataFactory.createList(values);
-        result.setNames(RDataFactory.createStringVector(names, true));
+        setNamesNode.setNames(result, RDataFactory.createStringVector(names, true));
         return result;
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
index ce99c5869b2ae21b6e0942ff6ed6458f534c1268..7104921f0dc2c92786597d31e9c707f6fadf5f1c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Drop.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAt
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
@@ -56,7 +57,8 @@ public abstract class Drop extends RBuiltinNode {
                     @Cached("create()") GetDimAttributeNode getDimsNode,
                     @Cached("create()") SetDimAttributeNode setDimsNode,
                     @Cached("create()") SetDimNamesAttributeNode setDimsNamesNode,
-                    @Cached("create()") GetDimNamesAttributeNode getDimsNamesNode) {
+                    @Cached("create()") GetDimNamesAttributeNode getDimsNamesNode,
+                    @Cached("create()") SetNamesAttributeNode setNamesNode) {
         int[] dims = getDimsNode.getDimensions(x);
         if (nullDimensions.profile(dims == null)) {
             return x;
@@ -78,13 +80,13 @@ public abstract class Drop extends RBuiltinNode {
             RAbstractVector r = x.copy();
             setDimsNode.setDimensions(x, null);
             setDimsNamesNode.setDimNames(x, null);
-            x.setNames(null);
+            setNamesNode.setNames(x, null);
             return x;
         }
 
         // the result is vector
         if (resultIsVector.profile(newDimsLength <= 1)) {
-            return toVector(x, lastNonOneIndex, setDimsNode, getDimsNamesNode);
+            return toVector(x, lastNonOneIndex, setDimsNode, getDimsNamesNode, setNamesNode);
         }
 
         // else: the result will be a matrix, copy non-1 dimensions
@@ -121,14 +123,14 @@ public abstract class Drop extends RBuiltinNode {
      * Handles the case when result is just a vector. The only catch is that we might have to copy
      * corresponding index from dimnames to names attribute of the new vector.
      */
-    private RAbstractVector toVector(RAbstractVector x, int nonOneIndex, SetDimAttributeNode setDimsNode, GetDimNamesAttributeNode getDimNamesNode) {
+    private RAbstractVector toVector(RAbstractVector x, int nonOneIndex, SetDimAttributeNode setDimsNode, GetDimNamesAttributeNode getDimNamesNode, SetNamesAttributeNode setNamesNode) {
         RAbstractVector result = x.copy(); // share?
         setDimsNode.setDimensions(result, null);
 
         // copy dimnames to names if possible
         RList dimNames = getDimNamesNode.getDimNames(x);
         if (noDimNamesProfile.profile(dimNames != null) && nonOneIndex < dimNames.getLength()) {
-            result.setNames(ensureStringVector(dimNames.getDataAt(nonOneIndex)));
+            setNamesNode.setNames(result, ensureStringVector(dimNames.getDataAt(nonOneIndex)));
         }
 
         return result;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
index 376b2e141e3dfdb85c6ffab612ae4d6ac3870eca..8d3ca0f3b4ef3d2c4cfe9763960769dca7ff01df 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java
@@ -37,6 +37,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAt
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
@@ -565,7 +566,8 @@ public class LaFunctions {
                         @Cached("create()") SetDimAttributeNode setBDimsNode,
                         @Cached("create()") SetDimNamesAttributeNode setBDimNamesNode,
                         @Cached("create()") GetDimNamesAttributeNode getADimNamesNode,
-                        @Cached("create()") GetDimNamesAttributeNode getBinDimNamesNode) {
+                        @Cached("create()") GetDimNamesAttributeNode getBinDimNamesNode,
+                        @Cached("create()") SetNamesAttributeNode setNamesNode) {
             int[] aDims = getADimsNode.getDimensions(a);
             int n = aDims[0];
             if (n == 0) {
@@ -615,7 +617,7 @@ public class LaFunctions {
                 bData = new double[n];
                 b = RDataFactory.createDoubleVector(bData, RDataFactory.COMPLETE_VECTOR);
                 if (aDn != null) {
-                    b.setNames(RDataFactory.createStringVector((String) aDn.getDataAt(1)));
+                    setNamesNode.setNames(b, RDataFactory.createStringVector((String) aDn.getDataAt(1)));
                 }
             }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
index 2be9987afc3a938032c803813242677704ca2fe5..83f99a9513a2e09bb32b33e7d754e008d0e4af4a 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.builtin.base.Lapply.LapplyInternalNode;
@@ -92,6 +93,7 @@ public abstract class VApply extends RBuiltinNode {
     @Child private CastStringNode castString;
     @Child private SetDimAttributeNode setDimNode;
     @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
+    @Child private SetNamesAttributeNode setNamesNode = SetNamesAttributeNode.create();
 
     @Override
     protected void createCasts(CastBuilder casts) {
@@ -205,7 +207,7 @@ public abstract class VApply extends RBuiltinNode {
                 newNames = (RStringVector) vecMat.copy();
             }
             if (newNames != null) {
-                result.setNames(newNames);
+                setNamesNode.setNames(result, newNames);
             }
         }
         return result;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
index 640919a6809fb0f99ae2d91fa42abbcfe2fb847f..88d79d6841c1354a33beb6fead61ce5b68d6e50f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java
@@ -41,6 +41,7 @@ import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.access.vector.CachedReplaceVectorNodeFactory.ValueProfileNodeGen;
 import com.oracle.truffle.r.nodes.access.vector.PositionsCheckNode.PositionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
 import com.oracle.truffle.r.nodes.binary.CastTypeNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.nodes.unary.CastListNodeGen;
@@ -101,6 +102,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
     @Child private CastNode castVectorNode;
     @Child private CachedReplaceVectorNode copyPositionNames;
     @Child private DeleteElementsNode deleteElementsNode;
+    @Child private SetNamesAttributeNode setNamesNode;
 
     CachedReplaceVectorNode(ElementAccessMode mode, RTypedValue vector, Object[] positions, RTypedValue value, boolean updatePositionNames, boolean recursive) {
         super(mode, vector, positions, recursive);
@@ -576,7 +578,11 @@ final class CachedReplaceVectorNode extends CachedVectorNode {
         assert copyPositionNames.isSupported(names, positions, positionNames);
         RAbstractStringVector newNames = (RAbstractStringVector) copyPositionNames.apply(names, positions, positionNames);
         if (updateNamesProfile.profile(newNames != originalNames)) {
-            resultVector.setNames(newNames.materialize());
+            if (setNamesNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                setNamesNode = insert(SetNamesAttributeNode.create());
+            }
+            setNamesNode.setNames(resultVector, newNames.materialize());
         }
     }
 
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
index 5929a57a89e8229850b1f94f5308156a38b82792..9ed1986c865e9a3a79baf17ed84c53b9d17cc424 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckSubsetNode.java
@@ -32,6 +32,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
 import com.oracle.truffle.r.nodes.access.vector.PositionsCheckNode.PositionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode;
 import com.oracle.truffle.r.runtime.NullProfile;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
@@ -137,13 +138,14 @@ abstract class PositionCheckSubsetNode extends PositionCheckNode {
                     @Cached("create()") BranchProfile seenOutOfBounds, //
                     @Cached("create()") NullProfile hasNamesProfile, //
                     @Cached("createCountingProfile()") LoopConditionProfile lengthProfile,
-                    @Cached("create()") GetNamesAttributeNode getNamesNode) {
+                    @Cached("create()") GetNamesAttributeNode getNamesNode,
+                    @Cached("create()") SetNamesAttributeNode setNamesNode) {
         RAbstractIntVector intPosition = RDataFactory.createIntVector(positionLength);
         intPosition.setComplete(position.isComplete());
         // requires names preservation
         RStringVector names = hasNamesProfile.profile(getNamesNode.getNames(position));
         if (names != null) {
-            intPosition.setNames(names);
+            setNamesNode.setNames(intPosition, names);
         }
         Object convertedStore = intPosition.getInternalStore();