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 33132b9ae090b56cb9a8cb40d4d21af27421c254..7733fc871c01a48f94c82a6892a6f8a28ce42f28 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 @@ -475,10 +475,9 @@ public abstract class Combine extends RBuiltinNode { RVector<?> materialized = vector.materialize(); RVector<?> result = materialized.copyDropAttributes(); - RStringVector vecNames = materialized.getInternalNames(); + RStringVector vecNames = materialized.getNamesFromAttrs(); if (hasNamesProfile.profile(vecNames != null)) { result.initAttributes(RAttributesLayout.createNames(vecNames)); - result.setInternalNames(vecNames); } else { RList dimNames = materialized.getDimNames(); if (hasDimNamesProfile.profile(dimNames != null)) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java index 743d510865d5285d571a2fc60fcc33c6765e69e3..7c727694708c8bb6f3ab5268ee8dd8b2e590c3f9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Repeat.java @@ -168,7 +168,6 @@ public abstract class Repeat extends RBuiltinNode { r = handleTimes(input, times, false); } putNames.execute(initAttributes.execute(r), names); - r.setInternalNames(names); return r; } @@ -186,7 +185,6 @@ public abstract class Repeat extends RBuiltinNode { r = handleTimes(x, times, true); } putNames.execute(initAttributes.execute(r), names); - r.setInternalNames(names); return r; } 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 c3b2751c16f81a39f79d6ec6590064f2d2a9bdb8..d30e638139ad629645041ed73dab870e8b043753 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 @@ -31,6 +31,7 @@ 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.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.attributes.RemoveFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.SetFixedAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; @@ -64,12 +65,13 @@ public abstract class UpdateDim extends RBuiltinNode { @Specialization protected RAbstractVector updateDim(RAbstractVector vector, RAbstractIntVector dimensions, @Cached("createBinaryProfile()") ConditionProfile initAttrProfile, - @Cached("createDim()") SetFixedAttributeNode putDimensions) { + @Cached("createDim()") SetFixedAttributeNode putDimensions, + @Cached("createNames()") RemoveFixedAttributeNode removeNames) { RIntVector dimensionsMaterialized = dimensions.materialize(); int[] dimsData = dimensionsMaterialized.getDataCopy(); RVector.verifyDimensions(vector.getLength(), dimsData, this); RVector<?> result = ((RAbstractVector) reuse.execute(vector)).materialize(); - result.setInternalNames(null); + removeNames.execute(result); DynamicObject attrs = result.getAttributes(); if (initAttrProfile.profile(attrs == 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 aad37e97d53a41b8ff4b242008b6410bed89fbbd..be3be6d2ff762fb0c2dee5c05add263c6dbc1754 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 @@ -467,7 +467,6 @@ final class CachedExtractVectorNode extends CachedVectorNode { if (container.getAttributes() == null) { // usual case container.initAttributes(RAttributesLayout.createNames(newNames1)); - container.setInternalNames(newNames1); } else { // from an RLanguage extraction that set a name RStringVector oldNames = (RStringVector) namesAttrGetter.execute(container.getAttributes()); 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 04ba55c164fca27bfa664bf511459534beb1965c..67d5b8f3236fd552195e440f32e05434bfd4f64b 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 @@ -163,7 +163,6 @@ public abstract class CopyAttributesNode extends RBaseNode { if (hasNamesLeft.profile(vecNames != null)) { if (result != left) { putNames.execute(initAttributes.execute(result), vecNames); - result.setInternalNames(vecNames); } return result; } @@ -171,7 +170,6 @@ public abstract class CopyAttributesNode extends RBaseNode { vecNames = right.getNames(attrRightProfiles); if (hasNamesRight.profile(vecNames != null)) { putNames.execute(initAttributes.execute(result), vecNames); - result.setInternalNames(vecNames); } } return result; @@ -238,7 +236,6 @@ public abstract class CopyAttributesNode extends RBaseNode { RStringVector vecNames = right.getNames(attrRightProfiles); if (hasNames.profile(vecNames != null)) { putNames.execute(initAttributes.execute(result), vecNames); - result.setInternalNames(vecNames); } } return result; @@ -291,7 +288,6 @@ public abstract class CopyAttributesNode extends RBaseNode { RStringVector vecNames = left.getNames(attrLeftProfiles); if (hasNames.profile(vecNames != null)) { putNames.execute(initAttributes.execute(result), vecNames); - result.setInternalNames(vecNames); } } 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 9dc4681c3120d047e58004db1bc509fceb022c31..100380c9eead08c57ec12f878ac0b58671148245 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 @@ -282,6 +282,8 @@ public final class SpecialAttributesFunctions { public abstract static class SetNamesAttributeNode extends SetSpecialAttributeNode { + private final ConditionProfile nullDimNamesProfile = ConditionProfile.createBinaryProfile(); + protected SetNamesAttributeNode() { super(RRuntime.NAMES_ATTR_KEY); } @@ -290,11 +292,52 @@ public final class SpecialAttributesFunctions { return SpecialAttributesFunctionsFactory.SetNamesAttributeNodeGen.create(); } + public void setNames(RAbstractContainer x, RStringVector newNames) { + if (nullDimNamesProfile.profile(newNames == null)) { + execute(x, RNull.instance); + } else { + execute(x, newNames); + } + } + + @Specialization(insertBefore = "setAttrInAttributable") + protected void resetDimNames(RAbstractContainer x, @SuppressWarnings("unused") RNull rnull, + @Cached("create()") RemoveNamesAttributeNode removeNamesAttrNode) { + removeNamesAttrNode.execute(x); + } + + @Specialization(insertBefore = "setAttrInAttributable") + protected void setNamesInVector(RVector<?> x, RStringVector newNames, + @Cached("create()") BranchProfile namesTooLongProfile, + @Cached("createBinaryProfile()") ConditionProfile useDimNamesProfile, + @Cached("create()") GetDimAttributeNode getDimNode, + @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, + @Cached("create()") BranchProfile attrNullProfile, + @Cached("createBinaryProfile()") ConditionProfile attrStorageProfile, + @Cached("createClassProfile()") ValueProfile xTypeProfile) { + RVector<?> 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()); + } + int[] dimensions = getDimNode.getDimensions(x); + if (useDimNamesProfile.profile(dimensions != null && dimensions.length == 1)) { + // for one dimensional array, "names" is really "dimnames[[1]]" (see R + // documentation for "names" function) + RList newDimNames = RDataFactory.createList(new Object[]{newNames}); + newDimNames.elementNamePrefix = RRuntime.DIMNAMES_LIST_ELEMENT_NAME_PREFIX; + setDimNamesNode.setDimNames(xProfiled, newDimNames); + } else { + super.setAttrInAttributable(xProfiled, newNames, attrNullProfile, attrStorageProfile, xTypeProfile); + assert newNames != xProfiled; + } + } + @Specialization(insertBefore = "setAttrInAttributable") - protected void setNamesInContainer(RAbstractContainer x, RStringVector names, + protected void setNamesInContainer(RAbstractContainer x, RStringVector newNames, @Cached("createClassProfile()") ValueProfile contClassProfile) { RAbstractContainer xProfiled = contClassProfile.profile(x); - xProfiled.setNames(names); + xProfiled.setNames(newNames); } } 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 5421bc848c14eed477c711281ee65781d2e5b630..97f977cbd6e31821d9b711483db5a459b603d3d1 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 @@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.attributes; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimAttributeNode; @@ -94,8 +93,7 @@ public abstract class UnaryCopyAttributesNode extends RBaseNode { @Cached("createBinaryProfile()") ConditionProfile noDimensions, // @Cached("createBinaryProfile()") ConditionProfile hasNamesSource, // @Cached("createBinaryProfile()") ConditionProfile hasDimNames, - @Cached("create()") GetDimAttributeNode getDimsNode, - @Cached("create()") GetDimNamesAttributeNode getDimNamesNode) { + @Cached("create()") GetDimAttributeNode getDimsNode) { RVector<?> result = target.materialize(); if (copyAllAttributes) { @@ -113,7 +111,6 @@ public abstract class UnaryCopyAttributesNode extends RBaseNode { RStringVector vecNames = source.getNames(attrSourceProfiles); if (hasNamesSource.profile(vecNames != null)) { putNames.execute(initAttributes.execute(result), vecNames); - result.setInternalNames(vecNames); 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 98c7a907f719623928cc9cb233977b7fd2dce6f0..394e4bc550b6df237bd9ae67077f88267b49e160 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 @@ -26,7 +26,6 @@ import com.oracle.truffle.api.CompilerDirectives; 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.nodes.Node.Child; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.LoopConditionProfile; 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 4ed316e9098910dadca1a832ced61ce207fdfee0..537d54d73051c4026054cb467d2661f4b271bf06 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 @@ -146,6 +146,7 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi @TruffleBoundary public final Object getNameAt(int index) { + RStringVector names = getNamesFromAttrs(); if (names != null && names != null) { String name = names.getDataAt(index); if (name == RRuntime.STRING_NA) { 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 41b4410eeefc2a5edc431dda001ad52366d97db9..feea7fec65ef5e2625574e2ae14eb323226565a2 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 @@ -59,14 +59,12 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement private static final RStringVector implicitClassHeaderMatrix = RDataFactory.createStringVector(new String[]{RType.Matrix.getName()}, true); protected boolean complete; // "complete" means: does not contain NAs - protected RStringVector names; // 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; assert names != this; - this.names = names; this.rowNames = RNull.instance; if (names != null) { // since this constructor is for internal use only, the assertion shouldn't fail @@ -107,6 +105,14 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement } } + public final RStringVector getNamesFromAttrs() { + if (attributes == null) { + return null; + } else { + return (RStringVector) attributes.get(RRuntime.NAMES_ATTR_KEY); + } + } + /** * Intended for external calls where a mutable copy is needed. */ @@ -142,15 +148,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement return getDimensionsFromAttrs(); } - public final RStringVector getInternalNames() { - return names; - } - - public final void setInternalNames(RStringVector newNames) { - assert newNames != this; - names = newNames; - } - public final Object getInternalRowNames() { return rowNames; } @@ -179,6 +176,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement if (attrProfiles.attrNullProfile(attributes == null)) { return null; } else { + RStringVector names = getNamesFromAttrs(); if (attrProfiles.attrNullNamesProfile(names == null)) { RList dimNames = getDimNames(); if (dimNames != null && dimNames.getLength() == 1) { @@ -197,6 +195,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement * performance-critical) */ public final RStringVector getNames() { + RStringVector names = getNamesFromAttrs(); if (names == null) { RList dimNames = getDimNames(); if (dimNames != null && dimNames.getLength() == 1) { @@ -214,6 +213,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement if (getNames(attrProfiles) == null) { return -1; } + RStringVector names = getNamesFromAttrs(); for (int i = 0; i < names.getLength(); i++) { if (names.getDataAt(i).equals(name)) { return i; @@ -234,6 +234,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement } boolean oneMatch = false; int match = -1; + RStringVector names = getNamesFromAttrs(); for (int i = 0; i < names.getLength(); i++) { if (names.getDataAt(i).startsWith(name)) { if (oneMatch) { @@ -341,7 +342,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement putAttribute(RRuntime.NAMES_ATTR_KEY, newNames); } assert newNames != this; - this.names = newNames; } @Override @@ -356,7 +356,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement // whether it's one dimensional array or not, assigning null always removes the "names" // attribute removeAttributeMapping(RRuntime.NAMES_ATTR_KEY); - this.names = null; } else if (newNames != null) { if (newNames.getLength() > this.getLength()) { throw RError.error(invokingNode, RError.Message.ATTRIBUTE_VECTOR_SAME_LENGTH, RRuntime.NAMES_ATTR_KEY, newNames.getLength(), this.getLength()); @@ -371,7 +370,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement } else { putAttribute(RRuntime.NAMES_ATTR_KEY, newNames); assert newNames != this; - this.names = newNames; } } } @@ -483,6 +481,10 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement return attributes == null ? false : attributes.containsKey(RRuntime.DIMNAMES_ATTR_KEY); } + public final boolean hasNames() { + return attributes == null ? false : attributes.containsKey(RRuntime.NAMES_ATTR_KEY); + } + @Override public final boolean isMatrix() { int[] dimensions = getDimensionsFromAttrs(); @@ -570,7 +572,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement } public final void setAttributes(RVector<?> result) { - result.names = this.names; result.rowNames = this.rowNames; if (this.attributes != null) { result.initAttributes(RAttributesLayout.copy(this.attributes)); @@ -667,16 +668,11 @@ 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 (!hasNames()); assert (!hasDimNames()); assert (this.rowNames == RNull.instance); assert (!hasDimensions()); assert (this.attributes == null || this.attributes.size() == 0) : this.attributes.size(); - if (vector.getDimensions() == null || vector.getDimensions().length != 1) { - // only assign name attribute if it's not represented as dimnames (as is the case for - // one-dimensional array) - this.names = vector.getNames(attrProfiles); - } this.rowNames = vector.getRowNames(attrProfiles); DynamicObject vecAttributes = vector.getAttributes(); if (vecAttributes != null) { @@ -692,9 +688,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement * vector conversion when setting class attribute */ protected final RAttributable copyAttributesFrom(RVector<?> vector) { - if (vector.getDimensions() == null || vector.getDimensions().length != 1) { - this.names = vector.getNames(); - } this.rowNames = vector.getRowNames(); DynamicObject vecAttributes = vector.getAttributes(); if (vecAttributes != null) { @@ -707,7 +700,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 (!hasDimNames()); assert (!hasDimNames()); assert (!hasDimensions()); assert (this.attributes == null); @@ -769,7 +762,7 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement private RVector<ArrayT> resize(int size, boolean resetAll) { this.complete &= getLength() >= size; RVector<ArrayT> res = this; - RStringVector oldNames = res.names; + RStringVector oldNames = res.getNamesFromAttrs(); res = copyResized(size, true); if (this.isShared()) { assert res.isTemporary(); @@ -785,7 +778,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement if (oldNames != null) { oldNames = oldNames.resizeWithEmpty(size); res.putAttribute(RRuntime.NAMES_ATTR_KEY, oldNames); - res.names = oldNames; } return res; } @@ -795,7 +787,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement // reset all attributes other than dimensions; // whether we nullify dimensions or re-set them to a different value, names and dimNames // must be reset - this.names = null; if (newDimensions != null) { putAttribute(RRuntime.DIM_ATTR_KEY, RDataFactory.createIntVector(newDimensions, true)); } else { @@ -810,7 +801,6 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement @Override public final void resetAllAttributes(boolean nullify) { - this.names = null; this.rowNames = RNull.instance; if (nullify) { this.attributes = null; diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimassign.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimassign.java index da6bda1e0cb7cc2ebe39516bfc246518da3e8a63..f76298ead2b14bf7a33e0e1fee0011b14932c8af 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimassign.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_dimassign.java @@ -71,4 +71,10 @@ public class TestBuiltin_dimassign extends TestBase { public void testdimassign11() { assertEval("argv <- list(structure(NA, .Dim = c(1L, 1L)), value = c(1L, 1L));`dim<-`(argv[[1]],argv[[2]]);"); } + + @Test + public void testdimassign12() { + assertEval("b <- c(a=1+2i,b=3+4i);dim(b) <- c(2,1);attributes(x)"); + } + }