diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
index 0977298652e9af68fe7ab8bd7a591b384d8c388f..2677032f64c39371eead62102ce392dbc3b817fd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsFiniteFunctions.java
@@ -30,18 +30,12 @@ import java.util.Arrays;
 import java.util.function.DoublePredicate;
 import java.util.function.IntPredicate;
 
-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.Fallback;
 import com.oracle.truffle.api.dsl.ImportStatic;
 import com.oracle.truffle.api.dsl.Specialization;
 import com.oracle.truffle.api.interop.TruffleObject;
-import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNamesAttributeNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.InitDimsNamesDimNamesNode;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
 import com.oracle.truffle.r.nodes.unary.TypeofNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -49,7 +43,6 @@ import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
-import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector;
@@ -65,12 +58,7 @@ public class IsFiniteFunctions {
     @ImportStatic(RRuntime.class)
     public abstract static class Adapter extends RBuiltinNode.Arg1 {
 
-        @Child private GetDimAttributeNode getDims = GetDimAttributeNode.create();
-        @Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
-        @Child private GetDimNamesAttributeNode getDimNames = GetDimNamesAttributeNode.create();
-        @Child private SetDimNamesAttributeNode setDimNames;
-
-        @CompilationFinal private ConditionProfile setDimNamesProfile;
+        @Child private InitDimsNamesDimNamesNode initDimsNamesDimNames = InitDimsNamesDimNamesNode.create();
 
         @FunctionalInterface
         protected interface ComplexPredicate {
@@ -112,7 +100,9 @@ public class IsFiniteFunctions {
         protected RLogicalVector doFunConstant(RAbstractVector x, byte value) {
             byte[] b = new byte[x.getLength()];
             Arrays.fill(b, value);
-            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
+            RLogicalVector result = RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            initDimsNamesDimNames.initAttributes(result, x);
+            return result;
         }
 
         protected RLogicalVector doFunDouble(RAbstractDoubleVector x, DoublePredicate fun) {
@@ -120,7 +110,9 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
+            RLogicalVector result = RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            initDimsNamesDimNames.initAttributes(result, x);
+            return result;
         }
 
         protected RLogicalVector doFunLogical(RAbstractLogicalVector x, LogicalPredicate fun) {
@@ -128,7 +120,9 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
+            RLogicalVector result = RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            initDimsNamesDimNames.initAttributes(result, x);
+            return result;
         }
 
         protected RLogicalVector doFunInt(RAbstractIntVector x, IntPredicate fun) {
@@ -136,7 +130,9 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
+            RLogicalVector result = RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            initDimsNamesDimNames.initAttributes(result, x);
+            return result;
         }
 
         protected RLogicalVector doFunComplex(RAbstractComplexVector x, ComplexPredicate fun) {
@@ -144,21 +140,8 @@ public class IsFiniteFunctions {
             for (int i = 0; i < b.length; i++) {
                 b[i] = RRuntime.asLogical(fun.test(x.getDataAt(i)));
             }
-            return transferDimNames(RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR, getDims.getDimensions(x), getNames.getNames(x)), x);
-        }
-
-        RLogicalVector transferDimNames(RLogicalVector result, RAbstractVector src) {
-            RList dimNames = getDimNames.getDimNames(src);
-            if (setDimNamesProfile == null) {
-                CompilerDirectives.transferToInterpreterAndInvalidate();
-                setDimNamesProfile = ConditionProfile.createBinaryProfile();
-            }
-            if (setDimNamesProfile.profile(dimNames != null)) {
-                if (setDimNames == null) {
-                    setDimNames = insert(SetDimNamesAttributeNode.create());
-                }
-                setDimNames.setDimNames(result, dimNames);
-            }
+            RLogicalVector result = RDataFactory.createLogicalVector(b, RDataFactory.COMPLETE_VECTOR);
+            initDimsNamesDimNames.initAttributes(result, x);
             return result;
         }
     }
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
index 09bde8d617b02030f4f908522f51447acb1d3173..59ba9f961eea560aaadd527e6d8eec5084f4b67b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LogFunctions.java
@@ -37,8 +37,7 @@ 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.CopyOfRegAttributesNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode;
-import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
+import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.InitDimsNamesDimNamesNode;
 import com.oracle.truffle.r.nodes.binary.BinaryMapArithmeticFunctionNode;
 import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef;
 import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
@@ -165,24 +164,22 @@ public class LogFunctions {
                         @Cached("createClassProfile()") ValueProfile vectorProfile,
                         @Cached("createBinaryProfile()") ConditionProfile isNAProfile,
                         @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
-                        @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") InitDimsNamesDimNamesNode initDimsNamesDimNames,
                         @Cached("create()") NACheck xNACheck,
                         @Cached("create()") NACheck baseNACheck) {
             RAbstractDoubleVector doubleVector = (RAbstractDoubleVector) vectorProfile.profile(vector).castSafe(RType.Double, isNAProfile);
-            return logInternal(doubleVector, base, copyAttrsNode, getNamesNode, getDimsNode, xNACheck, baseNACheck);
+            return logInternal(doubleVector, base, copyAttrsNode, initDimsNamesDimNames, xNACheck, baseNACheck);
         }
 
         @Specialization
         protected RComplexVector log(RAbstractComplexVector vector, double base,
                         @Cached("createClassProfile()") ValueProfile vectorProfile,
                         @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
-                        @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") InitDimsNamesDimNamesNode initDimsNamesDimNames,
                         @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
                         @Cached("create()") NACheck xNACheck,
                         @Cached("create()") NACheck baseNACheck) {
-            return logInternal(vectorProfile.profile(vector), RComplex.valueOf(base, 0), divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
+            return logInternal(vectorProfile.profile(vector), RComplex.valueOf(base, 0), divNode, initDimsNamesDimNames, copyAttrsNode, xNACheck, baseNACheck);
         }
 
         @Specialization
@@ -190,16 +187,15 @@ public class LogFunctions {
                         @Cached("createClassProfile()") ValueProfile vectorProfile,
                         @Cached("createBinaryProfile()") ConditionProfile isNAProfile,
                         @Cached("create()") CopyOfRegAttributesNode copyAttrsNode,
-                        @Cached("create()") GetNamesAttributeNode getNamesNode,
-                        @Cached("create()") GetDimAttributeNode getDimsNode,
+                        @Cached("create()") InitDimsNamesDimNamesNode initDimsNamesDimNames,
                         @Cached("createDivNode()") BinaryMapArithmeticFunctionNode divNode,
                         @Cached("create()") NACheck xNACheck,
                         @Cached("create()") NACheck baseNACheck) {
             RAbstractComplexVector complexVector = (RAbstractComplexVector) vectorProfile.profile(vector).castSafe(RType.Complex, isNAProfile);
-            return logInternal(complexVector, base, divNode, getDimsNode, getNamesNode, copyAttrsNode, xNACheck, baseNACheck);
+            return logInternal(complexVector, base, divNode, initDimsNamesDimNames, copyAttrsNode, xNACheck, baseNACheck);
         }
 
-        private RDoubleVector logInternal(RAbstractDoubleVector vector, double base, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode, GetDimAttributeNode getDimsNode,
+        private RDoubleVector logInternal(RAbstractDoubleVector vector, double base, CopyOfRegAttributesNode copyAttrsNode, InitDimsNamesDimNamesNode initDimsNamesDimNames,
                         NACheck xNACheck, NACheck baseNACheck) {
             baseNACheck.enable(base);
             double[] resultVector = new double[vector.getLength()];
@@ -220,7 +216,7 @@ public class LogFunctions {
                 }
             }
             boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA();
-            return createResult(vector, resultVector, complete, copyAttrsNode, getNamesNode, getDimsNode);
+            return createResult(vector, resultVector, complete, copyAttrsNode, initDimsNamesDimNames);
         }
 
         private double logb(double x, double base, NAProfile naBase) {
@@ -258,8 +254,8 @@ public class LogFunctions {
             return result;
         }
 
-        private RComplexVector logInternal(RAbstractComplexVector vector, RComplex base, BinaryMapArithmeticFunctionNode divNode, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode,
-                        CopyOfRegAttributesNode copyAttrsNode, NACheck xNACheck, NACheck baseNACheck) {
+        private RComplexVector logInternal(RAbstractComplexVector vector, RComplex base, BinaryMapArithmeticFunctionNode divNode,
+                        InitDimsNamesDimNamesNode initDimsNamesDimNames, CopyOfRegAttributesNode copyAttrsNode, NACheck xNACheck, NACheck baseNACheck) {
             baseNACheck.enable(base);
             double[] complexVector = new double[vector.getLength() * 2];
             if (baseNACheck.check(base)) {
@@ -285,7 +281,7 @@ public class LogFunctions {
                 }
             }
             boolean complete = xNACheck.neverSeenNA() && baseNACheck.neverSeenNA();
-            return createResult(vector, complexVector, complete, getDimsNode, getNamesNode, copyAttrsNode);
+            return createResult(vector, complexVector, complete, initDimsNamesDimNames, copyAttrsNode);
         }
 
         private static void fill(double[] array, int i, RComplex rc) {
@@ -328,16 +324,18 @@ public class LogFunctions {
             return RComplex.valueOf(Math.log(mod), arg);
         }
 
-        private static RDoubleVector createResult(RAbstractVector source, double[] resultData, boolean complete, CopyOfRegAttributesNode copyAttrsNode, GetNamesAttributeNode getNamesNode,
-                        GetDimAttributeNode getDimsNode) {
-            RDoubleVector result = RDataFactory.createDoubleVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source));
+        private static RDoubleVector createResult(RAbstractVector source, double[] resultData, boolean complete,
+                        CopyOfRegAttributesNode copyAttrsNode, InitDimsNamesDimNamesNode initDimsNamesDimNames) {
+            RDoubleVector result = RDataFactory.createDoubleVector(resultData, complete);
+            initDimsNamesDimNames.initAttributes(result, source);
             copyAttrsNode.execute(source, result);
             return result;
         }
 
-        private static RComplexVector createResult(RAbstractVector source, double[] resultData, boolean complete, GetDimAttributeNode getDimsNode, GetNamesAttributeNode getNamesNode,
-                        CopyOfRegAttributesNode copyAttrsNode) {
-            RComplexVector result = RDataFactory.createComplexVector(resultData, complete, getDimsNode.getDimensions(source), getNamesNode.getNames(source));
+        private static RComplexVector createResult(RAbstractVector source, double[] resultData, boolean complete,
+                        InitDimsNamesDimNamesNode initDimsNamesDimNames, CopyOfRegAttributesNode copyAttrsNode) {
+            RComplexVector result = RDataFactory.createComplexVector(resultData, complete);
+            initDimsNamesDimNames.initAttributes(result, source);
             copyAttrsNode.execute(source, result);
             return result;
         }
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 30896b1446fccb004ddfc74b1a6964a6637fbf8a..aa5ab4daaf5c8e4ea9176bbdeaaf1fbdddedceca 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
@@ -31,6 +31,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.api.profiles.ValueProfile;
+import com.oracle.truffle.r.nodes.access.vector.ExtractListElement;
 import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctionsFactory.GetDimAttributeNodeGen;
 import com.oracle.truffle.r.nodes.function.opt.ShareObjectNode;
 import com.oracle.truffle.r.runtime.RError;
@@ -439,16 +440,17 @@ public final class SpecialAttributesFunctions {
                         @Cached("createClassProfile()") ValueProfile xTypeProfile,
                         @Cached("create()") BranchProfile namesNullProfile,
                         @Cached("create()") BranchProfile dimNamesAvlProfile,
-                        @Cached("create()") GetDimNamesAttributeNode getDimNames) {
+                        @Cached("create()") GetDimNamesAttributeNode getDimNames,
+                        @Cached("create()") ExtractListElement extractListElement) {
             RStringVector names = (RStringVector) super.getAttrFromAttributable(x, attrNullProfile, attrStorageProfile, xTypeProfile);
             if (names == null) {
                 namesNullProfile.enter();
                 RList dimNames = getDimNames.getDimNames(x);
                 if (dimNames != null && dimNames.getLength() == 1) {
                     dimNamesAvlProfile.enter();
-                    Object dimName = dimNames.getDataAt(0);
-                    return (dimName != RNull.instance) ? dimName : null; // For
-                                                                         // ".Dimnames=list(NULL)"
+                    Object dimName = extractListElement.execute(dimNames, 0);
+                    // RNull for ".Dimnames=list(NULL)"
+                    return (dimName != RNull.instance) ? dimName : null;
                 }
                 return null;
             }
@@ -878,6 +880,104 @@ public final class SpecialAttributesFunctions {
         }
     }
 
+    public abstract static class InitDimsNamesDimNamesNode extends RBaseNode {
+
+        private final ConditionProfile oldAttrsNullProfile = ConditionProfile.createBinaryProfile();
+        private final ConditionProfile doAnythingProfile = ConditionProfile.createBinaryProfile();
+
+        @Child private GetDimAttributeNode getDimNode;
+        @Child private GetNamesAttributeNode getNamesNode;
+        @Child private GetDimNamesAttributeNode getDimNamesNode;
+
+        protected InitDimsNamesDimNamesNode() {
+        }
+
+        public static InitDimsNamesDimNamesNode create() {
+            return SpecialAttributesFunctionsFactory.InitDimsNamesDimNamesNodeGen.create();
+        }
+
+        public void initAttributes(RAbstractContainer x, int[] dimensions, RStringVector names, RList dimNames) {
+            if (doAnythingProfile.profile(dimensions != null || names != null || dimNames != null)) {
+                execute(x, dimensions, names, dimNames);
+            }
+        }
+
+        public void initAttributes(RAbstractContainer x, RAbstractContainer source) {
+            if (getDimNode == null) {
+                getDimNode = insert(GetDimAttributeNode.create());
+                getNamesNode = insert(GetNamesAttributeNode.create());
+                getDimNamesNode = insert(GetDimNamesAttributeNode.create());
+            }
+            this.initAttributes(x, getDimNode.getDimensions(source), getNamesNode.getNames(source), getDimNamesNode.getDimNames(source));
+        }
+
+        public abstract void execute(RAbstractContainer x, int[] dimensions, RStringVector names, RList dimNames);
+
+        @Specialization
+        protected void initContainerAttributes(RAbstractContainer x, int[] dimensions, RStringVector names, RList dimNames,
+                        @Cached("create()") ShareObjectNode shareObjectNode) {
+            assert names != x;
+            assert dimNames != x;
+            DynamicObject attrs = x.getAttributes();
+            if (dimNames != null) {
+                shareObjectNode.execute(dimNames);
+            }
+            if (names != null) {
+                assert names.getLength() == x.getLength() : "size mismatch: names.length=" + names.getLength() + " vs. length=" + x.getLength();
+                if (dimensions != null && dimensions.length == 1) {
+                    // one-dimensional arrays do not have names, only dimnames with one value
+                    if (dimNames == null) {
+                        shareObjectNode.execute(names);
+                        dimNames = RDataFactory.createList(new Object[]{names});
+                    }
+                    names = null;
+                } else {
+                    shareObjectNode.execute(names);
+                }
+            }
+
+            if (attrs == null) {
+                if (dimensions != null) {
+                    RIntVector dimensionsVector = RDataFactory.createIntVector(dimensions, true);
+                    if (dimNames != null) {
+                        attrs = RAttributesLayout.createDimAndDimNames(dimensionsVector, dimNames);
+                        if (names != null) {
+                            attrs.define(RRuntime.NAMES_ATTR_KEY, names);
+                        }
+                    } else {
+                        if (names != null) {
+                            attrs = RAttributesLayout.createNamesAndDim(names, dimensionsVector);
+                        } else {
+                            attrs = RAttributesLayout.createDim(dimensionsVector);
+                        }
+                    }
+                } else {
+                    if (dimNames != null) {
+                        attrs = RAttributesLayout.createDimNames(dimNames);
+                        if (names != null) {
+                            attrs.define(RRuntime.NAMES_ATTR_KEY, names);
+                        }
+                    } else {
+                        assert (names != null); // only called with at least one attr != null
+                        attrs = RAttributesLayout.createNames(names);
+                    }
+                }
+                x.initAttributes(attrs);
+            } else { // attrs != null
+                if (dimensions != null) {
+                    RIntVector dimensionsVector = RDataFactory.createIntVector(dimensions, true);
+                    x.setAttr(RRuntime.DIM_ATTR_KEY, dimensionsVector);
+                }
+                if (names != null) {
+                    x.setAttr(RRuntime.NAMES_ATTR_KEY, names);
+                }
+                if (dimNames != null) {
+                    x.setAttr(RRuntime.DIMNAMES_ATTR_KEY, dimNames);
+                }
+            }
+        }
+    }
+
     public abstract static class SetRowNamesAttributeNode extends SetSpecialAttributeNode {
 
         private final ConditionProfile nullRowNamesProfile = ConditionProfile.createBinaryProfile();
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
index f8c0488a44e0c579aa393c39f7e671c8471297b4..26503bfece54f28770a35e3d24fdfa35c5995abc 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java
@@ -37,20 +37,21 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract
 
     private final double[] data;
 
-    RComplexVector(double[] data, boolean complete, int[] dims, RStringVector names) {
-        super(complete, data.length >> 1, dims, names);
+    RComplexVector(double[] data, boolean complete) {
+        super(complete);
         assert data.length % 2 == 0;
         this.data = data;
         assert verify();
     }
 
-    private RComplexVector(double[] data, boolean complete, int[] dims) {
-        this(data, complete, dims, null);
+    RComplexVector(double[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        this(data, complete);
+        initDimsNamesDimNames(dims, names, dimNames);
     }
 
     @Override
     protected RComplexVector internalCopy() {
-        return new RComplexVector(Arrays.copyOf(data, data.length), this.isComplete(), null);
+        return new RComplexVector(Arrays.copyOf(data, data.length), this.isComplete());
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index eb98e8cdd860a965330f16fb53512c3de75354cc..06f3c97902603be00b2dd49044ba68de9b30138f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
@@ -69,7 +69,7 @@ public final class RDataFactory {
     }
 
     public static RIntVector createIntVector(int[] data, boolean complete) {
-        return createIntVector(data, complete, null, null);
+        return traceDataCreated(new RIntVector(data, complete));
     }
 
     public static RIntVector createIntVector(int[] data, boolean complete, int[] dims) {
@@ -81,7 +81,11 @@ public final class RDataFactory {
     }
 
     public static RIntVector createIntVector(int[] data, boolean complete, int[] dims, RStringVector names) {
-        return traceDataCreated(new RIntVector(data, complete, dims, names));
+        return createIntVector(data, complete, dims, names, null);
+    }
+
+    public static RIntVector createIntVector(int[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        return traceDataCreated(new RIntVector(data, complete, dims, names, dimNames));
     }
 
     public static RDoubleVector createDoubleVector(int length) {
@@ -97,7 +101,7 @@ public final class RDataFactory {
     }
 
     public static RDoubleVector createDoubleVector(double[] data, boolean complete) {
-        return createDoubleVector(data, complete, null, null);
+        return traceDataCreated(new RDoubleVector(data, complete));
     }
 
     public static RDoubleVector createDoubleVector(double[] data, boolean complete, int[] dims) {
@@ -109,7 +113,11 @@ public final class RDataFactory {
     }
 
     public static RDoubleVector createDoubleVector(double[] data, boolean complete, int[] dims, RStringVector names) {
-        return traceDataCreated(new RDoubleVector(data, complete, dims, names));
+        return createDoubleVector(data, complete, dims, names, null);
+    }
+
+    public static RDoubleVector createDoubleVector(double[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        return traceDataCreated(new RDoubleVector(data, complete, dims, names, dimNames));
     }
 
     public static RRawVector createRawVector(int length) {
@@ -117,7 +125,7 @@ public final class RDataFactory {
     }
 
     public static RRawVector createRawVector(byte[] data) {
-        return createRawVector(data, null, null);
+        return traceDataCreated(new RRawVector(data));
     }
 
     public static RRawVector createRawVector(byte[] data, int[] dims) {
@@ -129,7 +137,11 @@ public final class RDataFactory {
     }
 
     public static RRawVector createRawVector(byte[] data, int[] dims, RStringVector names) {
-        return traceDataCreated(new RRawVector(data, dims, names));
+        return createRawVector(data, dims, names, null);
+    }
+
+    public static RRawVector createRawVector(byte[] data, int[] dims, RStringVector names, RList dimNames) {
+        return traceDataCreated(new RRawVector(data, dims, names, dimNames));
     }
 
     public static RComplexVector createComplexVector(int length) {
@@ -144,11 +156,11 @@ public final class RDataFactory {
                 data[i + 1] = RRuntime.COMPLEX_NA_IMAGINARY_PART;
             }
         }
-        return createComplexVector(data, !fillNA, null, null);
+        return createComplexVector(data, !fillNA);
     }
 
     public static RComplexVector createComplexVector(double[] data, boolean complete) {
-        return createComplexVector(data, complete, null, null);
+        return traceDataCreated(new RComplexVector(data, complete));
     }
 
     public static RComplexVector createComplexVector(double[] data, boolean complete, int[] dims) {
@@ -160,11 +172,15 @@ public final class RDataFactory {
     }
 
     public static RComplexVector createComplexVector(double[] data, boolean complete, int[] dims, RStringVector names) {
-        return traceDataCreated(new RComplexVector(data, complete, dims, names));
+        return createComplexVector(data, complete, dims, names, null);
+    }
+
+    public static RComplexVector createComplexVector(double[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        return traceDataCreated(new RComplexVector(data, complete, dims, names, dimNames));
     }
 
     public static RStringVector createStringVector(String value) {
-        return createStringVector(new String[]{value}, !RRuntime.isNA(value), null, null);
+        return createStringVector(new String[]{value}, !RRuntime.isNA(value));
     }
 
     public static RStringVector createStringVector(int length) {
@@ -182,7 +198,7 @@ public final class RDataFactory {
     }
 
     public static RStringVector createStringVector(String[] data, boolean complete) {
-        return createStringVector(data, complete, null, null);
+        return traceDataCreated(new RStringVector(data, complete));
     }
 
     public static RStringVector createStringVector(String[] data, boolean complete, int[] dims) {
@@ -194,7 +210,11 @@ public final class RDataFactory {
     }
 
     public static RStringVector createStringVector(String[] data, boolean complete, int[] dims, RStringVector names) {
-        return traceDataCreated(new RStringVector(data, complete, dims, names));
+        return createStringVector(data, complete, dims, names, null);
+    }
+
+    public static RStringVector createStringVector(String[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        return traceDataCreated(new RStringVector(data, complete, dims, names, dimNames));
     }
 
     public static RLogicalVector createLogicalVector(int length) {
@@ -206,11 +226,11 @@ public final class RDataFactory {
         if (fillNA) {
             Arrays.fill(data, RRuntime.LOGICAL_NA);
         }
-        return createLogicalVector(data, false, null, null);
+        return createLogicalVector(data, false);
     }
 
     public static RLogicalVector createLogicalVector(byte[] data, boolean complete) {
-        return createLogicalVector(data, complete, null, null);
+        return traceDataCreated(new RLogicalVector(data, complete));
     }
 
     public static RLogicalVector createLogicalVector(byte[] data, boolean complete, int[] dims) {
@@ -222,7 +242,11 @@ public final class RDataFactory {
     }
 
     public static RLogicalVector createLogicalVector(byte[] data, boolean complete, int[] dims, RStringVector names) {
-        return traceDataCreated(new RLogicalVector(data, complete, dims, names));
+        return createLogicalVector(data, complete, dims, names, null);
+    }
+
+    public static RLogicalVector createLogicalVector(byte[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        return traceDataCreated(new RLogicalVector(data, complete, dims, names, dimNames));
     }
 
     public static RLogicalVector createNAVector(int length) {
@@ -359,7 +383,7 @@ public final class RDataFactory {
     }
 
     public static RList createList(Object[] data) {
-        return createList(data, null, null);
+        return traceDataCreated(new RList(data));
     }
 
     public static RComplex createComplexZero() {
@@ -375,11 +399,11 @@ public final class RDataFactory {
     }
 
     public static RList createList() {
-        return createList(new Object[0], null, null);
+        return createList(new Object[0]);
     }
 
     public static RList createList(int n) {
-        return createList(createRNullArray(n), null, null);
+        return createList(createRNullArray(n));
     }
 
     public static RList createList(int size, RStringVector names) {
@@ -391,7 +415,11 @@ public final class RDataFactory {
     }
 
     public static RList createList(Object[] data, int[] newDimensions, RStringVector names) {
-        return traceDataCreated(new RList(data, newDimensions, names));
+        return createList(data, newDimensions, names, null);
+    }
+
+    public static RList createList(Object[] data, int[] newDimensions, RStringVector names, RList dimNames) {
+        return traceDataCreated(new RList(data, newDimensions, names, dimNames));
     }
 
     public static RExpression createExpression(int size) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
index 52366b1ae86c5a4e41c6927140452ebbe52043c8..aba05f10a7db066f2269327c97f558ff8e5e7219 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java
@@ -37,14 +37,15 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
 
     private final double[] data;
 
-    RDoubleVector(double[] data, boolean complete, int[] dims, RStringVector names) {
-        super(complete, data.length, dims, names);
+    RDoubleVector(double[] data, boolean complete) {
+        super(complete);
         this.data = data;
         assert verify();
     }
 
-    private RDoubleVector(double[] data, boolean complete, int[] dims) {
-        this(data, complete, dims, null);
+    RDoubleVector(double[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        this(data, complete);
+        initDimsNamesDimNames(dims, names, dimNames);
     }
 
     @Override
@@ -67,7 +68,7 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
 
     @Override
     protected RDoubleVector internalCopy() {
-        return new RDoubleVector(Arrays.copyOf(data, data.length), this.isComplete(), null);
+        return new RDoubleVector(Arrays.copyOf(data, data.length), this.isComplete());
     }
 
     @Override
@@ -95,7 +96,7 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD
                 break;
             }
         }
-        RDoubleVector result = new RDoubleVector(newData, isComplete, null);
+        RDoubleVector result = new RDoubleVector(newData, isComplete);
         setAttributes(result);
         return result;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
index e8cbeb5a4e73d8d7f97be1fa5774fbfede93c691..2e0463d5598a60d179459766246a95f4569ab2c7 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RExpression.java
@@ -31,7 +31,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 public final class RExpression extends RListBase implements RAbstractVector {
 
     RExpression(Object[] data, int[] dims, RStringVector names) {
-        super(data, dims, names);
+        super(data, dims, names, null);
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
index d95bb428e4a28c9fed63b1a57ae8527276bf708f..face5053d948c54629159b8c5f306d61c84978cb 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java
@@ -37,14 +37,15 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
 
     private final int[] data;
 
-    RIntVector(int[] data, boolean complete, int[] dims, RStringVector names) {
-        super(complete, data.length, dims, names);
+    RIntVector(int[] data, boolean complete) {
+        super(complete);
         this.data = data;
         assert verify();
     }
 
-    private RIntVector(int[] data, boolean complete, int[] dims) {
-        this(data, complete, dims, null);
+    RIntVector(int[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        this(data, complete);
+        initDimsNamesDimNames(dims, names, dimNames);
     }
 
     @Override
@@ -89,7 +90,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
 
     @Override
     protected RIntVector internalCopy() {
-        return new RIntVector(Arrays.copyOf(data, data.length), isComplete(), null);
+        return new RIntVector(Arrays.copyOf(data, data.length), isComplete());
     }
 
     public RIntVector copyResetData(int[] newData) {
@@ -100,7 +101,7 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect
                 break;
             }
         }
-        RIntVector result = new RIntVector(newData, isComplete, null);
+        RIntVector result = new RIntVector(newData, isComplete);
         setAttributes(result);
         return result;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
index 4b0bb9a76b856198d26874513fa49fb2100aef33..650c2f1173a80e6c7cf1f3b8dd5c56724421af39 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java
@@ -31,8 +31,12 @@ public final class RList extends RListBase implements RAbstractListVector {
 
     public String elementNamePrefix;
 
-    RList(Object[] data, int[] dims, RStringVector names) {
-        super(data, dims, names);
+    RList(Object[] data) {
+        super(data);
+    }
+
+    RList(Object[] data, int[] dims, RStringVector names, RList dimNames) {
+        super(data, dims, names, dimNames);
     }
 
     @Override
@@ -42,7 +46,7 @@ public final class RList extends RListBase implements RAbstractListVector {
 
     @Override
     protected RList internalCopy() {
-        return new RList(Arrays.copyOf(data, data.length), getDimensionsInternal(), null);
+        return new RList(Arrays.copyOf(data, data.length), getDimensionsInternal(), null, null);
     }
 
     @TruffleBoundary
@@ -54,7 +58,7 @@ public final class RList extends RListBase implements RAbstractListVector {
     protected RList internalDeepCopy() {
         // TOOD: only used for nested list updates, but still could be made faster (through a
         // separate AST node?)
-        RList listCopy = new RList(Arrays.copyOf(data, data.length), getDimensionsInternal(), null);
+        RList listCopy = new RList(Arrays.copyOf(data, data.length), getDimensionsInternal(), null, null);
         for (int i = 0; i < listCopy.getLength(); i++) {
             Object el = listCopy.getDataAt(i);
             if (el instanceof RVector) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
index 4a796edb8499890e7203816ac3d434c52f90d2f7..305e605d2621b422c7365abfb63dfe30646abe25 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java
@@ -50,12 +50,17 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi
 
     protected final Object[] data;
 
-    RListBase(Object[] data, int[] dims, RStringVector names) {
-        super(false, data.length, dims, names);
+    RListBase(Object[] data) {
+        super(false);
         this.data = data;
         assert verify();
     }
 
+    RListBase(Object[] data, int[] dims, RStringVector names, RList dimNames) {
+        this(data);
+        initDimsNamesDimNames(dims, names, dimNames);
+    }
+
     @Override
     public final int getLength() {
         return data.length;
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
index 3bde20df8e776d6571b91dd07dee09db4b6c2988..5f0472308588aee30a4952a3311e835a55c7d612 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java
@@ -37,14 +37,15 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
 
     private final byte[] data;
 
-    RLogicalVector(byte[] data, boolean complete, int[] dims, RStringVector names) {
-        super(complete, data.length, dims, names);
+    RLogicalVector(byte[] data, boolean complete) {
+        super(complete);
         this.data = data;
         assert verify();
     }
 
-    private RLogicalVector(byte[] data, boolean complete, int[] dims) {
-        this(data, complete, dims, null);
+    RLogicalVector(byte[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        this(data, complete);
+        initDimsNamesDimNames(dims, names, dimNames);
     }
 
     @Override
@@ -86,7 +87,7 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
 
     @Override
     protected RLogicalVector internalCopy() {
-        return new RLogicalVector(Arrays.copyOf(data, data.length), isComplete(), null);
+        return new RLogicalVector(Arrays.copyOf(data, data.length), isComplete());
     }
 
     public RLogicalVector copyResetData(byte[] newData) {
@@ -97,7 +98,7 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo
                 break;
             }
         }
-        RLogicalVector result = new RLogicalVector(newData, isComplete, null);
+        RLogicalVector result = new RLogicalVector(newData, isComplete);
         setAttributes(result);
         return result;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
index 26252b7da5746b0efdfd06af7ed539a09ff6c070..1d680bc8bae69c9274ab42b77bf8f65557da1f14 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java
@@ -37,14 +37,15 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
 
     private final byte[] data;
 
-    RRawVector(byte[] data, int[] dims, RStringVector names) {
-        super(true, data.length, dims, names);
+    RRawVector(byte[] data) {
+        super(true);
         this.data = data;
         assert verify();
     }
 
-    private RRawVector(byte[] data, int[] dims) {
-        this(data, dims, null);
+    RRawVector(byte[] data, int[] dims, RStringVector names, RList dimNames) {
+        this(data);
+        initDimsNamesDimNames(dims, names, dimNames);
     }
 
     @Override
@@ -89,7 +90,7 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec
 
     @Override
     protected RRawVector internalCopy() {
-        return new RRawVector(Arrays.copyOf(data, data.length), null);
+        return new RRawVector(Arrays.copyOf(data, data.length));
     }
 
     @Override
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
index 38fdbb99181b237ae911db36a6074201c5ed22c3..7fb2ffdad2bb3f978fda84fe63838ba6e1095ef1 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java
@@ -38,14 +38,15 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
 
     private final String[] data;
 
-    RStringVector(String[] data, boolean complete, int[] dims, RStringVector names) {
-        super(complete, data.length, dims, names);
+    RStringVector(String[] data, boolean complete) {
+        super(complete);
         this.data = data;
         assert verify();
     }
 
-    private RStringVector(String[] data, boolean complete, int[] dims) {
-        this(data, complete, dims, null);
+    RStringVector(String[] data, boolean complete, int[] dims, RStringVector names, RList dimNames) {
+        this(data, complete);
+        initDimsNamesDimNames(dims, names, dimNames);
     }
 
     @Override
@@ -79,7 +80,7 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
 
     @Override
     protected RStringVector internalCopy() {
-        return new RStringVector(Arrays.copyOf(data, data.length), isComplete(), null);
+        return new RStringVector(Arrays.copyOf(data, data.length), isComplete());
     }
 
     @Override
@@ -102,7 +103,7 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS
                 break;
             }
         }
-        RStringVector result = new RStringVector(newData, isComplete, null);
+        RStringVector result = new RStringVector(newData, isComplete);
         setAttributes(result);
         return result;
     }
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 5af392c0858ff416f7d37a96a11f27436e593744..ad2756524f8c0ca8b4ea1a7677fea16f55ab2c33 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
@@ -62,29 +62,8 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
 
     protected boolean complete; // "complete" means: does not contain NAs
 
-    protected RVector(boolean complete, int length, int[] dimensions, RStringVector names) {
+    protected RVector(boolean complete) {
         this.complete = complete;
-        assert names != this;
-        if (names != null) {
-            // since this constructor is for internal use only, the assertion shouldn't fail
-            assert names.getLength() == length : "size mismatch: " + names.getLength() + " vs. " + length;
-            if (dimensions == null) {
-                initAttributes(RAttributesLayout.createNames(names));
-            } else {
-                RIntVector dimensionsVector = RDataFactory.createIntVector(dimensions, true);
-                if (dimensions.length != 1) {
-                    initAttributes(RAttributesLayout.createNamesAndDim(names, dimensionsVector));
-                } else {
-                    // one-dimensional arrays do not have names, only dimnames with one value
-                    RList newDimNames = RDataFactory.createList(new Object[]{names});
-                    initAttributes(RAttributesLayout.createDimAndDimNames(dimensionsVector, newDimNames));
-                }
-            }
-        } else {
-            if (dimensions != null) {
-                initAttributes(RAttributesLayout.createDim(RDataFactory.createIntVector(dimensions, true)));
-            }
-        }
     }
 
     private int[] getDimensionsFromAttrs() {
@@ -601,6 +580,59 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement
         this.setDimNames(vector.getDimNames(), invokingNode);
     }
 
+    /**
+     * Inits dims, names and dimnames attributes and it should only be invoked if no attributes were
+     * initialized yet.
+     */
+    @TruffleBoundary
+    protected final void initDimsNamesDimNames(int[] dimensions, RStringVector names, RList dimNames) {
+        assert (this.attributes == null) : "Vector attributes must be null";
+        assert names != this;
+        assert dimNames != this;
+        if (dimNames != null) {
+            DynamicObject attrs;
+            if (dimensions != null) {
+                RIntVector dimensionsVector = RDataFactory.createIntVector(dimensions, true);
+                attrs = RAttributesLayout.createDimAndDimNames(dimensionsVector, dimNames);
+                // one-dimensional arrays do not have names, only dimnames with one value so do not
+                // init names in that case
+                if (names != null && dimensions.length != 1) {
+                    assert names.getLength() == getLength() : "size mismatch: names.length=" + names.getLength() + " vs. length=" + getLength();
+                    attrs.define(RRuntime.NAMES_ATTR_KEY, names);
+                }
+            } else {
+                attrs = RAttributesLayout.createDimNames(dimNames);
+                if (names != null) {
+                    assert names.getLength() == getLength() : "size mismatch: names.length=" + names.getLength() + " vs. length=" + getLength();
+                    attrs.define(RRuntime.NAMES_ATTR_KEY, names);
+                }
+            }
+            initAttributes(attrs);
+        } else {
+            if (names != null) {
+                // since this constructor is for internal use only, the assertion shouldn't fail
+                assert names.getLength() == getLength() : "size mismatch: " + names.getLength() + " vs. " + getLength();
+                if (dimensions != null) {
+                    RIntVector dimensionsVector = RDataFactory.createIntVector(dimensions, true);
+                    if (dimensions.length != 1) {
+                        initAttributes(RAttributesLayout.createNamesAndDim(names, dimensionsVector));
+                    } else {
+                        // one-dimensional arrays do not have names, only dimnames with one value
+                        RList newDimNames = RDataFactory.createList(new Object[]{names});
+                        initAttributes(RAttributesLayout.createDimAndDimNames(dimensionsVector, newDimNames));
+                    }
+                } else {
+                    initAttributes(RAttributesLayout.createNames(names));
+                }
+            } else {
+                if (dimensions != null) {
+                    RIntVector dimensionsVector = RDataFactory.createIntVector(dimensions, true);
+                    initAttributes(RAttributesLayout.createDim(dimensionsVector));
+                }
+            }
+        }
+    }
+
     public final boolean copyNamesFrom(RAbstractVector vector) {
         CompilerAsserts.neverPartOfCompilation();
 
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
index fea2f45e62a7463bd1751d0bed3671df96e26760..5288c6fc4ac7f00ba3f6e2bf05cd1327feefb666 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test
@@ -33817,6 +33817,30 @@ Error in lockEnvironment("foo", TRUE) : not an environment
 #{ round( log(10,2), digits = 5 ) }
 [1] 3.32193
 
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogAttrs#
+#{ x <- array(1:3, 1); dimnames(x) <- list('a'); r <- log(x); names(r)[[1]] <- 'new'; list(x=x, r=r); }
+$x
+a
+1
+
+$r
+new
+  0
+
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogAttrs#
+#{ x <- array(1:3, 3, list(x=c('x1','x2','x3'))); r <- log(x); r; }
+x
+       x1        x2        x3
+0.0000000 0.6931472 1.0986123
+
+##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogAttrs#
+#{ y <- array(1:6, c(2,3), list(y=c('y1','y2'), x=c('x1','x2','x3'))); r <- log(y); r; }
+    x
+y           x1       x2       x3
+  y1 0.0000000 1.098612 1.609438
+  y2 0.6931472 1.386294 1.791759
+
 ##com.oracle.truffle.r.test.builtins.TestBuiltin_log.testLogComplex#
 #{ log(-10-1i, 10) }
 [1] 1.002161-1.321091i
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java
index 4e5da9071abda26fdb9bc07abc9dd67b653c1032..28cf30f87f6d259667aedad31624ebf6a68fbf22 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_log.java
@@ -170,4 +170,12 @@ public class TestBuiltin_log extends TestBase {
         assertEval("{ log(c(0.0, 0.0), 0+0i) }");
         assertEval("{ log(c(0+0i, 0+0i), 0+0i) }");
     }
+
+    @Test
+    public void testLogAttrs() {
+        assertEval("{ x <- array(1:3, 1); dimnames(x) <- list('a'); r <- log(x); names(r)[[1]] <- 'new'; list(x=x, r=r); }");
+        assertEval("{ x <- array(1:3, 3, list(x=c('x1','x2','x3'))); r <- log(x); r; }");
+        assertEval("{ y <- array(1:6, c(2,3), list(y=c('y1','y2'), x=c('x1','x2','x3'))); r <- log(y); r; }");
+    }
+
 }