diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
index 5080206bbed26ecd787667839af2adae4bfe9f3f..8d692d6efcbc18a78ec1214791a4a21770ae8953 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Covcor.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2013, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2013, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -82,16 +82,10 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
     private final LoopConditionProfile loopLength = LoopConditionProfile.createCountingProfile();
 
     public RDoubleVector corcov(RDoubleVector x, RDoubleVector y, @SuppressWarnings("unused") int method, boolean iskendall, RBaseNode invokingNode) throws RError {
-        boolean ansmat;
-        boolean naFail;
-        boolean everything;
-        boolean sd0;
-        boolean emptyErr;
+
+        boolean ansmat = getDimsNode.isMatrix(x);
         int n;
         int ncx;
-        int ncy;
-
-        ansmat = x.isMatrix();
         if (ansmat) {
             n = nrows(x);
             ncx = ncols(x);
@@ -100,9 +94,10 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
             ncx = 1;
         }
 
+        int ncy;
         if (y == null) {
             ncy = ncx;
-        } else if (y.isMatrix()) {
+        } else if (getDimsNode.isMatrix(y)) {
             if (nrows(y) != n) {
                 error.enter();
                 error("incompatible dimensions");
@@ -120,9 +115,9 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         // TODO adopt full use semantics
 
         /* "default: complete" (easier for -Wall) */
-        naFail = false;
-        everything = false;
-        emptyErr = true;
+        boolean naFail = false;
+        boolean everything = false;
+        boolean emptyErr = true;
 
         // case 4: /* "everything": NAs are propagated */
         everything = true;
@@ -136,6 +131,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         double[] answerData = new double[ncx * ncy];
 
         double[] xm = new double[ncx];
+        boolean sd0;
         if (y == null) {
             if (everything) {
                 sd0 = covNA1(n, ncx, x, xm, answerData, isCor, iskendall);
@@ -170,7 +166,7 @@ public abstract class Covcor extends RExternalBuiltinNode.Arg4 {
         }
 
         RDoubleVector ans = null;
-        if (x.isMatrix()) {
+        if (getDimsNode.isMatrix(x)) {
             ans = RDataFactory.createDoubleVector(answerData, !seenNA, new int[]{ncx, ncy});
         } else {
             ans = RDataFactory.createDoubleVector(answerData, !seenNA);
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 14a7bd1687650116a8d7b22ee82b2c5f6fa1de90..0198eb0e04f8e0a9b54d20beb668b6a3f7bde66a 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
@@ -4,7 +4,7 @@
  * http://www.gnu.org/licenses/gpl-2.0.html
  *
  * Copyright (c) 2014, Purdue University
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -55,8 +55,8 @@ public abstract class APerm extends RBuiltinNode {
         casts.arg("resize").mustBe(numericValue().or(logicalValue()), Message.INVALID_LOGICAL, "resize").asLogicalVector().findFirst();
     }
 
-    private void checkErrorConditions(RAbstractVector vector) {
-        if (!vector.isArray()) {
+    private void checkErrorConditions(int[] dim) {
+        if (!GetDimAttributeNode.isArray(dim)) {
             errorProfile.enter();
             throw RError.error(RError.SHOW_CALLER, RError.Message.FIRST_ARG_MUST_BE_ARRAY);
         }
@@ -66,9 +66,9 @@ public abstract class APerm extends RBuiltinNode {
     protected RAbstractVector aPerm(RAbstractVector vector, @SuppressWarnings("unused") RNull permVector, byte resize,
                     @Cached("create()") GetDimAttributeNode getDimsNode,
                     @Cached("create()") SetDimAttributeNode setDimNode) {
-        checkErrorConditions(vector);
 
         int[] dim = getDimsNode.getDimensions(vector);
+        checkErrorConditions(dim);
         final int diml = dim.length;
 
         RVector<?> result = vector.createEmptySameType(vector.getLength(), vector.isComplete());
@@ -108,9 +108,9 @@ public abstract class APerm extends RBuiltinNode {
     protected RAbstractVector aPerm(RAbstractVector vector, RAbstractIntVector permVector, byte resize,
                     @Cached("create()") GetDimAttributeNode getDimsNode,
                     @Cached("create()") SetDimAttributeNode setDimsNode) {
-        checkErrorConditions(vector);
 
         int[] dim = getDimsNode.getDimensions(vector);
+        checkErrorConditions(dim);
         int[] perm = getPermute(dim, permVector);
 
         int[] posV = new int[dim.length];
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 13294d4f362ab562c0db9a44cb1426995eaca939..ec5dd5de2709877c968124a144661283dd242ce7 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -306,24 +306,23 @@ public abstract class Bind extends RBaseNode {
     /**
      * Compute dimnames for rows (cbind) or columns (rbind) from names of elements of combined
      * vectors.
-     *
-     * @param vec
-     * @param dimLength
-     * @return dimnames
      */
     protected Object getDimResultNamesFromElements(RAbstractVector vec, int dimLength, int dimInd, GetDimNamesAttributeNode getDimNamesNode, GetNamesAttributeNode getNamesNode) {
         Object firstDimResultNames = RNull.instance;
         Object firstDimNames = RNull.instance;
-        if (vec.isMatrix()) {
+        int[] dim = getVectorDimensions(vec);
+        if (GetDimAttributeNode.isMatrix(dim)) {
             RList vecDimNames = getDimNamesNode.getDimNames(vec);
             if (vecDimNames != null) {
                 firstDimNames = vecDimNames.getDataAt(dimInd);
             }
-        } else if (!vec.isArray() || getVectorDimensions(vec).length == 1) {
-            RStringVector names = getNamesNode.getNames(vec);
-            firstDimNames = names == null ? RNull.instance : names;
         } else {
-            RInternalError.unimplemented("binding multi-dimensional arrays is not supported");
+            if (!GetDimAttributeNode.isArray(dim) || dim.length == 1) {
+                RStringVector names = getNamesNode.getNames(vec);
+                firstDimNames = names == null ? RNull.instance : names;
+            } else {
+                RInternalError.unimplemented("binding multi-dimensional arrays is not supported");
+            }
         }
         if (firstDimNames != RNull.instance) {
             RStringVector names = (RStringVector) firstDimNames;
@@ -341,7 +340,8 @@ public abstract class Bind extends RBaseNode {
     protected int getDimResultNamesFromVectors(RArgsValuesAndNames promiseArgs, RAbstractVector vec, String[] argNames, int resDim, int oldInd, int vecInd, int deparseLevel,
                     String[] dimNamesArray, int dimNamesInd, GetDimNamesAttributeNode getDimNamesNode) {
         int ind = oldInd;
-        if (vec.isMatrix()) {
+        int[] rawDimensions = getVectorDimensions(vec);
+        if (GetDimAttributeNode.isMatrix(rawDimensions)) {
             RList vecDimNames = getDimNamesNode.getDimNames(vec);
             if (vecDimNames != null) {
                 Object resDimNames = vecDimNames.getDataAt(dimNamesInd);
@@ -362,33 +362,34 @@ public abstract class Bind extends RBaseNode {
                 dimNamesArray[ind++] = RRuntime.NAMES_ATTR_EMPTY_VALUE;
             }
             return -ind;
-        } else if (!vec.isArray() || getVectorDimensions(vec).length == 1) {
-            if (argNames == null) {
-                if (deparseLevel == 0) {
-                    dimNamesArray[ind++] = RRuntime.NAMES_ATTR_EMPTY_VALUE;
-                    return -ind;
+        } else {
+            if (!GetDimAttributeNode.isArray(rawDimensions) || rawDimensions.length == 1) {
+                if (argNames == null) {
+                    if (deparseLevel == 0) {
+                        dimNamesArray[ind++] = RRuntime.NAMES_ATTR_EMPTY_VALUE;
+                        return -ind;
+                    } else {
+                        String deparsedName = deparseArgName(promiseArgs, deparseLevel, vecInd);
+                        dimNamesArray[ind++] = deparsedName;
+                        return deparsedName == RRuntime.NAMES_ATTR_EMPTY_VALUE ? -ind : ind;
+                    }
                 } else {
-                    String deparsedName = deparseArgName(promiseArgs, deparseLevel, vecInd);
-                    dimNamesArray[ind++] = deparsedName;
-                    return deparsedName == RRuntime.NAMES_ATTR_EMPTY_VALUE ? -ind : ind;
+                    if (argNames[vecInd] == null) {
+                        dimNamesArray[ind++] = RRuntime.NAMES_ATTR_EMPTY_VALUE;
+                        return -ind;
+                    } else {
+                        dimNamesArray[ind++] = argNames[vecInd];
+                        return ind;
+                    }
                 }
             } else {
-                if (argNames[vecInd] == null) {
-                    dimNamesArray[ind++] = RRuntime.NAMES_ATTR_EMPTY_VALUE;
-                    return -ind;
-                } else {
-                    dimNamesArray[ind++] = argNames[vecInd];
-                    return ind;
-                }
+                RInternalError.unimplemented("binding multi-dimensional arrays is not supported");
+                return 0;
             }
-        } else {
-            RInternalError.unimplemented("binding multi-dimensional arrays is not supported");
-            return 0;
         }
     }
 
     /**
-     *
      * @param vectors vectors to be combined
      * @param res result dims
      * @param bindDims columns dim (cbind) or rows dim (rbind)
@@ -398,14 +399,16 @@ public abstract class Bind extends RBaseNode {
         int srcDim1Ind = type == BindType.cbind ? 0 : 1;
         int srcDim2Ind = type == BindType.cbind ? 1 : 0;
         assert vectors.length > 0;
-        int[] dim = getDimensions(vectors[0]);
+        RAbstractVector v = vectorProfile.profile(vectors[0]);
+        int[] dim = getDimensions(v, getVectorDimensions(v));
         assert dim.length == 2;
         bindDims[0] = dim[srcDim2Ind];
         res[srcDim1Ind] = dim[srcDim1Ind];
         res[srcDim2Ind] = dim[srcDim2Ind];
         boolean notEqualDims = false;
         for (int i = 1; i < vectors.length; i++) {
-            int[] dims = getDimensions(vectors[i]);
+            RAbstractVector v2 = vectorProfile.profile(vectors[i]);
+            int[] dims = getDimensions(v2, getVectorDimensions(v2));
             assert dims.length == 2;
             bindDims[i] = dims[srcDim2Ind];
             if (dims[srcDim1Ind] != res[srcDim1Ind]) {
@@ -419,11 +422,9 @@ public abstract class Bind extends RBaseNode {
         return notEqualDims;
     }
 
-    protected int[] getDimensions(RAbstractVector vector) {
-        RAbstractVector vectorProfiled = vectorProfile.profile(vector);
-        int[] dimensions = getVectorDimensions(vectorProfiled);
+    protected int[] getDimensions(RAbstractVector vector, int[] dimensions) {
         if (dimensions == null || dimensions.length != 2) {
-            return type == BindType.cbind ? new int[]{vectorProfiled.getLength(), 1} : new int[]{1, vectorProfiled.getLength()};
+            return type == BindType.cbind ? new int[]{vector.getLength(), 1} : new int[]{1, vector.getLength()};
         } else {
             assert dimensions.length == 2;
             return dimensions;
@@ -491,11 +492,11 @@ public abstract class Bind extends RBaseNode {
     protected Object allOneElem(int deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence,
                     @Cached("create()") SetDimNamesAttributeNode setDimNamesNode,
                     @Cached("create()") GetNamesAttributeNode getNamesNode) {
-        RAbstractVector vec = castVector(args[0]);
-        if (vec.isMatrix()) {
+        RAbstractVector vec = vectorProfile.profile(castVector(args[0]));
+        int[] rawDimensions = getVectorDimensions(vec);
+        if (GetDimAttributeNode.isMatrix(rawDimensions)) {
             return vec;
         }
-        int[] dims = getDimensions(vec);
         // for cbind dimNamesA is names for the 1st dim and dimNamesB is names for 2nd dim; for
         // rbind the other way around
         Object dimNamesA = getNamesNode.getNames(vec);
@@ -521,6 +522,7 @@ public abstract class Bind extends RBaseNode {
             dimNamesB = RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR);
         }
 
+        int[] dims = getDimensions(vec, rawDimensions);
         RVector<?> res = (RVector<?>) vec.copyWithNewDimensions(dims);
         setDimNamesNode.execute(res, RDataFactory.createList(type == BindType.cbind ? new Object[]{dimNamesA, dimNamesB} : new Object[]{dimNamesB, dimNamesA}));
         res.copyRegAttributesFrom(vec);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
index 0c56b90e339c57fe5fb953bc9ae5277506ece876..310b8758f5361a305ff6a03a777169ae0d993d37 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java
@@ -37,6 +37,8 @@ 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.GetFixedAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctionsFactory.GetDimAttributeNodeGen;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode;
@@ -82,11 +84,14 @@ public class IsTypeFunctions {
     @RBuiltin(name = "is.array", kind = PRIMITIVE, parameterNames = {"x"}, behavior = PURE)
     public abstract static class IsArray extends MissingAdapter {
 
+        private final ConditionProfile isArrayProfile = ConditionProfile.createBinaryProfile();
+        @Child private GetDimAttributeNode getDim = GetDimAttributeNodeGen.create();
+
         public abstract byte execute(Object value);
 
         @Specialization
         protected byte isType(RAbstractVector vector) {
-            return RRuntime.asLogical(vector.isArray());
+            return RRuntime.asLogical(isArrayProfile.profile(getDim.isArray(vector)));
         }
 
         @Specialization(guards = {"!isRMissing(value)", "!isRAbstractVector(value)"})
@@ -335,10 +340,11 @@ public class IsTypeFunctions {
     public abstract static class IsMatrix extends MissingAdapter {
 
         private final ConditionProfile isMatrixProfile = ConditionProfile.createBinaryProfile();
+        @Child private GetDimAttributeNode getDim = GetDimAttributeNodeGen.create();
 
         @Specialization
         protected byte isType(RAbstractVector vector) {
-            return RRuntime.asLogical(isMatrixProfile.profile(vector.isMatrix()));
+            return RRuntime.asLogical(isMatrixProfile.profile(getDim.isMatrix(vector)));
         }
 
         @Specialization(guards = {"!isRMissing(value)", "!isRAbstractVector(value)"})
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
index 54ea1667f9c2ad16c2241a538238538824630191..3ae66a186c491bf20a9f717c6112fa0e994037be 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Quantifier.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,7 @@ import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.profiles.BranchProfile;
+import com.oracle.truffle.api.profiles.ValueProfile;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.CastNode;
@@ -61,6 +62,21 @@ public abstract class Quantifier extends RBuiltinNode {
 
     @Children private final CastNode[] argCastNodes = new CastNode[MAX_CACHED_LENGTH];
 
+    private static final class ProfileCastNode extends CastNode {
+
+        private final ValueProfile profile = ValueProfile.createClassProfile();
+        @Child private CastNode next;
+
+        ProfileCastNode(CastNode next) {
+            this.next = next;
+        }
+
+        @Override
+        public Object execute(Object value) {
+            return profile.profile(next.execute(value));
+        }
+    }
+
     @Override
     public Object[] getDefaultParameterValues() {
         return new Object[]{RArgsValuesAndNames.EMPTY, RRuntime.LOGICAL_FALSE};
@@ -75,7 +91,7 @@ public abstract class Quantifier extends RBuiltinNode {
         CastBuilder argCastBuilder = new CastBuilder();
         argCastBuilder.arg(0).allowNull().shouldBe(integerValue().or(logicalValue()).or(instanceOf(RAbstractVector.class).and(size(0))), RError.Message.COERCING_ARGUMENT, argTypeName,
                         "logical").asLogicalVector();
-        argCastNodes[index] = insert(argCastBuilder.getCasts()[0]);
+        argCastNodes[index] = insert(new ProfileCastNode(argCastBuilder.getCasts()[0]));
     }
 
     protected boolean emptyVectorResult() {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckNode.java
index 10667a93e64b7f6b95a859e000e616aca120f108..b7fe92ffd5b67a4fe256fb013c1406ab65a32577 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCheckNode.java
@@ -135,7 +135,7 @@ abstract class PositionCheckNode extends Node {
             }
             int[] vectorDim = getVectorDimsNode.getDimensions(vector);
             if (nullDimensionsProfile.profile(vectorDim != null) && vectorDim.length == 2) {
-                if (vector instanceof RAbstractVector && ((RAbstractVector) vector).isArray()) {
+                if (vector instanceof RAbstractVector) {
                     if (castPosition instanceof RAbstractVector) {
                         if (getVectorPosDimsNode == null) {
                             CompilerDirectives.transferToInterpreterAndInvalidate();
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 bc0e2c8a3a6f17199f309e76b7b0f31b9606d8da..8db25088fa1a830d58a8a2797c953d2052f2511a 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -312,7 +312,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "setAttrInAttributable")
-        protected void setNamesInVector(RVector<?> x, RStringVector newNames,
+        protected void setNamesInVector(RAbstractVector x, RStringVector newNames,
                         @Cached("create()") BranchProfile namesTooLongProfile,
                         @Cached("createBinaryProfile()") ConditionProfile useDimNamesProfile,
                         @Cached("create()") GetDimAttributeNode getDimNode,
@@ -321,7 +321,7 @@ public final class SpecialAttributesFunctions {
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
                         @Cached("create()") ShareObjectNode updateRefCountNode) {
-            RVector<?> xProfiled = xTypeProfile.profile(x);
+            RAbstractVector xProfiled = xTypeProfile.profile(x);
             if (newNames.getLength() > xProfiled.getLength()) {
                 namesTooLongProfile.enter();
                 throw RError.error(this, RError.Message.ATTRIBUTE_VECTOR_SAME_LENGTH, RRuntime.NAMES_ATTR_KEY, newNames.getLength(), xProfiled.getLength());
@@ -348,7 +348,7 @@ public final class SpecialAttributesFunctions {
             }
         }
 
-        @Specialization(insertBefore = "setAttrInAttributable")
+        @Specialization(insertBefore = "setAttrInAttributable", guards = "!isRAbstractVector(x)")
         protected void setNamesInContainer(RAbstractContainer x, RStringVector newNames,
                         @Cached("createClassProfile()") ValueProfile contClassProfile) {
             RAbstractContainer xProfiled = contClassProfile.profile(x);
@@ -388,7 +388,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getVectorNames(RVector<?> x,
+        protected Object getVectorNames(RAbstractVector x,
                         @Cached("create()") BranchProfile attrNullProfile,
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
@@ -405,12 +405,10 @@ public final class SpecialAttributesFunctions {
                 }
                 return null;
             }
-
             return names;
-
         }
 
-        @Specialization(insertBefore = "getAttrFromAttributable")
+        @Specialization(insertBefore = "getAttrFromAttributable", guards = "!isRAbstractVector(x)")
         protected Object getVectorNames(RAbstractContainer x,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
                         @Cached("create()") RAttributeProfiles attrProfiles) {
@@ -478,7 +476,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "setAttrInAttributable")
-        protected void setDimsInVector(RVector<?> x, RAbstractIntVector dims,
+        protected void setDimsInVector(RAbstractVector x, RAbstractIntVector dims,
                         @Cached("create()") BranchProfile attrNullProfile,
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
@@ -498,7 +496,7 @@ public final class SpecialAttributesFunctions {
             super.setAttrInAttributable(x, dims, attrNullProfile, attrStorageProfile, xTypeProfile, updateRefCountNode);
         }
 
-        @Specialization(insertBefore = "setAttrInAttributable")
+        @Specialization(insertBefore = "setAttrInAttributable", guards = "!isRAbstractVector(x)")
         protected void setDimsInContainerFallback(RAbstractContainer x, RAbstractIntVector dims,
                         @Cached("create()") SetDimAttributeNode setDimNode) {
             int[] dimsArr = dims.materialize().getDataCopy();
@@ -592,6 +590,24 @@ public final class SpecialAttributesFunctions {
             return nullDimsProfile.profile(dims == null) ? null : dims.getInternalStore();
         }
 
+        public static boolean isArray(int[] dimensions) {
+            return dimensions != null && dimensions.length > 0;
+        }
+
+        public static boolean isMatrix(int[] dimensions) {
+            return dimensions != null && dimensions.length == 2;
+        }
+
+        public final boolean isArray(RAbstractVector vector) {
+            RIntVector dims = (RIntVector) execute(vector);
+            return nullDimsProfile.profile(dims == null) ? false : dims.getLength() > 0;
+        }
+
+        public final boolean isMatrix(RAbstractVector vector) {
+            RIntVector dims = (RIntVector) execute(vector);
+            return nullDimsProfile.profile(dims == null) ? false : dims.getLength() == 2;
+        }
+
         @Specialization(insertBefore = "getAttrFromAttributable")
         protected Object getScalarVectorDims(@SuppressWarnings("unused") RScalarVector x) {
             return null;
@@ -786,14 +802,14 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getVectorDimNames(RVector<?> x,
+        protected Object getVectorDimNames(RAbstractVector x,
                         @Cached("create()") BranchProfile attrNullProfile,
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile) {
             return super.getAttrFromAttributable(x, attrNullProfile, attrStorageProfile, xTypeProfile);
         }
 
-        @Specialization(insertBefore = "getAttrFromAttributable")
+        @Specialization(insertBefore = "getAttrFromAttributable", guards = "!isRAbstractVector(x)")
         protected Object getVectorDimNames(RAbstractContainer x,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
                         @Cached("create()") RAttributeProfiles attrProfiles) {
@@ -829,7 +845,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "setAttrInAttributable")
-        protected void setRowNamesInVector(RVector<?> x, RAbstractVector newRowNames,
+        protected void setRowNamesInVector(RAbstractVector x, RAbstractVector newRowNames,
                         @Cached("create()") BranchProfile attrNullProfile,
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
@@ -843,7 +859,7 @@ public final class SpecialAttributesFunctions {
             setAttrInAttributable(x, newRowNames, attrNullProfile, attrStorageProfile, xTypeProfile, updateRefCountNode);
         }
 
-        @Specialization(insertBefore = "setAttrInAttributable")
+        @Specialization(insertBefore = "setAttrInAttributable", guards = "!isRAbstractVector(x)")
         protected void setRowNamesInContainer(RAbstractContainer x, RAbstractVector rowNames, @Cached("createClassProfile()") ValueProfile contClassProfile) {
             RAbstractContainer xProfiled = contClassProfile.profile(x);
             xProfiled.setRowNames(rowNames);
@@ -926,7 +942,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "setAttrInAttributable")
-        protected <T> void handleVectorNullClass(RVector<T> vector, @SuppressWarnings("unused") RNull classAttr,
+        protected <T> void handleVectorNullClass(RAbstractVector vector, @SuppressWarnings("unused") RNull classAttr,
                         @Cached("createClass()") RemoveFixedAttributeNode removeClassAttrNode,
                         @Cached("createBinaryProfile()") ConditionProfile initAttrProfile,
                         @Cached("create()") BranchProfile nullAttrProfile,
@@ -939,7 +955,7 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "setAttrInAttributable")
-        protected <T> void handleVector(RVector<T> vector, RStringVector classAttr,
+        protected <T> void handleVector(RAbstractVector vector, RStringVector classAttr,
                         @Cached("createClass()") RemoveFixedAttributeNode removeClassAttrNode,
                         @Cached("createBinaryProfile()") ConditionProfile initAttrProfile,
                         @Cached("create()") BranchProfile nullAttrProfile,
@@ -989,12 +1005,12 @@ public final class SpecialAttributesFunctions {
             }
         }
 
-        @Specialization(insertBefore = "setAttrInAttributable")
+        @Specialization(insertBefore = "setAttrInAttributable", guards = "!isRAbstractVector(x)")
         protected void handleAttributable(RAttributable x, @SuppressWarnings("unused") RNull classAttr) {
             x.setClassAttr(null);
         }
 
-        @Specialization(insertBefore = "setAttrInAttributable")
+        @Specialization(insertBefore = "setAttrInAttributable", guards = "!isRAbstractVector(x)")
         protected void handleAttributable(RAttributable x, RStringVector classAttr) {
             x.setClassAttr(classAttr);
         }
@@ -1039,14 +1055,14 @@ public final class SpecialAttributesFunctions {
         }
 
         @Specialization(insertBefore = "getAttrFromAttributable")
-        protected Object getVectorClass(RVector<?> x,
+        protected Object getVectorClass(RAbstractVector x,
                         @Cached("create()") BranchProfile attrNullProfile,
                         @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile) {
             return super.getAttrFromAttributable(x, attrNullProfile, attrStorageProfile, xTypeProfile);
         }
 
-        @Specialization(insertBefore = "getAttrFromAttributable")
+        @Specialization(insertBefore = "getAttrFromAttributable", guards = "!isRAbstractVector(x)")
         protected Object getVectorClass(RAbstractContainer x,
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
                         @Cached("create()") RAttributeProfiles attrProfiles) {