diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
index ed643cb629ef06cd93cc76696597613684206b0f..470d1ba4cf21f2e3a72db08dce47ccf36bf590a3 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/APerm.java
@@ -24,6 +24,7 @@ import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -63,7 +64,8 @@ public abstract class APerm extends RBuiltinNode {
 
     @Specialization
     protected RAbstractVector aPerm(RAbstractVector vector, @SuppressWarnings("unused") RNull permVector, byte resize,
-                    @Cached("create()") GetDimAttributeNode getDimsNode) {
+                    @Cached("create()") GetDimAttributeNode getDimsNode,
+                    @Cached("create()") SetDimAttributeNode setDimNode) {
         checkErrorConditions(vector);
 
         int[] dim = getDimsNode.getDimensions(vector);
@@ -76,9 +78,9 @@ public abstract class APerm extends RBuiltinNode {
             for (int i = 0; i < diml; i++) {
                 pDim[i] = dim[diml - 1 - i];
             }
-            result.setDimensions(pDim);
+            setDimNode.setDimensions(result, pDim);
         } else {
-            result.setDimensions(dim);
+            setDimNode.setDimensions(result, dim);
         }
 
         // Move along the old array using stride
@@ -104,7 +106,8 @@ public abstract class APerm extends RBuiltinNode {
 
     @Specialization
     protected RAbstractVector aPerm(RAbstractVector vector, RAbstractIntVector permVector, byte resize,
-                    @Cached("create()") GetDimAttributeNode getDimsNode) {
+                    @Cached("create()") GetDimAttributeNode getDimsNode,
+                    @Cached("create()") SetDimAttributeNode setDimsNode) {
         checkErrorConditions(vector);
 
         int[] dim = getDimsNode.getDimensions(vector);
@@ -115,7 +118,7 @@ public abstract class APerm extends RBuiltinNode {
 
         RVector<?> result = vector.createEmptySameType(vector.getLength(), vector.isComplete());
 
-        result.setDimensions(resize == RRuntime.LOGICAL_TRUE ? pDim : dim);
+        setDimsNode.setDimensions(result, resize == RRuntime.LOGICAL_TRUE ? pDim : dim);
 
         // Move along the old array using stride
         for (int i = 0; i < result.getLength(); i++) {
@@ -130,7 +133,8 @@ public abstract class APerm extends RBuiltinNode {
     @Specialization
     protected RAbstractVector aPerm(RAbstractVector vector, RAbstractStringVector permVector, byte resize,
                     @Cached("create()") RAttributeProfiles dimNamesProfile,
-                    @Cached("create()") GetDimAttributeNode getDimsNode) {
+                    @Cached("create()") GetDimAttributeNode getDimsNode,
+                    @Cached("create()") SetDimAttributeNode setDimsNode) {
         RList dimNames = vector.getDimNames(dimNamesProfile);
         if (dimNames == null) {
             // TODO: this error is reported after IS_OF_WRONG_LENGTH in GnuR
@@ -150,7 +154,7 @@ public abstract class APerm extends RBuiltinNode {
         }
 
         // Note: if this turns out to be slow, we can cache the permutation
-        return aPerm(vector, RDataFactory.createIntVector(perm, true), resize, getDimsNode);
+        return aPerm(vector, RDataFactory.createIntVector(perm, true), resize, getDimsNode, setDimsNode);
     }
 
     private static int[] getReverse(int[] dim) {
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 28a3e5cd648b4679148037ac0d0fae5e82059078..853a071cb5cb0218d803cb97f519d208c62ec607 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
@@ -37,6 +37,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.RASTUtils;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode;
@@ -171,7 +172,7 @@ public abstract class Bind extends RBaseNode {
         }
     }
 
-    private Object bindInternal(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, CastNode castNode, boolean needsVectorCast) {
+    private Object bindInternal(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, CastNode castNode, boolean needsVectorCast, SetDimAttributeNode setDimNode) {
         ArgumentsSignature signature = promiseArgs.getSignature();
         String[] vecNames = nullNamesProfile.profile(signature.getNonNullCount() == 0) ? null : new String[signature.getLength()];
         RAbstractVector[] vectors = new RAbstractVector[args.length];
@@ -227,46 +228,52 @@ public abstract class Bind extends RBaseNode {
             }
         }
         if (type == BindType.cbind) {
-            return genericCBind(promiseArgs, vectors, complete, vecNames, naCheck.neverSeenNA(), deparseLevel);
+            return genericCBind(promiseArgs, vectors, complete, vecNames, naCheck.neverSeenNA(), deparseLevel, setDimNode);
         } else {
-            return genericRBind(promiseArgs, vectors, complete, vecNames, naCheck.neverSeenNA(), deparseLevel);
+            return genericRBind(promiseArgs, vectors, complete, vecNames, naCheck.neverSeenNA(), deparseLevel, setDimNode);
         }
     }
 
     @Specialization(guards = {"precedence == LOGICAL_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"})
     protected Object allLogical(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, //
-                    @Cached("create()") CastLogicalNode cast) {
-        return bindInternal(deparseLevel, args, promiseArgs, cast, true);
+                    @Cached("create()") CastLogicalNode cast,
+                    @Cached("create()") SetDimAttributeNode setDimNode) {
+        return bindInternal(deparseLevel, args, promiseArgs, cast, true, setDimNode);
     }
 
     @Specialization(guards = {"precedence == INT_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"})
     protected Object allInt(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, //
-                    @Cached("create()") CastIntegerNode cast) {
-        return bindInternal(deparseLevel, args, promiseArgs, cast, true);
+                    @Cached("create()") CastIntegerNode cast,
+                    @Cached("create()") SetDimAttributeNode setDimNode) {
+        return bindInternal(deparseLevel, args, promiseArgs, cast, true, setDimNode);
     }
 
     @Specialization(guards = {"precedence == DOUBLE_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"})
     protected Object allDouble(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, //
-                    @Cached("create()") CastDoubleNode cast) {
-        return bindInternal(deparseLevel, args, promiseArgs, cast, true);
+                    @Cached("create()") CastDoubleNode cast,
+                    @Cached("create()") SetDimAttributeNode setDimNode) {
+        return bindInternal(deparseLevel, args, promiseArgs, cast, true, setDimNode);
     }
 
     @Specialization(guards = {"precedence == STRING_PRECEDENCE", "args.length> 1", "!isDataFrame(args)"})
     protected Object allString(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, //
-                    @Cached("create()") CastStringNode cast) {
-        return bindInternal(deparseLevel, args, promiseArgs, cast, true);
+                    @Cached("create()") CastStringNode cast,
+                    @Cached("create()") SetDimAttributeNode setDimNode) {
+        return bindInternal(deparseLevel, args, promiseArgs, cast, true, setDimNode);
     }
 
     @Specialization(guards = {"precedence == COMPLEX_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"})
     protected Object allComplex(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, //
-                    @Cached("create()") CastComplexNode cast) {
-        return bindInternal(deparseLevel, args, promiseArgs, cast, true);
+                    @Cached("create()") CastComplexNode cast,
+                    @Cached("create()") SetDimAttributeNode setDimNode) {
+        return bindInternal(deparseLevel, args, promiseArgs, cast, true, setDimNode);
     }
 
     @Specialization(guards = {"precedence == LIST_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"})
     protected Object allList(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, //
-                    @Cached("create()") CastListNode cast) {
-        return bindInternal(deparseLevel, args, promiseArgs, cast, false);
+                    @Cached("create()") CastListNode cast,
+                    @Cached("create()") SetDimAttributeNode setDimNode) {
+        return bindInternal(deparseLevel, args, promiseArgs, cast, false, setDimNode);
     }
 
     /**
@@ -489,7 +496,8 @@ public abstract class Bind extends RBaseNode {
         return res;
     }
 
-    public RVector<?> genericCBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, int deparseLevel) {
+    public RVector<?> genericCBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, int deparseLevel,
+                    SetDimAttributeNode setDimNode) {
 
         int[] resultDimensions = new int[2];
         int[] secondDims = new int[vectors.length];
@@ -540,7 +548,7 @@ public abstract class Bind extends RBaseNode {
 
         }
         Object colDimResultNames = allColDimNamesNull ? RNull.instance : RDataFactory.createStringVector(colDimNamesArray, vecNamesComplete);
-        result.setDimensions(resultDimensions);
+        setDimNode.setDimensions(result, resultDimensions);
         result.setDimNames(RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames}));
         return result;
     }
@@ -570,7 +578,8 @@ public abstract class Bind extends RBaseNode {
         }
     }
 
-    public RVector<?> genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, int deparseLevel) {
+    public RVector<?> genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, int deparseLevel,
+                    SetDimAttributeNode setDimNode) {
 
         int[] resultDimensions = new int[2];
         int[] firstDims = new int[vectors.length];
@@ -625,7 +634,7 @@ public abstract class Bind extends RBaseNode {
 
         }
         Object rowDimResultNames = allRowDimNamesNull ? RNull.instance : RDataFactory.createStringVector(rowDimNamesArray, vecNamesComplete);
-        result.setDimensions(resultDimensions);
+        setDimNode.setDimensions(result, resultDimensions);
         result.setDimNames(RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames}));
         return result;
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
index e5e26a5b22a1c7c348fa222a89e21828b2a2a377..9f291c1c2e8ce95c266b1a527d213a0bc696c641 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Combine.java
@@ -478,10 +478,9 @@ public abstract class Combine extends RBuiltinNode {
                 result.initAttributes(RAttributesLayout.createNames(vecNames));
                 result.setInternalNames(vecNames);
             } else {
-                RList dimNames = materialized.getInternalDimNames();
+                RList dimNames = materialized.getDimNames();
                 if (hasDimNamesProfile.profile(dimNames != null)) {
-                    result.initAttributes(RAttributesLayout.createDimNames(vecNames));
-                    result.setInternalDimNames(dimNames);
+                    result.initAttributes(RAttributesLayout.createDimNames(dimNames));
                 }
             }
             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 e31f75656d5eb43a0ca4d37666f818a7de86e739..0ff9a4a4b01e3264fd6c35ddf61e0ea5c546deae 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
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
@@ -49,7 +50,9 @@ public abstract class Drop extends RBuiltinNode {
     private final ConditionProfile noDimNamesProfile = ConditionProfile.createBinaryProfile();
 
     @Specialization
-    protected RAbstractVector doDrop(RAbstractVector x, @Cached("create()") GetDimAttributeNode getDimsNode) {
+    protected RAbstractVector doDrop(RAbstractVector x,
+                    @Cached("create()") GetDimAttributeNode getDimsNode,
+                    @Cached("create()") SetDimAttributeNode setDimsNode) {
         int[] dims = getDimsNode.getDimensions(x);
         if (nullDimensions.profile(dims == null)) {
             return x;
@@ -69,7 +72,7 @@ public abstract class Drop extends RBuiltinNode {
         if (resultIsScalarProfile.profile(lastNonOneIndex == -1)) {
             @SuppressWarnings("unused")
             RAbstractVector r = x.copy();
-            x.setDimensions(null);
+            setDimsNode.setDimensions(x, null);
             x.setDimNames(null);
             x.setNames(null);
             return x;
@@ -77,7 +80,7 @@ public abstract class Drop extends RBuiltinNode {
 
         // the result is vector
         if (resultIsVector.profile(newDimsLength <= 1)) {
-            return toVector(x, lastNonOneIndex);
+            return toVector(x, lastNonOneIndex, setDimsNode);
         }
 
         // else: the result will be a matrix, copy non-1 dimensions
@@ -90,7 +93,7 @@ public abstract class Drop extends RBuiltinNode {
         }
 
         RAbstractVector result = x.copy();
-        result.setDimensions(newDims);
+        setDimsNode.setDimensions(result, newDims);
 
         // if necessary, copy corresponding dimnames
         RList oldDimNames = x.getDimNames(dimNamesAttrProfile);
@@ -114,9 +117,9 @@ 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) {
+    private RAbstractVector toVector(RAbstractVector x, int nonOneIndex, SetDimAttributeNode setDimsNode) {
         RAbstractVector result = x.copy(); // share?
-        result.setDimensions(null);
+        setDimsNode.setDimensions(result, null);
 
         // copy dimnames to names if possible
         RList dimNames = x.getDimNames(dimNamesAttrProfile);
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 81003390bcf0aaede7fb48b504a4cb2146a7f844..5e0c81fa1dfb924c8bf73d2341115114e8247105 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
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastDoubleNode;
@@ -259,7 +260,9 @@ public class LaFunctions {
         }
 
         @Specialization
-        protected RList doQr(RAbstractDoubleVector aIn, @Cached("create()") GetDimAttributeNode getDimsNode) {
+        protected RList doQr(RAbstractDoubleVector aIn,
+                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") SetDimAttributeNode setDimsNode) {
             // This implementation is sufficient for B25 matcal-5.
             if (!(aIn instanceof RDoubleVector)) {
                 RError.nyi(this, "non-real vectors not supported (yet)");
@@ -290,7 +293,7 @@ public class LaFunctions {
             // TODO check complete
             RDoubleVector ra = RDataFactory.createDoubleVector(a, RDataFactory.COMPLETE_VECTOR);
             // TODO check pivot
-            ra.setDimensions(dims);
+            setDimsNode.setDimensions(ra, dims);
             data[0] = ra;
             data[1] = m < n ? m : n;
             data[2] = RDataFactory.createDoubleVector(tau, RDataFactory.COMPLETE_VECTOR);
@@ -554,7 +557,8 @@ public class LaFunctions {
         @Specialization
         protected RDoubleVector laSolve(RAbstractVector a, RDoubleVector bin, double tol,
                         @Cached("create()") GetDimAttributeNode getADimsNode,
-                        @Cached("create()") GetDimAttributeNode getBinDimsNode) {
+                        @Cached("create()") GetDimAttributeNode getBinDimsNode,
+                        @Cached("create()") SetDimAttributeNode setBDimsNode) {
             int[] aDims = getADimsNode.getDimensions(a);
             int n = aDims[0];
             if (n == 0) {
@@ -580,7 +584,7 @@ public class LaFunctions {
                 }
                 bData = new double[n * p];
                 b = RDataFactory.createDoubleVector(bData, RDataFactory.COMPLETE_VECTOR);
-                b.setDimensions(new int[]{n, p});
+                setBDimsNode.setDimensions(b, new int[]{n, p});
                 RList binDn = bin.getDimNames();
                 // This is somewhat odd, but Matrix relies on dropping NULL dimnames
                 if (aDn != null || binDn != null) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
index 359655123762e0281c039706e26d6481b4346e28..616b798d932dda8bf7da680e6fd6d137d0d66f3d 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java
@@ -35,6 +35,7 @@ import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.LoopConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.binary.BinaryMapArithmeticFunctionNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -78,6 +79,7 @@ public abstract class MatMult extends RBuiltinNode {
 
     @Child protected GetDimAttributeNode getADimsNode = GetDimAttributeNode.create();
     @Child protected GetDimAttributeNode getBDimsNode = GetDimAttributeNode.create();
+    @Child protected SetDimAttributeNode setDimsNode = SetDimAttributeNode.create();
 
     protected abstract Object executeObject(Object a, Object b);
 
@@ -97,7 +99,7 @@ public abstract class MatMult extends RBuiltinNode {
         int r = getBDimsNode.getDimensions(b)[1];
         int c = getADimsNode.getDimensions(a)[0];
         RDoubleVector result = RDataFactory.createDoubleVector(r * c);
-        result.setDimensions(new int[]{r, c});
+        setDimsNode.setDimensions(result, new int[]{r, c});
         return result;
     }
 
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
index bec8a180fab423d0887b7139cc7907743180d4a5..0895f7591631e6d7ef4c4630ecd35884c4923457 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Matrix.java
@@ -28,8 +28,10 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -75,7 +77,8 @@ public abstract class Matrix extends RBuiltinNode {
     }
 
     @Specialization
-    protected RAbstractVector matrix(RAbstractVector data, int nrow, int ncol, boolean byrow, Object dimnames, boolean missingNr, boolean missingNc) {
+    protected RAbstractVector matrix(RAbstractVector data, int nrow, int ncol, boolean byrow, Object dimnames, boolean missingNr, boolean missingNc,
+                    @Cached("create()") SetDimAttributeNode setDimNode) {
         int[] dim;
         if (byrowProfile.profile(byrow)) {
             dim = computeDimByRow(data.getLength(), nrow, ncol, missingNr, missingNc);
@@ -99,7 +102,7 @@ public abstract class Matrix extends RBuiltinNode {
                 }
             } else {
                 res = data.createEmptySameType(0, RDataFactory.COMPLETE_VECTOR);
-                res.setDimensions(dim);
+                setDimNode.setDimensions(res, dim);
             }
         } else {
             res = data.copyResizedWithDimensions(dim, false);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
index 2d936337b0bc60b2ab1a52ec21a3f8db25a27733..44cf8ad8d2579c37b58b8e58e41fb01f3511be54 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Transpose.java
@@ -103,7 +103,6 @@ public abstract class Transpose extends RBuiltinNode {
             hasDimNamesProfile.enter();
             assert dimNames.getLength() == 2;
             RList newDimNames = RDataFactory.createList(new Object[]{dimNames.getDataAt(1), dimNames.getDataAt(0)});
-            r.setInternalDimNames(newDimNames);
             putDimNames.execute(r.getAttributes(), newDimNames);
         }
         return r;
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
index f1fcfd5dc4d34b48cc357681924abb28a819d7dd..5e3750bbf11b644378488edf21e0d8161e38f016 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java
@@ -31,11 +31,13 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetRowNamesAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -72,6 +74,7 @@ public abstract class UpdateAttr extends RBuiltinNode {
     @Child private SetClassAttributeNode setClassAttrNode;
     @Child private SetRowNamesAttributeNode setRowNamesAttrNode;
     @Child private SetAttributeNode setGenAttrNode;
+    @Child private SetDimAttributeNode setDimNode;
 
     @CompilationFinal private String cachedName = "";
     @CompilationFinal private String cachedInternedName = "";
@@ -144,7 +147,11 @@ public abstract class UpdateAttr extends RBuiltinNode {
         RAbstractContainer result = (RAbstractContainer) container.getNonShared();
         // the name is interned, so identity comparison is sufficient
         if (internedName == RRuntime.DIM_ATTR_KEY) {
-            result.setDimensions(null);
+            if (setDimNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                setDimNode = insert(SetDimAttributeNode.create());
+            }
+            setDimNode.setDimensions(result, null);
         } else if (internedName == RRuntime.NAMES_ATTR_KEY) {
             return updateNames(result, value);
         } else if (internedName == RRuntime.DIMNAMES_ATTR_KEY) {
@@ -186,7 +193,11 @@ public abstract class UpdateAttr extends RBuiltinNode {
                 errorProfile.enter();
                 throw RError.error(this, RError.Message.LENGTH_ZERO_DIM_INVALID);
             }
-            result.setDimensions(dimsVector.materialize().getDataCopy());
+            if (setDimNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                setDimNode = insert(SetDimAttributeNode.create());
+            }
+            setDimNode.setDimensions(result, dimsVector.materialize().getDataCopy());
         } else if (internedName == RRuntime.NAMES_ATTR_KEY) {
             return updateNames(result, value);
         } else if (internedName == RRuntime.DIMNAMES_ATTR_KEY) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
index 744664502bc6512cc64e74509f98b5f846dd6d30..fd24c7fe3a85441890ec618d965dc8f2e03c3c3c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java
@@ -34,6 +34,7 @@ import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.nodes.attributes.InitAttributesNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetClassAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastIntegerNode;
@@ -64,6 +65,7 @@ public abstract class UpdateAttributes extends RBuiltinNode {
     @Child private CastIntegerNode castInteger;
     @Child private CastToVectorNode castVector;
     @Child private SetAttributeNode setAttrNode;
+    @Child private SetDimAttributeNode setDimNode;
 
     @Override
     protected void createCasts(CastBuilder casts) {
@@ -165,14 +167,20 @@ public abstract class UpdateAttributes extends RBuiltinNode {
             Object value = sourceList.getDataAt(i);
             String attrName = listNames.getDataAt(i);
             if (attrName.equals(RRuntime.DIM_ATTR_KEY)) {
+
+                if (setDimNode == null) {
+                    CompilerDirectives.transferToInterpreterAndInvalidate();
+                    setDimNode = insert(SetDimAttributeNode.create());
+                }
+
                 if (value == RNull.instance) {
-                    result.setDimensions(null);
+                    setDimNode.setDimensions(result, null);
                 } else {
                     RAbstractIntVector dimsVector = castInteger(castVector(value));
                     if (dimsVector.getLength() == 0) {
                         throw RError.error(this, RError.Message.LENGTH_ZERO_DIM_INVALID);
                     }
-                    result.setDimensions(dimsVector.materialize().getDataCopy());
+                    setDimNode.setDimensions(result, dimsVector.materialize().getDataCopy());
                 }
             }
         }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
index 319577028597641d7bd356acd485e0de78775405..c3b2751c16f81a39f79d6ec6590064f2d2a9bdb8 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDim.java
@@ -70,7 +70,6 @@ public abstract class UpdateDim extends RBuiltinNode {
         RVector.verifyDimensions(vector.getLength(), dimsData, this);
         RVector<?> result = ((RAbstractVector) reuse.execute(vector)).materialize();
         result.setInternalNames(null);
-        result.setInternalDimNames(null);
 
         DynamicObject attrs = result.getAttributes();
         if (initAttrProfile.profile(attrs == null)) {
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
index ace3e951b770935861cfca0502a8f5fcaeac013b..160eb65328e509c85b9380e7359ee9344d4be57f 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java
@@ -97,15 +97,7 @@ public abstract class UpdateDimNames extends RBuiltinNode {
     protected RAbstractContainer updateDimnamesNull(RAbstractContainer container, @SuppressWarnings("unused") RNull list, //
                     @Cached("createDimNames()") RemoveFixedAttributeNode remove) {
         RAbstractContainer result = (RAbstractContainer) container.getNonShared();
-        if (isRVectorProfile.profile(container instanceof RVector)) {
-            RVector<?> vector = (RVector<?>) result;
-            if (vector.getInternalDimNames() != null) {
-                vector.setInternalDimNames(null);
-                remove.execute(vector.getAttributes());
-            }
-        } else {
-            result.setDimNames(null);
-        }
+        remove.execute(result);
         return result;
     }
 
@@ -179,7 +171,6 @@ public abstract class UpdateDimNames extends RBuiltinNode {
                 attrSetter.execute(vector.getAttributes(), resDimNames);
             }
             resDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX;
-            vector.setInternalDimNames(resDimNames);
         } else {
             container.setDimNames(newDimNames);
         }
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 2fdba2452bbd296c15841f87e7aead60fb576a88..305c602cad205fd89e0b3520f7dad06a9aa0a6ce 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
@@ -29,9 +29,11 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
 import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 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;
@@ -90,6 +92,7 @@ public abstract class VApply extends RBuiltinNode {
     @Child private CastIntegerNode castInteger;
     @Child private CastLogicalNode castLogical;
     @Child private CastStringNode castString;
+    @Child private SetDimAttributeNode setDimNode;
 
     @Override
     protected void createCasts(CastBuilder casts) {
@@ -186,7 +189,11 @@ public abstract class VApply extends RBuiltinNode {
         }
 
         if (dimsProfile.profile(funValueVecLen > 1)) {
-            result.setDimensions(new int[]{funValueVecLen, applyResult.length});
+            if (setDimNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                setDimNode = insert(SetDimAttributeNode.create());
+            }
+            setDimNode.setDimensions(result, new int[]{funValueVecLen, applyResult.length});
         }
 
         // TODO: handle names in case of matrices
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExpressionPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExpressionPrinter.java
index 5e15b1beafcee1c2817788f538d1cbca51dd7a33..56c7b015c27af255525f77ad8961c7faea4a033c 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExpressionPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ExpressionPrinter.java
@@ -46,7 +46,7 @@ final class ExpressionPrinter extends AbstractValuePrinter<RExpression> {
         valPrintCtx.parameters().setSuppressIndexLabels(true);
 
         out.print("expression(");
-        RStringVector names = (RStringVector) expr.getAttr(RRuntime.NAMES_ATTR_KEY);
+        RStringVector names = expr.getNames();
         for (int i = 0; i < expr.getLength(); i++) {
             if (i != 0) {
                 out.print(", ");
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
index cf6378f2f601ac71a5c613e9fb4146d3ac127e5f..62a994e753e86d30a52158f32994a1dbba4891ae 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ListPrinter.java
@@ -24,6 +24,7 @@ import com.oracle.truffle.r.runtime.RDeparse;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RAttributeProfiles;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -43,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector;
 final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
 
     static final ListPrinter INSTANCE = new ListPrinter();
+    private static final RAttributeProfiles dummyAttrProfiles = RAttributeProfiles.create();
 
     private ListPrinter() {
         // singleton
@@ -168,7 +170,7 @@ final class ListPrinter extends AbstractValuePrinter<RAbstractListVector> {
         int ns = s.getLength();
 
         RAbstractStringVector names;
-        names = Utils.castTo(RRuntime.asAbstractVector(s.getAttr(RRuntime.NAMES_ATTR_KEY)));
+        names = Utils.castTo(RRuntime.asAbstractVector(s.getNames(dummyAttrProfiles)));
 
         if (ns > 0) {
             int npr = (ns <= pp.getMax() + 1) ? ns : pp.getMax();
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
index 3167f0062c999d7e372a005dd4461eeb15869e1e..5577dd7c283cd4f934d3edcdee26c1a71687af24 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/VectorPrinter.java
@@ -80,7 +80,7 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
                 if (dims.getLength() == 1) {
                     RList t = Utils.<RList> castTo(vector.getAttr(RRuntime.DIMNAMES_ATTR_KEY));
                     if (t != null && t.getDataAt(0) != null) {
-                        RAbstractStringVector nn = Utils.castTo(RRuntime.asAbstractVector(t.getAttr(RRuntime.NAMES_ATTR_KEY)));
+                        RAbstractStringVector nn = Utils.castTo(RRuntime.asAbstractVector(t.getNames()));
 
                         if (nn != null) {
                             title = nn.getDataAt(0);
@@ -685,7 +685,7 @@ abstract class VectorPrinter<T extends RAbstractVector> extends AbstractValuePri
             } else {
                 rl = getDimNamesAt(0);
                 cl = getDimNamesAt(1);
-                axisNames = Utils.<RAbstractStringVector> castTo(dimnames.getAttr(RRuntime.NAMES_ATTR_KEY));
+                axisNames = Utils.<RAbstractStringVector> castTo(dimnames.getNames());
                 if (axisNames == null) {
                     rn = null;
                     cn = null;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
index b81069298c0f33afa77acd3a240c2e86f059c492..805339e2673281bc6819bc4d3cc10b1d08f18946 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedExtractVectorNode.java
@@ -33,6 +33,7 @@ import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.access.vector.CachedExtractVectorNodeFactory.SetNamesNodeGen;
 import com.oracle.truffle.r.nodes.access.vector.PositionsCheckNode.PositionProfile;
 import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.profile.AlwaysOnBranchProfile;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RError;
@@ -279,6 +280,8 @@ final class CachedExtractVectorNode extends CachedVectorNode {
     private final ConditionProfile originalDimNamesPRofile = ConditionProfile.createBinaryProfile();
     private final ConditionProfile foundNamesProfile = ConditionProfile.createBinaryProfile();
 
+    @Child private SetDimAttributeNode setDimNode;
+
     @ExplodeLoop
     private void applyDimensions(RAbstractContainer originalTarget, RVector<?> extractedTarget, int extractedTargetLength, PositionProfile[] positionProfile, Object[] positions) {
         // TODO speculate on the number of counted dimensions
@@ -325,7 +328,13 @@ final class CachedExtractVectorNode extends CachedVectorNode {
 
         if (resultHasDimensions.profile(dimCount > 1)) {
             metadataApplied.enter();
-            extractedTarget.setDimensions(newDimensions);
+
+            if (setDimNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                setDimNode = insert(SetDimAttributeNode.create());
+            }
+
+            setDimNode.setDimensions(extractedTarget, newDimensions);
             if (newDimNames != null) {
                 extractedTarget.setDimNames(RDataFactory.createList(newDimNames, newDimNamesNames == null ? null : RDataFactory.createStringVector(newDimNamesNames, originalDimNames.isComplete())));
             }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java
index 088dcd2711c487ae188cc1119e8d3236ec366253..62fb60138bb7ae74e342c352b7970c34f5b786c2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/CopyAttributesNode.java
@@ -153,7 +153,6 @@ public abstract class CopyAttributesNode extends RBaseNode {
                 if (hasAttributes.profile(attributes != null)) {
                     removeDim.execute(attributes);
                     removeDimNames.execute(attributes);
-                    result.setInternalDimNames(null);
                 }
 
                 RStringVector vecNames = left.getNames(attrLeftProfiles);
@@ -187,7 +186,6 @@ public abstract class CopyAttributesNode extends RBaseNode {
                 putDimNames.execute(result.getAttributes(), newDimNames);
 
                 newDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX;
-                result.setInternalDimNames(newDimNames);
                 return result;
             }
             if (result != right) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetFixedAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetFixedAttributeNode.java
index 4fd0e9cba05925452c34a0f4fdabb55c1502ac75..cfea85e1806d90b5dc4bddd2edca27daf0d8b244 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetFixedAttributeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/GetFixedAttributeNode.java
@@ -32,7 +32,9 @@ import com.oracle.truffle.api.object.Shape;
 import com.oracle.truffle.api.profiles.BranchProfile;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetClassAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RAttributable;
 import com.oracle.truffle.r.runtime.data.RAttributeStorage;
@@ -52,11 +54,15 @@ public abstract class GetFixedAttributeNode extends FixedAttributeAccessNode {
     }
 
     public static GetFixedAttributeNode create(String name) {
-        return GetFixedAttributeNodeGen.create(name);
+        if (SpecialAttributesFunctions.IsSpecialAttributeNode.isSpecialAttribute(name)) {
+            return SpecialAttributesFunctions.createGetSpecialAttributeNode(name);
+        } else {
+            return GetFixedAttributeNodeGen.create(name);
+        }
     }
 
     public static GetFixedAttributeNode createNames() {
-        return GetFixedAttributeNode.create(RRuntime.NAMES_ATTR_KEY);
+        return GetNamesAttributeNode.create();
     }
 
     public static GetDimAttributeNode createDim() {
@@ -64,7 +70,7 @@ public abstract class GetFixedAttributeNode extends FixedAttributeAccessNode {
     }
 
     public static GetFixedAttributeNode createClass() {
-        return GetFixedAttributeNode.create(RRuntime.CLASS_ATTR_KEY);
+        return GetClassAttributeNode.create();
     }
 
     public abstract Object execute(Object attr);
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveFixedAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveFixedAttributeNode.java
index 1b7ed881a0436f587d0587a99227c258e100467e..93561001034cd3559fefbd1e64295c5d884d9496 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveFixedAttributeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveFixedAttributeNode.java
@@ -23,9 +23,18 @@
 package com.oracle.truffle.r.nodes.attributes;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.object.DynamicObject;
-import com.oracle.truffle.r.runtime.RRuntime;
+import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.RemoveClassAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.RemoveDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.RemoveDimNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.RemoveNamesAttributeNode;
+import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 
 public abstract class RemoveFixedAttributeNode extends FixedAttributeAccessNode {
 
@@ -34,30 +43,55 @@ public abstract class RemoveFixedAttributeNode extends FixedAttributeAccessNode
     }
 
     public static RemoveFixedAttributeNode create(String name) {
-        return RemoveFixedAttributeNodeGen.create(name);
+        if (SpecialAttributesFunctions.IsSpecialAttributeNode.isSpecialAttribute(name)) {
+            return SpecialAttributesFunctions.createRemoveSpecialAttributeNode(name);
+        } else {
+            return RemoveFixedAttributeNodeGen.create(name);
+        }
     }
 
     public static RemoveFixedAttributeNode createNames() {
-        return RemoveFixedAttributeNode.create(RRuntime.NAMES_ATTR_KEY);
+        return RemoveNamesAttributeNode.create();
     }
 
     public static RemoveFixedAttributeNode createDim() {
-        return RemoveFixedAttributeNode.create(RRuntime.DIM_ATTR_KEY);
+        return RemoveDimAttributeNode.create();
     }
 
     public static RemoveFixedAttributeNode createDimNames() {
-        return RemoveFixedAttributeNode.create(RRuntime.DIMNAMES_ATTR_KEY);
+        return RemoveDimNamesAttributeNode.create();
     }
 
     public static RemoveFixedAttributeNode createClass() {
-        return RemoveFixedAttributeNode.create(RRuntime.CLASS_ATTR_KEY);
+        return RemoveClassAttributeNode.create();
     }
 
-    public abstract void execute(DynamicObject attrs);
+    public abstract void execute(Object attrs);
 
     @Specialization
     @TruffleBoundary
     protected void removeAttrFallback(DynamicObject attrs) {
         attrs.delete(this.name);
     }
+
+    @Specialization
+    protected void removeAttrFromAttributable(RAttributable x,
+                    @Cached("create()") BranchProfile attrNullProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
+                    @Cached("createClassProfile()") ValueProfile xTypeProfile) {
+        DynamicObject attributes;
+        if (attrStorageProfile.profile(x instanceof RAttributeStorage)) {
+            attributes = ((RAttributeStorage) x).getAttributes();
+        } else {
+            attributes = xTypeProfile.profile(x).getAttributes();
+        }
+
+        if (attributes == null) {
+            attrNullProfile.enter();
+            return;
+        }
+
+        removeAttrFallback(attributes);
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetAttributeNode.java
index c09d2d58bc5897e4be6d3db446a096b77f9f1fa8..aecd9e3c0fc95b1f2f6cdb3c2bb80e3c5ff862da 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetAttributeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetAttributeNode.java
@@ -32,8 +32,11 @@ import com.oracle.truffle.api.object.IncompatibleLocationException;
 import com.oracle.truffle.api.object.Location;
 import com.oracle.truffle.api.object.Shape;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 
 /**
  * This node is responsible for setting a value to an arbitrary attribute. It accepts both
@@ -116,7 +119,7 @@ public abstract class SetAttributeNode extends AttributeAccessNode {
     }
 
     protected static SpecialAttributesFunctions.SetSpecialAttributeNode createSpecAttrNode(String name) {
-        return SpecialAttributesFunctions.createSpecialAttributeNode(name);
+        return SpecialAttributesFunctions.createSetSpecialAttributeNode(name);
     }
 
     @Specialization(limit = "3", //
@@ -143,8 +146,16 @@ public abstract class SetAttributeNode extends AttributeAccessNode {
 
     @Specialization
     protected void setAttrInAttributable(RAttributable x, String name, Object value,
-                    @Cached("create()") BranchProfile attrNullProfile) {
-        DynamicObject attributes = x.getAttributes();
+                    @Cached("create()") BranchProfile attrNullProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
+                    @Cached("createClassProfile()") ValueProfile xTypeProfile) {
+        DynamicObject attributes;
+        if (attrStorageProfile.profile(x instanceof RAttributeStorage)) {
+            attributes = ((RAttributeStorage) x).getAttributes();
+        } else {
+            attributes = xTypeProfile.profile(x).getAttributes();
+        }
+
         if (attributes == null) {
             attrNullProfile.enter();
             attributes = x.initAttributes();
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetFixedAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetFixedAttributeNode.java
index 95f995a5481e993130e435e63cb367d8c5df0a15..1b1477258b980a07db9bec92b44c427a04247b4f 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetFixedAttributeNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetFixedAttributeNode.java
@@ -32,10 +32,12 @@ import com.oracle.truffle.api.object.IncompatibleLocationException;
 import com.oracle.truffle.api.object.Location;
 import com.oracle.truffle.api.object.Shape;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ConditionProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetSpecialAttributeNode;
 import com.oracle.truffle.r.runtime.RInternalError;
-import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RAttributeStorage;
 
 /**
  * This node is responsible for setting a value to the predefined (fixed) attribute. It accepts both
@@ -52,31 +54,32 @@ public abstract class SetFixedAttributeNode extends FixedAttributeAccessNode {
     @Child private SetFixedAttributeNode recursive;
     @Child private SetSpecialAttributeNode setSpecialAttrNode;
 
-    private final boolean isSpecialAttribute;
-
     protected SetFixedAttributeNode(String name) {
         super(name);
-        this.isSpecialAttribute = SpecialAttributesFunctions.IsSpecialAttributeNode.isSpecialAttribute(name);
     }
 
     public static SetFixedAttributeNode create(String name) {
-        return SetFixedAttributeNodeGen.create(name);
+        if (SpecialAttributesFunctions.IsSpecialAttributeNode.isSpecialAttribute(name)) {
+            return SpecialAttributesFunctions.createSetSpecialAttributeNode(name);
+        } else {
+            return SetFixedAttributeNodeGen.create(name);
+        }
     }
 
     public static SetFixedAttributeNode createNames() {
-        return SetFixedAttributeNode.create(RRuntime.NAMES_ATTR_KEY);
+        return SpecialAttributesFunctions.SetNamesAttributeNode.create();
     }
 
     public static SetFixedAttributeNode createDim() {
-        return SetFixedAttributeNode.create(RRuntime.DIM_ATTR_KEY);
+        return SpecialAttributesFunctions.SetDimAttributeNode.create();
     }
 
     public static SetFixedAttributeNode createDimNames() {
-        return SetFixedAttributeNode.create(RRuntime.DIMNAMES_ATTR_KEY);
+        return SpecialAttributesFunctions.SetDimNamesAttributeNode.create();
     }
 
     public static SetFixedAttributeNode createClass() {
-        return SetFixedAttributeNode.create(RRuntime.CLASS_ATTR_KEY);
+        return SpecialAttributesFunctions.SetClassAttributeNode.create();
     }
 
     public abstract void execute(Object attr, Object value);
@@ -121,27 +124,26 @@ public abstract class SetFixedAttributeNode extends FixedAttributeAccessNode {
 
     @Specialization
     protected void setAttrInAttributable(RAttributable x, Object value,
-                    @Cached("create()") BranchProfile attrNullProfile) {
-        if (isSpecialAttribute) {
-            if (setSpecialAttrNode == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                setSpecialAttrNode = insert(SpecialAttributesFunctions.createSpecialAttributeNode(name));
-            }
-            setSpecialAttrNode.execute(x, value);
+                    @Cached("create()") BranchProfile attrNullProfile,
+                    @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
+                    @Cached("createClassProfile()") ValueProfile xTypeProfile) {
+        DynamicObject attributes;
+        if (attrStorageProfile.profile(x instanceof RAttributeStorage)) {
+            attributes = ((RAttributeStorage) x).getAttributes();
         } else {
-            DynamicObject attributes = x.getAttributes();
-            if (attributes == null) {
-                attrNullProfile.enter();
-                attributes = x.initAttributes();
-            }
-
-            if (recursive == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                recursive = insert(create(name));
-            }
-            recursive.execute(attributes, value);
+            attributes = xTypeProfile.profile(x).getAttributes();
         }
 
+        if (attributes == null) {
+            attrNullProfile.enter();
+            attributes = x.initAttributes();
+        }
+
+        if (recursive == null) {
+            CompilerDirectives.transferToInterpreterAndInvalidate();
+            recursive = insert(create(name));
+        }
+        recursive.execute(attributes, value);
     }
 
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
index 241be5a0e6f5b3514285efe7990f335b677a99a2..ea270ac4e7452bfedc3b214b84b19cf8b9058ec0 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SpecialAttributesFunctions.java
@@ -28,12 +28,14 @@ import com.oracle.truffle.api.dsl.Specialization;
 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.api.profiles.LoopConditionProfile;
 import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctionsFactory.GetDimAttributeNodeGen;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.data.RAttributable;
+import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RInteger;
 import com.oracle.truffle.r.runtime.data.RList;
@@ -164,12 +166,12 @@ public final class SpecialAttributesFunctions {
     }
 
     /**
-     * A factory method for creating a node handling the given special attribute.
+     * A factory method for creating a node setting the given special attribute.
      *
      * @param name the special attribute name
      * @return the node
      */
-    public static SetSpecialAttributeNode createSpecialAttributeNode(String name) {
+    public static SetSpecialAttributeNode createSetSpecialAttributeNode(String name) {
         assert name.intern() == name;
         if (name == RRuntime.NAMES_ATTR_KEY) {
             return SetNamesAttributeNode.create();
@@ -186,22 +188,108 @@ public final class SpecialAttributesFunctions {
         }
     }
 
+    /**
+     * A factory method for creating a node removing the given special attribute.
+     *
+     * @param name the special attribute name
+     * @return the node
+     */
+    public static RemoveSpecialAttributeNode createRemoveSpecialAttributeNode(String name) {
+        assert name.intern() == name;
+        if (name == RRuntime.NAMES_ATTR_KEY) {
+            return RemoveNamesAttributeNode.create();
+        } else if (name == RRuntime.DIM_ATTR_KEY) {
+            return RemoveDimAttributeNode.create();
+        } else if (name == RRuntime.DIMNAMES_ATTR_KEY) {
+            return RemoveDimNamesAttributeNode.create();
+        } else if (name == RRuntime.ROWNAMES_ATTR_KEY) {
+            return RemoveRowNamesAttributeNode.create();
+        } else if (name == RRuntime.CLASS_ATTR_KEY) {
+            return RemoveClassAttributeNode.create();
+        } else {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+
+    /**
+     * A factory method for creating a node retrieving the given special attribute.
+     *
+     * @param name the special attribute name
+     * @return the node
+     */
+    public static GetFixedAttributeNode createGetSpecialAttributeNode(String name) {
+        assert name.intern() == name;
+        if (name == RRuntime.NAMES_ATTR_KEY) {
+            return GetNamesAttributeNode.create();
+        } else if (name == RRuntime.DIM_ATTR_KEY) {
+            return GetDimAttributeNode.create();
+        } else if (name == RRuntime.DIMNAMES_ATTR_KEY) {
+            return GetDimNamesAttributeNode.create();
+        } else if (name == RRuntime.ROWNAMES_ATTR_KEY) {
+            return GetRowNamesAttributeNode.create();
+        } else if (name == RRuntime.CLASS_ATTR_KEY) {
+            return GetClassAttributeNode.create();
+        } else {
+            throw RInternalError.shouldNotReachHere();
+        }
+    }
+
     /**
      * The base class for the nodes setting values to special attributes.
      */
-    public abstract static class SetSpecialAttributeNode extends RBaseNode {
+    public abstract static class SetSpecialAttributeNode extends SetFixedAttributeNode {
+
+        protected SetSpecialAttributeNode(String name) {
+            super(name);
+        }
 
         public abstract void execute(RAttributable x, Object attrValue);
 
     }
 
+    /**
+     * The base class for the nodes removing values from special attributes.
+     */
+    public abstract static class RemoveSpecialAttributeNode extends RemoveFixedAttributeNode {
+
+        protected RemoveSpecialAttributeNode(String name) {
+            super(name);
+        }
+
+        public abstract void execute(RAttributable x);
+
+        @Specialization(insertBefore = "removeAttrFromAttributable")
+        protected void removeAttrFromVector(RVector<?> x,
+                        @Cached("create()") BranchProfile attrNullProfile,
+                        @Cached("create()") BranchProfile attrEmptyProfile) {
+            DynamicObject attributes = x.getAttributes();
+            if (attributes == null) {
+                attrNullProfile.enter();
+                return;
+            }
+
+            attrNullProfile.enter();
+            attributes.delete(name);
+
+            if (attributes.isEmpty()) {
+                attrEmptyProfile.enter();
+                x.initAttributes(null);
+            }
+        }
+
+    }
+
     public abstract static class SetNamesAttributeNode extends SetSpecialAttributeNode {
 
+        protected SetNamesAttributeNode() {
+            super(RRuntime.NAMES_ATTR_KEY);
+        }
+
         public static SetNamesAttributeNode create() {
             return SpecialAttributesFunctionsFactory.SetNamesAttributeNodeGen.create();
         }
 
-        @Specialization
+        @Specialization(insertBefore = "setAttrInAttributable")
         protected void setNamesInContainer(RAbstractContainer x, RStringVector names,
                         @Cached("createClassProfile()") ValueProfile contClassProfile) {
             RAbstractContainer xProfiled = contClassProfile.profile(x);
@@ -209,41 +297,162 @@ public final class SpecialAttributesFunctions {
         }
     }
 
+    public abstract static class RemoveNamesAttributeNode extends RemoveSpecialAttributeNode {
+
+        protected RemoveNamesAttributeNode() {
+            super(RRuntime.NAMES_ATTR_KEY);
+        }
+
+        @Override
+        @Specialization
+        protected void removeAttrFallback(DynamicObject attrs) {
+            super.removeAttrFallback(attrs);
+        }
+
+        public static RemoveNamesAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.RemoveNamesAttributeNodeGen.create();
+        }
+    }
+
+    public abstract static class GetNamesAttributeNode extends GetFixedAttributeNode {
+
+        protected GetNamesAttributeNode() {
+            super(RRuntime.NAMES_ATTR_KEY);
+        }
+
+        public static GetNamesAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.GetNamesAttributeNodeGen.create();
+        }
+
+        @Override
+        @Specialization(contains = "getAttrCached")
+        protected Object getAttrFallback(DynamicObject attrs) {
+            return super.getAttrFallback(attrs);
+        }
+
+    }
+
     public abstract static class SetDimAttributeNode extends SetSpecialAttributeNode {
 
+        private final ConditionProfile nullDimProfile = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile naDimProfile = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile negativeDimProfile = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile dimNotMatchLengthProfile = ConditionProfile.createBinaryProfile();
+        private final ValueProfile contArgClassProfile = ValueProfile.createClassProfile();
+        private final ValueProfile dimArgClassProfile = ValueProfile.createClassProfile();
+        private final LoopConditionProfile verifyLoopProfile = LoopConditionProfile.createCountingProfile();
+
+        protected SetDimAttributeNode() {
+            super(RRuntime.DIM_ATTR_KEY);
+        }
+
         public static SetDimAttributeNode create() {
             return SpecialAttributesFunctionsFactory.SetDimAttributeNodeGen.create();
         }
 
-        @Specialization
-        protected void setOneDimInContainer(RAbstractContainer x, Integer dim,
-                        @Cached("createClassProfile()") ValueProfile contClassProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile vectorProfile) {
-            int[] dims = new int[]{dim};
-            if (vectorProfile.profile(x instanceof RVector)) {
-                ((RVector<?>) x).setDimensions(dims);
+        public void setDimensions(RAbstractContainer x, int[] dims) {
+            if (nullDimProfile.profile(dims == null)) {
+                execute(x, RNull.instance);
             } else {
-                RAbstractContainer xProfiled = contClassProfile.profile(x);
-                xProfiled.setDimensions(dims);
+                execute(x, RDataFactory.createIntVector(dims, RDataFactory.COMPLETE_VECTOR));
             }
+        }
 
+        @Specialization(insertBefore = "setAttrInAttributable")
+        protected void resetDims(RAbstractContainer x, @SuppressWarnings("unused") RNull rnull,
+                        @Cached("create()") RemoveDimAttributeNode removeDimAttrNode,
+                        @Cached("createBinaryProfile()") ConditionProfile vectorClassProfile,
+                        @Cached("createClassProfile()") ValueProfile xTypeProfile) {
+            removeDimAttrNode.execute(x);
+            if (vectorClassProfile.profile(x instanceof RVector)) {
+                ((RVector<?>) x).setDimNames(null);
+            } else {
+                xTypeProfile.profile(x).setDimNames(null);
+            }
         }
 
-        @Specialization
-        protected void setDimsInContainer(RAbstractContainer x, RAbstractIntVector dims,
-                        @Cached("createClassProfile()") ValueProfile contClassProfile,
-                        @Cached("createBinaryProfile()") ConditionProfile vectorProfile) {
+        @Specialization(insertBefore = "setAttrInAttributable")
+        protected void setOneDimInVector(RVector<?> x, int dim,
+                        @Cached("create()") BranchProfile attrNullProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
+                        @Cached("createClassProfile()") ValueProfile xTypeProfile) {
+            int[] dims = new int[]{dim};
+            verifyOneDimensions(x.getLength(), dim);
+            super.setAttrInAttributable(x, RDataFactory.createIntVector(dims, RDataFactory.COMPLETE_VECTOR), attrNullProfile, attrStorageProfile, xTypeProfile);
+        }
+
+        @Specialization(insertBefore = "setAttrInAttributable")
+        protected void setDimsInVector(RVector<?> x, RAbstractIntVector dims,
+                        @Cached("create()") BranchProfile attrNullProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
+                        @Cached("createClassProfile()") ValueProfile xTypeProfile) {
+            RAbstractContainer xProfiled = contArgClassProfile.profile(x);
+            verifyDimensions(xProfiled.getLength(), dims);
+            super.setAttrInAttributable(x, dims, attrNullProfile, attrStorageProfile, xTypeProfile);
+        }
+
+        @Specialization(insertBefore = "setAttrInAttributable")
+        protected void setDimsInContainerFallback(RAbstractContainer x, RAbstractIntVector dims,
+                        @Cached("create()") SetDimAttributeNode setDimNode) {
             int[] dimsArr = dims.materialize().getDataCopy();
-            if (vectorProfile.profile(x instanceof RVector)) {
-                ((RVector<?>) x).setDimensions(dimsArr);
-            } else {
-                RAbstractContainer xProfiled = contClassProfile.profile(x);
-                xProfiled.setDimensions(dimsArr);
+            setDimNode.setDimensions(x, dimsArr);
+        }
+
+        private void verifyOneDimensions(int vectorLength, int dim) {
+            int length = dim;
+            if (naDimProfile.profile(RRuntime.isNA(dim))) {
+                throw RError.error(this, RError.Message.DIMS_CONTAIN_NA);
+            } else if (negativeDimProfile.profile(dim < 0)) {
+                throw RError.error(this, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
+            }
+            if (dimNotMatchLengthProfile.profile(length != vectorLength && vectorLength > 0)) {
+                CompilerDirectives.transferToInterpreter();
+                throw RError.error(this, RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength);
+            }
+        }
+
+        public void verifyDimensions(int vectorLength, RAbstractIntVector dims) {
+            RAbstractIntVector dimsProfiled = dimArgClassProfile.profile(dims);
+            int dimLen = dims.getLength();
+            verifyLoopProfile.profileCounted(dimLen);
+            int length = 1;
+            for (int i = 0; i < dimLen; i++) {
+                int dim = dimsProfiled.getDataAt(i);
+                if (naDimProfile.profile(RRuntime.isNA(dim))) {
+                    CompilerDirectives.transferToInterpreter();
+                    throw RError.error(this, RError.Message.DIMS_CONTAIN_NA);
+                } else if (negativeDimProfile.profile(dim < 0)) {
+                    CompilerDirectives.transferToInterpreter();
+                    throw RError.error(this, RError.Message.DIMS_CONTAIN_NEGATIVE_VALUES);
+                }
+                length *= dim;
+            }
+            if (length != vectorLength && vectorLength > 0) {
+                CompilerDirectives.transferToInterpreter();
+                throw RError.error(this, RError.Message.DIMS_DONT_MATCH_LENGTH, length, vectorLength);
             }
         }
 
     }
 
+    public abstract static class RemoveDimAttributeNode extends RemoveSpecialAttributeNode {
+
+        protected RemoveDimAttributeNode() {
+            super(RRuntime.DIM_ATTR_KEY);
+        }
+
+        public static RemoveDimAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.RemoveDimAttributeNodeGen.create();
+        }
+
+        @Override
+        @Specialization
+        protected void removeAttrFallback(DynamicObject attrs) {
+            super.removeAttrFallback(attrs);
+        }
+
+    }
+
     public abstract static class GetDimAttributeNode extends GetFixedAttributeNode {
 
         private final ConditionProfile nullDimsProfile = ConditionProfile.createBinaryProfile();
@@ -300,11 +509,79 @@ public final class SpecialAttributesFunctions {
 
     public abstract static class SetDimNamesAttributeNode extends SetSpecialAttributeNode {
 
+        private final ConditionProfile nullDimNamesProfile = ConditionProfile.createBinaryProfile();
+
+        protected SetDimNamesAttributeNode() {
+            super(RRuntime.DIMNAMES_ATTR_KEY);
+        }
+
         public static SetDimNamesAttributeNode create() {
             return SpecialAttributesFunctionsFactory.SetDimNamesAttributeNodeGen.create();
         }
 
-        @Specialization
+        public void setDimNames(RAbstractContainer x, RList dimNames) {
+            if (nullDimNamesProfile.profile(dimNames == null)) {
+                execute(x, RNull.instance);
+            } else {
+                execute(x, dimNames);
+            }
+        }
+
+        @Specialization(insertBefore = "setAttrInAttributable")
+        protected void resetDimNames(RAbstractContainer x, @SuppressWarnings("unused") RNull rnull,
+                        @Cached("create()") RemoveDimNamesAttributeNode removeDimNamesAttrNode) {
+// removeDimNamesAttrNode.execute(x);
+            x.setDimNames(null);
+        }
+
+        @Specialization(insertBefore = "setAttrInAttributable")
+        protected void setDimNamesInVector(RVector<?> x, RList newDimNames,
+                        @Cached("create()") GetDimAttributeNode getDimNode,
+                        @Cached("create()") BranchProfile attrNullProfile,
+                        @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
+                        @Cached("createClassProfile()") ValueProfile xTypeProfile) {
+            x.setDimNames(newDimNames);
+// int[] dimensions = getDimNode.getDimensions(x);
+// if (dimensions == null) {
+// throw RError.error(this, RError.Message.DIMNAMES_NONARRAY);
+// }
+// int newDimNamesLength = newDimNames.getLength();
+// if (newDimNamesLength > dimensions.length) {
+// throw RError.error(this, RError.Message.DIMNAMES_DONT_MATCH_DIMS, newDimNamesLength,
+// dimensions.length);
+// }
+// for (int i = 0; i < newDimNamesLength; i++) {
+// Object dimObject = newDimNames.getDataAt(i);
+// if (dimObject != RNull.instance) {
+// if (dimObject instanceof String) {
+// if (dimensions[i] != 1) {
+// throw RError.error(this, RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
+// }
+// } else {
+// RStringVector dimVector = (RStringVector) dimObject;
+// if (dimVector == null) {
+// newDimNames.updateDataAt(i, RNull.instance, null);
+// } else if (dimVector.getLength() != dimensions[i]) {
+// throw RError.error(this, RError.Message.DIMNAMES_DONT_MATCH_EXTENT, i + 1);
+// }
+// }
+// }
+// }
+//
+// RList resDimNames = newDimNames;
+// if (newDimNamesLength < dimensions.length) {
+// // resize the array and fill the missing entries with NULL-s
+// resDimNames = (RList) resDimNames.copyResized(dimensions.length, true);
+// resDimNames.setAttributes(newDimNames);
+// for (int i = newDimNamesLength; i < dimensions.length; i++) {
+// resDimNames.updateDataAt(i, RNull.instance, null);
+// }
+// }
+// resDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX;
+// super.setAttrInAttributable(x, newDimNames, attrNullProfile, attrStorageProfile, xTypeProfile);
+        }
+
+        @Specialization(insertBefore = "setAttrInAttributable")
         protected void setDimNamesInContainer(RAbstractContainer x, RList dimNames, @Cached("createClassProfile()") ValueProfile contClassProfile) {
             RAbstractContainer xProfiled = contClassProfile.profile(x);
             xProfiled.setDimNames(dimNames);
@@ -312,13 +589,56 @@ public final class SpecialAttributesFunctions {
 
     }
 
+    public abstract static class RemoveDimNamesAttributeNode extends RemoveSpecialAttributeNode {
+
+        protected RemoveDimNamesAttributeNode() {
+            super(RRuntime.DIMNAMES_ATTR_KEY);
+        }
+
+        @Override
+        @Specialization
+        protected void removeAttrFallback(DynamicObject attrs) {
+            super.removeAttrFallback(attrs);
+        }
+
+        public static RemoveDimNamesAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.RemoveDimNamesAttributeNodeGen.create();
+        }
+    }
+
+    public abstract static class GetDimNamesAttributeNode extends GetFixedAttributeNode {
+
+        protected GetDimNamesAttributeNode() {
+            super(RRuntime.DIMNAMES_ATTR_KEY);
+        }
+
+        public static GetDimNamesAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.GetDimNamesAttributeNodeGen.create();
+        }
+
+        public final RList getDimNames(Object x) {
+            return (RList) execute(x);
+        }
+
+        @Override
+        @Specialization(contains = "getAttrCached")
+        protected Object getAttrFallback(DynamicObject attrs) {
+            return super.getAttrFallback(attrs);
+        }
+
+    }
+
     public abstract static class SetRowNamesAttributeNode extends SetSpecialAttributeNode {
 
+        protected SetRowNamesAttributeNode() {
+            super(RRuntime.ROWNAMES_ATTR_KEY);
+        }
+
         public static SetRowNamesAttributeNode create() {
             return SpecialAttributesFunctionsFactory.SetRowNamesAttributeNodeGen.create();
         }
 
-        @Specialization
+        @Specialization(insertBefore = "setAttrInAttributable")
         protected void setRowNamesInContainer(RAbstractContainer x, RAbstractVector rowNames, @Cached("createClassProfile()") ValueProfile contClassProfile) {
             RAbstractContainer xProfiled = contClassProfile.profile(x);
             xProfiled.setRowNames(rowNames);
@@ -326,8 +646,47 @@ public final class SpecialAttributesFunctions {
 
     }
 
+    public abstract static class RemoveRowNamesAttributeNode extends RemoveSpecialAttributeNode {
+
+        protected RemoveRowNamesAttributeNode() {
+            super(RRuntime.DIMNAMES_ATTR_KEY);
+        }
+
+        public static RemoveRowNamesAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.RemoveRowNamesAttributeNodeGen.create();
+        }
+
+        @Override
+        @Specialization
+        protected void removeAttrFallback(DynamicObject attrs) {
+            super.removeAttrFallback(attrs);
+        }
+    }
+
+    public abstract static class GetRowNamesAttributeNode extends GetFixedAttributeNode {
+
+        protected GetRowNamesAttributeNode() {
+            super(RRuntime.ROWNAMES_ATTR_KEY);
+        }
+
+        public static GetRowNamesAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.GetRowNamesAttributeNodeGen.create();
+        }
+
+        @Override
+        @Specialization(contains = "getAttrCached")
+        protected Object getAttrFallback(DynamicObject attrs) {
+            return super.getAttrFallback(attrs);
+        }
+
+    }
+
     public abstract static class SetClassAttributeNode extends SetSpecialAttributeNode {
 
+        protected SetClassAttributeNode() {
+            super(RRuntime.CLASS_ATTR_KEY);
+        }
+
         public static SetClassAttributeNode create() {
             return SpecialAttributesFunctionsFactory.SetClassAttributeNodeGen.create();
         }
@@ -336,7 +695,7 @@ public final class SpecialAttributesFunctions {
             execute(x, RNull.instance);
         }
 
-        @Specialization
+        @Specialization(insertBefore = "setAttrInAttributable")
         protected <T> void handleVectorNullClass(RVector<T> vector, @SuppressWarnings("unused") RNull classAttr,
                         @Cached("createClass()") RemoveFixedAttributeNode removeClassAttrNode,
                         @Cached("createClass()") SetFixedAttributeNode setClassAttrNode,
@@ -346,7 +705,7 @@ public final class SpecialAttributesFunctions {
             handleVector(vector, null, removeClassAttrNode, setClassAttrNode, nullAttrProfile, nullClassProfile, notNullClassProfile);
         }
 
-        @Specialization
+        @Specialization(insertBefore = "setAttrInAttributable")
         protected <T> void handleVector(RVector<T> vector, RStringVector classAttr,
                         @Cached("createClass()") RemoveFixedAttributeNode removeClassAttrNode,
                         @Cached("createClass()") SetFixedAttributeNode setClassAttrNode,
@@ -385,12 +744,12 @@ public final class SpecialAttributesFunctions {
             }
         }
 
-        @Specialization
+        @Specialization(insertBefore = "setAttrInAttributable")
         protected void handleAttributable(RAttributable x, @SuppressWarnings("unused") RNull classAttr) {
             x.setClassAttr(null);
         }
 
-        @Specialization
+        @Specialization(insertBefore = "setAttrInAttributable")
         protected void handleAttributable(RAttributable x, RStringVector classAttr) {
             x.setClassAttr(classAttr);
         }
@@ -406,4 +765,40 @@ public final class SpecialAttributesFunctions {
 
     }
 
+    public abstract static class RemoveClassAttributeNode extends RemoveSpecialAttributeNode {
+
+        protected RemoveClassAttributeNode() {
+            super(RRuntime.CLASS_ATTR_KEY);
+        }
+
+        public static RemoveClassAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.RemoveClassAttributeNodeGen.create();
+        }
+
+        @Override
+        @Specialization
+        protected void removeAttrFallback(DynamicObject attrs) {
+            super.removeAttrFallback(attrs);
+        }
+
+    }
+
+    public abstract static class GetClassAttributeNode extends GetFixedAttributeNode {
+
+        protected GetClassAttributeNode() {
+            super(RRuntime.CLASS_ATTR_KEY);
+        }
+
+        public static GetClassAttributeNode create() {
+            return SpecialAttributesFunctionsFactory.GetClassAttributeNodeGen.create();
+        }
+
+        @Override
+        @Specialization(contains = "getAttrCached")
+        protected Object getAttrFallback(DynamicObject attrs) {
+            return super.getAttrFallback(attrs);
+        }
+
+    }
+
 }
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/UnaryCopyAttributesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/UnaryCopyAttributesNode.java
index f695e4d9ee8677e1381cd9fed2a70f505e2fda3f..1a1f9a30a29ff7ee1df4990fa5326c50ddf0bf79 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/UnaryCopyAttributesNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/UnaryCopyAttributesNode.java
@@ -105,7 +105,6 @@ public abstract class UnaryCopyAttributesNode extends RBaseNode {
             if (attributes != null) {
                 removeDim.execute(attributes);
                 removeDimNames.execute(attributes);
-                result.setInternalDimNames(null);
             }
 
             RStringVector vecNames = source.getNames(attrSourceProfiles);
@@ -123,7 +122,6 @@ public abstract class UnaryCopyAttributesNode extends RBaseNode {
         if (hasDimNames.profile(newDimNames != null)) {
             putDimNames.execute(result.getAttributes(), newDimNames);
             newDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX;
-            result.setInternalDimNames(newDimNames);
             return result;
         }
         return result;
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java
index df9aea109de8925484edd31bcfc2ecb3b21b9746..569cc6483a43ba832a05a8fbf4b1e84eb69d6de7 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/primitive/UnaryMapNode.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.attributes.HasFixedAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode;
 import com.oracle.truffle.r.nodes.primitive.UnaryMapNodeFactory.MapUnaryVectorInternalNodeGen;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.RInternalError;
@@ -55,6 +56,7 @@ public final class UnaryMapNode extends RBaseNode {
     @Child private UnaryMapFunctionNode scalarNode;
     @Child private MapUnaryVectorInternalNode vectorNode;
     @Child private GetDimAttributeNode getDimNode;
+    @Child private SetDimAttributeNode setDimNode;
 
     // profiles
     private final Class<? extends RAbstractVector> operandClass;
@@ -181,7 +183,14 @@ public final class UnaryMapNode extends RBaseNode {
                 getDimNode = insert(GetDimAttributeNode.create());
             }
 
-            copyAttributesInternal((RVector<?>) result, operand, getDimNode.getDimensions(operand));
+            if (setDimNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                setDimNode = insert(SetDimAttributeNode.create());
+            }
+
+            setDimNode.setDimensions(result, getDimNode.getDimensions(operand));
+
+            copyAttributesInternal((RVector<?>) result, operand);
         }
         return result;
     }
@@ -198,9 +207,8 @@ public final class UnaryMapNode extends RBaseNode {
     }
 
     @TruffleBoundary
-    private void copyAttributesInternal(RVector<?> result, RAbstractVector attributeSource, int[] dims) {
+    private void copyAttributesInternal(RVector<?> result, RAbstractVector attributeSource) {
         result.copyRegAttributesFrom(attributeSource);
-        result.setDimensions(dims);
         result.copyNamesFrom(attrProfiles, attributeSource);
     }
 
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 5d952237fb70f7e3aad9089653ce63df02ad65b3..41b4410eeefc2a5edc431dda001ad52366d97db9 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
@@ -60,13 +60,11 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     protected boolean complete; // "complete" means: does not contain NAs
     protected RStringVector names;
-    private RList dimNames;
     // cache rownames for data frames as they are accessed at every data frame access
     private Object rowNames;
 
     protected RVector(boolean complete, int length, int[] dimensions, RStringVector names) {
         this.complete = complete;
-        // this.dimensions = dimensions;
         assert names != this;
         this.names = names;
         this.rowNames = RNull.instance;
@@ -83,7 +81,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
                     // one-dimensional arrays do not have names, only dimnames with one value
                     RList newDimNames = RDataFactory.createList(new Object[]{names});
                     initAttributes(RAttributesLayout.createDimAndDimNames(dimensionsVector, newDimNames));
-                    this.dimNames = newDimNames;
                 }
             }
         } else {
@@ -102,6 +99,14 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         }
     }
 
+    private RList getDimNamesFromAttrs() {
+        if (attributes == null) {
+            return null;
+        } else {
+            return (RList) attributes.get(RRuntime.DIMNAMES_ATTR_KEY);
+        }
+    }
+
     /**
      * Intended for external calls where a mutable copy is needed.
      */
@@ -146,14 +151,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         names = newNames;
     }
 
-    public final RList getInternalDimNames() {
-        return dimNames;
-    }
-
-    public final void setInternalDimNames(RList newDimNames) {
-        dimNames = newDimNames;
-    }
-
     public final Object getInternalRowNames() {
         return rowNames;
     }
@@ -183,6 +180,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
             return null;
         } else {
             if (attrProfiles.attrNullNamesProfile(names == null)) {
+                RList dimNames = getDimNames();
                 if (dimNames != null && dimNames.getLength() == 1) {
                     return (RStringVector) dimNames.getDataAt(0);
                 } else {
@@ -200,6 +198,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
      */
     public final RStringVector getNames() {
         if (names == null) {
+            RList dimNames = getDimNames();
             if (dimNames != null && dimNames.getLength() == 1) {
                 return (RStringVector) dimNames.getDataAt(0);
             } else {
@@ -369,7 +368,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
                 RList newDimNames = RDataFactory.createList(new Object[]{newNames});
                 newDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX;
                 putAttribute(RRuntime.DIMNAMES_ATTR_KEY, newDimNames);
-                this.dimNames = newDimNames;
             } else {
                 putAttribute(RRuntime.NAMES_ATTR_KEY, newNames);
                 assert newNames != this;
@@ -384,7 +382,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
     }
 
     public final RList getDimNames() {
-        return dimNames;
+        return getDimNamesFromAttrs();
     }
 
     /**
@@ -398,7 +396,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         } else {
             putAttribute(RRuntime.DIMNAMES_ATTR_KEY, newDimNames);
         }
-        this.dimNames = newDimNames;
     }
 
     @Override
@@ -411,7 +408,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
     private void setDimNames(RList newDimNames, RBaseNode invokingNode) {
         if (attributes != null && newDimNames == null) {
             removeAttributeMapping(RRuntime.DIMNAMES_ATTR_KEY);
-            this.dimNames = null;
         } else if (newDimNames != null) {
             int[] dimensions = getDimensionsFromAttrs();
             if (dimensions == null) {
@@ -450,7 +446,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
             }
             putAttribute(RRuntime.DIMNAMES_ATTR_KEY, resDimNames);
             resDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX;
-            this.dimNames = resDimNames;
         }
     }
 
@@ -481,10 +476,13 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     @Override
     public final boolean hasDimensions() {
-        // Sync the shape
         return attributes == null ? false : attributes.containsKey(RRuntime.DIM_ATTR_KEY);
     }
 
+    public final boolean hasDimNames() {
+        return attributes == null ? false : attributes.containsKey(RRuntime.DIMNAMES_ATTR_KEY);
+    }
+
     @Override
     public final boolean isMatrix() {
         int[] dimensions = getDimensionsFromAttrs();
@@ -573,7 +571,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     public final void setAttributes(RVector<?> result) {
         result.names = this.names;
-        result.dimNames = this.dimNames;
         result.rowNames = this.rowNames;
         if (this.attributes != null) {
             result.initAttributes(RAttributesLayout.copy(this.attributes));
@@ -671,7 +668,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
     public final RAttributable copyAttributesFrom(RAttributeProfiles attrProfiles, RAbstractContainer vector) {
         // it's meant to be used on a "fresh" vector with only dimensions potentially set
         assert (this.names == null);
-        assert (this.dimNames == null);
+        assert (!hasDimNames());
         assert (this.rowNames == RNull.instance);
         assert (!hasDimensions());
         assert (this.attributes == null || this.attributes.size() == 0) : this.attributes.size();
@@ -680,7 +677,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
             // one-dimensional array)
             this.names = vector.getNames(attrProfiles);
         }
-        this.dimNames = vector.getDimNames(attrProfiles);
         this.rowNames = vector.getRowNames(attrProfiles);
         DynamicObject vecAttributes = vector.getAttributes();
         if (vecAttributes != null) {
@@ -699,7 +695,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         if (vector.getDimensions() == null || vector.getDimensions().length != 1) {
             this.names = vector.getNames();
         }
-        this.dimNames = vector.getDimNames();
         this.rowNames = vector.getRowNames();
         DynamicObject vecAttributes = vector.getAttributes();
         if (vecAttributes != null) {
@@ -713,7 +708,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
     public final void copyNamesDimsDimNamesFrom(RAttributeProfiles attrProfiles, RAbstractVector vector, RBaseNode invokingNode) {
         // it's meant to be used on a "fresh" vector with only dimensions potentially set
         assert (this.names == null);
-        assert (this.dimNames == null);
+        assert (!hasDimNames());
         assert (!hasDimensions());
         assert (this.attributes == null);
         // for some reason, names is copied first, then dims, then dimnames
@@ -801,7 +796,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         // whether we nullify dimensions or re-set them to a different value, names and dimNames
         // must be reset
         this.names = null;
-        this.dimNames = null;
         if (newDimensions != null) {
             putAttribute(RRuntime.DIM_ATTR_KEY, RDataFactory.createIntVector(newDimensions, true));
         } else {
@@ -817,7 +811,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
     @Override
     public final void resetAllAttributes(boolean nullify) {
         this.names = null;
-        this.dimNames = null;
         this.rowNames = RNull.instance;
         if (nullify) {
             this.attributes = null;