diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java index c2a0cb887709ca2e9ac96630f520e0923c3db8c4..af6abfd1cd8adcc7790c0f1671ba73214f58f1ef 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java @@ -18,6 +18,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.r.nodes.attributes.SetAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -43,7 +44,8 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { @Specialization(guards = "method == cachedMethod") protected RDoubleVector cdist(RAbstractDoubleVector x, @SuppressWarnings("unused") int method, RList list, double p, @SuppressWarnings("unused") @Cached("method") int cachedMethod, @Cached("getMethod(method)") Method methodObj, - @Cached("create()") SetAttributeNode setAttrNode) { + @Cached("create()") SetAttributeNode setAttrNode, + @Cached("create()") SetClassAttributeNode setClassAttrNode) { int nr = RRuntime.nrows(x); int nc = RRuntime.ncols(x); int n = nr * (nr - 1) / 2; /* avoid int overflow for N ~ 50,000 */ @@ -57,7 +59,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { String name = names.getDataAt(i); Object listValue = list.getDataAt(i); if (name.equals(RRuntime.CLASS_ATTR_KEY)) { - result.setClassAttr(listValue instanceof RStringVector ? (RStringVector) listValue : RDataFactory.createStringVectorFromScalar((String) listValue)); + setClassAttrNode.execute(result, listValue instanceof RStringVector ? (RStringVector) listValue : RDataFactory.createStringVectorFromScalar((String) listValue)); } else { setAttrNode.execute(resultAttrs, name, listValue); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java index d5579cf6151b85e0587b23fa51245d3452b81101..ef88564b409673c60b1b9e05f9a8c9565d8854ed 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Attributes.java @@ -122,6 +122,6 @@ public abstract class Attributes extends RBuiltinNode { } private static boolean hasAttributes(RAttributable attributable) { - return attributable.getAttributes() != null && attributable.getAttributes().size() > 0; + return attributable.getAttributes() != null && !attributable.getAttributes().isEmpty(); } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java index c9a3e2826bcf8d325844e894e04922fb2c9f369a..9836382db9156393a1fa64d3e2f8920a2128585c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DatePOSIXFunctions.java @@ -36,7 +36,9 @@ import java.util.HashMap; import java.util.TimeZone; 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.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RInternalError; @@ -280,7 +282,8 @@ public class DatePOSIXFunctions { @Specialization @TruffleBoundary - protected RDoubleVector posix2date(RAbstractListVector x) { + protected RDoubleVector posix2date(RAbstractListVector x, + @Cached("create()") SetClassAttributeNode setClassAttrNode) { RAbstractVector secVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(0)); RAbstractVector minVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(1)); RAbstractVector hourVector = (RAbstractVector) RRuntime.asAbstractVector(x.getDataAt(2)); @@ -314,7 +317,7 @@ public class DatePOSIXFunctions { } } RDoubleVector result = RDataFactory.createDoubleVector(data, complete); - result.setClassAttr(CLASS_ATTR); + setClassAttrNode.execute(result, CLASS_ATTR); return result; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java index 91b440abc58300884c1fe7ce11b3eb9cdef5690f..b40823209066398f4129d631f1ff02d4ee801705 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DynLoadFunctions.java @@ -22,7 +22,11 @@ */ package com.oracle.truffle.r.nodes.builtin.base; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.*; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.logicalValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notEmpty; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.size; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.stringValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.RVisibility.OFF; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; @@ -32,6 +36,7 @@ import java.util.ArrayList; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -102,6 +107,9 @@ public class DynLoadFunctions { @RBuiltin(name = "getLoadedDLLs", kind = INTERNAL, parameterNames = {}, behavior = READS_STATE) public abstract static class GetLoadedDLLs extends RBuiltinNode { + + @Child private SetClassAttributeNode setClassAttrNode = SetClassAttributeNode.create(); + @Specialization @TruffleBoundary protected RList doGetLoadedDLLs() { @@ -115,7 +123,7 @@ public class DynLoadFunctions { data[i] = dllInfo.toRList(); } RList result = RDataFactory.createList(data, RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR)); - result.setClassAttr(RDataFactory.createStringVectorFromScalar(DLLINFOLIST_CLASS)); + setClassAttrNode.execute(result, RDataFactory.createStringVectorFromScalar(DLLINFOLIST_CLASS)); return result; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java index 83bade1e3165ab0807caa023896b8a47890d2a4c..c9dbe8b0ba2d04b46c492967c385033af323ada0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java @@ -56,7 +56,9 @@ import java.util.stream.Stream; 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.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastStringNode; @@ -266,6 +268,8 @@ public class FileFunctions { private static final RStringVector NAMES_VECTOR = RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR); private static final RStringVector OCTMODE = RDataFactory.createStringVectorFromScalar("octmode"); + @Child private SetClassAttributeNode setClassAttrNode; + @Override protected void createCasts(CastBuilder casts) { casts.arg("extra_cols").asLogicalVector().findFirst().map(toBoolean()); @@ -400,12 +404,19 @@ public class FileFunctions { // @formatter:on } - private static Object createColumnResult(Column column, Object data, boolean complete) { + private Object createColumnResult(Column column, Object data, boolean complete) { // @formatter:off switch(column) { case size: return RDataFactory.createDoubleVector((double[]) data, complete); case isdir: return RDataFactory.createLogicalVector((byte[]) data, complete); - case mode: RIntVector res = RDataFactory.createIntVector((int[]) data, complete); res.setClassAttr(OCTMODE); return res; + case mode: + if (setClassAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setClassAttrNode = insert(SetClassAttributeNode.create()); + } + RIntVector res = RDataFactory.createIntVector((int[]) data, complete); + setClassAttrNode.execute(res, OCTMODE); + return res; case mtime: case ctime: case atime: case uid: case gid: return RDataFactory.createIntVector((int[]) data, complete); case uname: case grname: return RDataFactory.createStringVector((String[]) data, complete); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java index 0ff9871785cb6fb0523d27ae4bae2b6f98f303e7..04403d4fbfa08dfd3911b9516908144f8df1f931 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FormatC.java @@ -15,7 +15,9 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastStringNode; @@ -51,8 +53,10 @@ public abstract class FormatC extends RBuiltinNode { @SuppressWarnings("unused") @Specialization - RAttributable formatC(RAbstractContainer x, String mode, int width, int digits, String format, String flag, int iStrlen) { + RAttributable formatC(RAbstractContainer x, String mode, int width, int digits, String format, String flag, int iStrlen, + @Cached("create()") SetClassAttributeNode setClassAttrNode) { RStringVector res = castStringVector(x); - return res.setClassAttr(null); + setClassAttrNode.reset(res); + return res; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java index 7b1275c1b1d5ffbe7a3539868b2d97a1a451e9a4..2bffe1729c707c3512447a5c71924a3aa09ada6a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/HiddenInternalFunctions.java @@ -27,6 +27,7 @@ import java.nio.ByteBuffer; 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.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.MaterializedFrame; @@ -35,6 +36,7 @@ import com.oracle.truffle.api.nodes.LoopNode; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; @@ -284,7 +286,8 @@ public class HiddenInternalFunctions { @Specialization(guards = "isDLLInfo(externalPtr)") @TruffleBoundary - protected RList getRegisteredRoutines(RExternalPtr externalPtr) { + protected RList getRegisteredRoutines(RExternalPtr externalPtr, + @Cached("create()") SetClassAttributeNode setClassAttrNode) { Object[] data = new Object[NAMES.getLength()]; DLL.DLLInfo dllInfo = (DLLInfo) externalPtr.getExternalObject(); RInternalError.guarantee(dllInfo != null); @@ -301,7 +304,7 @@ public class HiddenInternalFunctions { symbolData[i] = symbolInfo.createRSymbolObject(rnt, true); } RList symbolDataList = RDataFactory.createList(symbolData); - symbolDataList.setClassAttr(NATIVE_ROUTINE_LIST); + setClassAttrNode.execute(symbolDataList, NATIVE_ROUTINE_LIST); data[nst.ordinal()] = symbolDataList; } return RDataFactory.createList(data, NAMES); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java index be182b91b23a5b1ef9147f6ae56359df1f2d456c..ea86a45e96d6237e66ad4ff52cf3c3a1b3d8417e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ProcTime.java @@ -27,6 +27,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; @@ -44,6 +45,8 @@ public abstract class ProcTime extends RBuiltinNode { private static RStringVector RNAMES; + @Child private SetClassAttributeNode setClassAttrNode = SetClassAttributeNode.create(); + @Specialization @TruffleBoundary protected RDoubleVector procTime() { @@ -65,7 +68,8 @@ public abstract class ProcTime extends RBuiltinNode { RNAMES = RDataFactory.createStringVector(NAMES, RDataFactory.COMPLETE_VECTOR); } RDoubleVector result = RDataFactory.createDoubleVector(data, complete, RNAMES); - result.setClassAttr(PROC_TIME_CLASS); + setClassAttrNode.execute(result, PROC_TIME_CLASS); + return result; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java index 11bc95e938d5a7b6c2e3a9127e07b22fb9b2d582..a7104255300fc675b12928e8c6be4c528e3f913f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttr.java @@ -31,9 +31,12 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; @@ -66,6 +69,7 @@ public abstract class UpdateAttr extends RBuiltinNode { @Child private CastIntegerNode castInteger; @Child private CastToVectorNode castVector; @Child private CastListNode castList; + @Child private SetClassAttributeNode setClassAttrNode; @CompilationFinal private String cachedName = ""; @CompilationFinal private String cachedInternedName = ""; @@ -144,7 +148,12 @@ public abstract class UpdateAttr extends RBuiltinNode { } else if (internedName == RRuntime.DIMNAMES_ATTR_KEY) { return updateDimNames(result, value); } else if (internedName == RRuntime.CLASS_ATTR_KEY) { - return (RAbstractContainer) result.setClassAttr(null); + if (setClassAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setClassAttrNode = insert(SetClassAttributeNode.create()); + } + setClassAttrNode.reset(result); + return result; } else if (internedName == RRuntime.ROWNAMES_ATTR_KEY) { result.setRowNames(null); } else if (result.getAttributes() != null) { @@ -181,7 +190,12 @@ public abstract class UpdateAttr extends RBuiltinNode { } else if (internedName == RRuntime.DIMNAMES_ATTR_KEY) { return updateDimNames(result, value); } else if (internedName == RRuntime.CLASS_ATTR_KEY) { - return (RAbstractContainer) result.setClassAttr(convertClassAttrFromObject(value)); + if (setClassAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setClassAttrNode = insert(SetClassAttributeNode.create()); + } + setClassAttrNode.execute(result, convertClassAttrFromObject(value)); + return result; } else if (internedName == RRuntime.ROWNAMES_ATTR_KEY) { result.setRowNames(castVector(value)); } else { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java index 31ce0f85a414a66a52bc6d3757e9398960508d74..de564de8968fe28cd0597085e810fb9fc0f8d70e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateAttributes.java @@ -30,7 +30,11 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.attributes.InitAttributesNode; +import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNode; @@ -60,6 +64,9 @@ public abstract class UpdateAttributes extends RBuiltinNode { @Child private UpdateDimNames updateDimNames; @Child private CastIntegerNode castInteger; @Child private CastToVectorNode castVector; + @Child private SetClassAttributeNode setClassAttrNode; + @Child private InitAttributesNode initAttrNode; + @Child private SetAttributeNode setAttrNode; @Override protected void createCasts(CastBuilder casts) { @@ -189,11 +196,16 @@ public abstract class UpdateAttributes extends RBuiltinNode { } else if (attrName.equals(RRuntime.DIMNAMES_ATTR_KEY)) { res = updateDimNames(res, value); } else if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { + if (setClassAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setClassAttrNode = insert(SetClassAttributeNode.create()); + } if (value == RNull.instance) { - res = (RAbstractContainer) result.setClassAttr(null); + setClassAttrNode.reset(result); } else { - res = (RAbstractContainer) result.setClassAttr(UpdateAttr.convertClassAttrFromObject(value)); + setClassAttrNode.execute(res, UpdateAttr.convertClassAttrFromObject(value)); } + res = result; } else if (attrName.equals(RRuntime.ROWNAMES_ATTR_KEY)) { res.setRowNames(castVector(value)); } else { @@ -222,7 +234,12 @@ public abstract class UpdateAttributes extends RBuiltinNode { Object obj = getNonShared(o); RAttributable attrObj = (RAttributable) obj; attrObj.removeAllAttributes(); - attrObj.setClassAttr(null); + + if (setClassAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setClassAttrNode = insert(SetClassAttributeNode.create()); + } + setClassAttrNode.reset(attrObj); return obj; } @@ -251,9 +268,22 @@ public abstract class UpdateAttributes extends RBuiltinNode { if (attrValue == null) { throw RError.error(this, RError.Message.SET_INVALID_CLASS_ATTR); } - attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue)); + + if (setClassAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setClassAttrNode = insert(SetClassAttributeNode.create()); + } + setClassAttrNode.execute(attrObj, UpdateAttr.convertClassAttrFromObject(attrValue)); } else { - attrObj.setAttr(attrName.intern(), operand.getDataAt(i)); + if (setAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setAttrNode = insert(SetAttributeNode.create()); + } + if (initAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + initAttrNode = insert(InitAttributesNode.create()); + } + setAttrNode.execute(initAttrNode.execute(attrObj), attrName.intern(), operand.getDataAt(i)); } } return obj; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java index 62799507ade961086ec2c43d64c72aa344899b69..674c82de1633d6a8529a51e3fe5e6de7b882d048 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateClass.java @@ -18,6 +18,9 @@ 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.r.nodes.attributes.SetAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode; import com.oracle.truffle.r.nodes.binary.CastTypeNode; import com.oracle.truffle.r.nodes.binary.CastTypeNodeGen; @@ -48,6 +51,7 @@ public abstract class UpdateClass extends RBuiltinNode { @Child private CastTypeNode castTypeNode; @Child private TypeofNode typeof; + @Child private SetClassAttributeNode setClassAttrNode = SetClassAttributeNode.create(); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @@ -61,7 +65,8 @@ public abstract class UpdateClass extends RBuiltinNode { @TruffleBoundary protected Object setClass(RAbstractContainer arg, @SuppressWarnings("unused") RNull className) { RAbstractContainer result = reuseNonShared(arg); - return result.setClassAttr(null); + setClassAttrNode.reset(result); + return result; } @Specialization(limit = "CACHE_LIMIT", guards = "cachedClassName == className") @@ -114,73 +119,75 @@ public abstract class UpdateClass extends RBuiltinNode { } } - return result.setClassAttr(RDataFactory.createStringVector(className)); + setClassAttrNode.execute(result, RDataFactory.createStringVector(className)); + return result; } @Specialization @TruffleBoundary protected Object setClass(RAbstractContainer arg, RStringVector className) { RAbstractContainer result = reuseNonShared(arg); - return result.setClassAttr(className); + setClassAttrNode.execute(result, className); + return result; } @Specialization protected Object setClass(RFunction arg, RAbstractStringVector className) { - arg.setClassAttr(className.materialize()); + setClassAttrNode.execute(arg, className.materialize()); return arg; } @Specialization protected Object setClass(RFunction arg, @SuppressWarnings("unused") RNull className) { - arg.setClassAttr(null); + setClassAttrNode.reset(arg); return arg; } @Specialization protected Object setClass(REnvironment arg, RAbstractStringVector className) { - arg.setClassAttr(className.materialize()); + setClassAttrNode.execute(arg, className.materialize()); return arg; } @Specialization protected Object setClass(REnvironment arg, @SuppressWarnings("unused") RNull className) { - arg.setClassAttr(null); + setClassAttrNode.reset(arg); return arg; } @Specialization protected Object setClass(RSymbol arg, RAbstractStringVector className) { - arg.setClassAttr(className.materialize()); + setClassAttrNode.execute(arg, className.materialize()); return arg; } @Specialization protected Object setClass(RSymbol arg, @SuppressWarnings("unused") RNull className) { - arg.setClassAttr(null); + setClassAttrNode.reset(arg); return arg; } @Specialization protected Object setClass(RExternalPtr arg, RAbstractStringVector className) { - arg.setClassAttr(className.materialize()); + setClassAttrNode.execute(arg, className.materialize()); return arg; } @Specialization protected Object setClass(RExternalPtr arg, @SuppressWarnings("unused") RNull className) { - arg.setClassAttr(null); + setClassAttrNode.reset(arg); return arg; } @Specialization protected Object setClass(RS4Object arg, RAbstractStringVector className) { - arg.setClassAttr(className.materialize()); + setClassAttrNode.execute(arg, className.materialize()); return arg; } @Specialization protected Object setClass(RS4Object arg, @SuppressWarnings("unused") RNull className) { - arg.setClassAttr(null); + setClassAttrNode.reset(arg); return arg; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java index f05261a585f42113af69f41576f5a2897eddc6df..375dc81129642bbb03ba5b814b44f63f51236bfe 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateOldClass.java @@ -29,6 +29,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; @@ -45,6 +46,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public abstract class UpdateOldClass extends RBuiltinNode { @Child private CastStringNode castStringNode; + @Child private SetClassAttributeNode setClassAttributeNode = SetClassAttributeNode.create(); @Specialization(guards = "!isStringVector(className)") protected Object setOldClass(RAbstractContainer arg, RAbstractVector className) { @@ -73,14 +75,16 @@ public abstract class UpdateOldClass extends RBuiltinNode { @TruffleBoundary protected Object setOldClass(RAbstractContainer arg, RStringVector className) { RAbstractContainer result = (RAbstractContainer) arg.getNonShared(); - return result.setClassAttr(className); + setClassAttributeNode.execute(result, className); + return result; } @Specialization @TruffleBoundary protected Object setOldClass(RAbstractContainer arg, @SuppressWarnings("unused") RNull className) { RAbstractContainer result = (RAbstractContainer) arg.getNonShared(); - return result.setClassAttr(null); + setClassAttributeNode.reset(result); + return result; } protected boolean isStringVector(RAbstractVector className) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java index a2b8ddcf234c55e836d8af7397a79d7e2ea40423..2828a0bcc5dc8d618467bfdb08544a31a5e5a6a3 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateStorageMode.java @@ -20,6 +20,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.attributes.TypeFromModeNode; import com.oracle.truffle.r.nodes.attributes.TypeFromModeNodeGen; import com.oracle.truffle.r.nodes.binary.CastTypeNode; @@ -47,6 +48,7 @@ public abstract class UpdateStorageMode extends RBuiltinNode { @Child private TypeofNode typeof; @Child private CastTypeNode castTypeNode; @Child private IsFactorNode isFactor; + @Child private SetClassAttributeNode setClassAttrNode; private final BranchProfile errorProfile = BranchProfile.create(); @@ -80,10 +82,16 @@ public abstract class UpdateStorageMode extends RBuiltinNode { String attrName = attr.getName(); Object v = attr.getValue(); if (attrName.equals(RRuntime.CLASS_ATTR_KEY)) { + + if (setClassAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setClassAttrNode = insert(SetClassAttributeNode.create()); + } + if (v == RNull.instance) { - rresult = (RAbstractContainer) rresult.setClassAttr(null); + setClassAttrNode.reset(rresult); } else { - rresult = (RAbstractContainer) rresult.setClassAttr((RStringVector) v); + setClassAttrNode.execute(rresult, v); } } else { rresult.setAttr(Utils.intern(attrName), v); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java index 771bc4bd590e1e2d170aacb2159ceca8c77d16c5..00771501a3095b30554c164c0fa60bd45bf81f47 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/Tilde.java @@ -27,6 +27,8 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.Node.Child; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.RRuntime; @@ -49,6 +51,8 @@ public abstract class Tilde extends RBuiltinNode { private static final RStringVector FORMULA_CLASS = RDataFactory.createStringVectorFromScalar(RRuntime.FORMULA_CLASS); + @Child private SetClassAttributeNode setClassAttrNode = SetClassAttributeNode.create(); + @Override public Object[] getDefaultParameterValues() { return new Object[]{RMissing.instance, RMissing.instance}; @@ -58,7 +62,7 @@ public abstract class Tilde extends RBuiltinNode { protected RLanguage tilde(VirtualFrame frame, @SuppressWarnings("unused") Object response, @SuppressWarnings("unused") Object model) { RCallNode call = (RCallNode) ((RBaseNode) getParent()).asRSyntaxNode(); RLanguage lang = RDataFactory.createLanguage(call); - lang.setClassAttr(FORMULA_CLASS); + setClassAttrNode.execute(lang, FORMULA_CLASS); REnvironment env = REnvironment.frameToEnvironment(frame.materialize()); lang.setAttr(RRuntime.DOT_ENVIRONMENT, env); return lang; diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java index d17626bd61f79b6c3f08b544914cebc5fdca54c1..b0e55a5d0192eea5ba7efba7987f15b82d589f6f 100644 --- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java +++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/builtin/CastBuilderTest.java @@ -64,7 +64,6 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import java.util.function.Consumer; import java.util.function.Function; import org.junit.After; @@ -75,7 +74,6 @@ import org.junit.Test; import com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef; import com.oracle.truffle.r.nodes.builtin.casts.PipelineConfig; import com.oracle.truffle.r.nodes.builtin.casts.fluent.InitialPhaseBuilder; -import com.oracle.truffle.r.nodes.builtin.casts.fluent.PipelineConfigBuilder; import com.oracle.truffle.r.nodes.builtin.casts.fluent.PreinitialPhaseBuilder; import com.oracle.truffle.r.nodes.casts.CastNodeSampler; import com.oracle.truffle.r.nodes.casts.FilterSamplerFactory; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveFixedAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveFixedAttributeNode.java index 5d41dae1dbc3861f24152719abd03b86707050e0..bb698a4a4540121e0655b46d7bf2f290ccdf2767 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveFixedAttributeNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/RemoveFixedAttributeNode.java @@ -59,19 +59,7 @@ public abstract class RemoveFixedAttributeNode extends FixedAttributeAccessNode public abstract void execute(DynamicObject attrs); - @Specialization(limit = "3", // - guards = {"shapeCheck(shape, attrs)"}, // - assumptions = {"shape.getValidAssumption()"}) - protected void removeAttrCached(DynamicObject attrs, - @Cached("lookupShape(attrs)") Shape shape, - @Cached("lookupProperty(shape, name)") Property property) { - if (property != null) { - Shape newShape = attrs.getShape().removeProperty(property); - attrs.setShapeAndResize(shape, newShape); - } - } - - @Specialization(contains = "removeAttrCached") + @Specialization @TruffleBoundary protected void removeAttrFallback(DynamicObject attrs) { attrs.delete(this.name); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetClassAttributeNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetClassAttributeNode.java new file mode 100644 index 0000000000000000000000000000000000000000..ef5dbf6859ecef9b78eef9d39e3ff1e00d758101 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/SetClassAttributeNode.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +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.object.DynamicObject; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RAttributable; +import com.oracle.truffle.r.runtime.data.RInteger; +import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; + +public abstract class SetClassAttributeNode extends RBaseNode { + + public static SetClassAttributeNode create() { + return SetClassAttributeNodeGen.create(); + } + + public abstract void execute(RAttributable x, Object classAttr); + + public void reset(RAttributable x) { + execute(x, RNull.instance); + } + + @Specialization + protected <T> void handleVectorNullClass(RVector<T> vector, @SuppressWarnings("unused") RNull classAttr, + @Cached("createClass()") RemoveFixedAttributeNode removeClassAttrNode, + @Cached("createClass()") SetFixedAttributeNode setClassAttrNode, + @Cached("create()") BranchProfile nullAttrProfile, + @Cached("createBinaryProfile()") ConditionProfile nullClassProfile, + @Cached("createBinaryProfile()") ConditionProfile notNullClassProfile) { + handleVector(vector, null, removeClassAttrNode, setClassAttrNode, nullAttrProfile, nullClassProfile, notNullClassProfile); + } + + @Specialization + protected <T> void handleVector(RVector<T> vector, RStringVector classAttr, + @Cached("createClass()") RemoveFixedAttributeNode removeClassAttrNode, + @Cached("createClass()") SetFixedAttributeNode setClassAttrNode, + @Cached("create()") BranchProfile nullAttrProfile, + @Cached("createBinaryProfile()") ConditionProfile nullClassProfile, + @Cached("createBinaryProfile()") ConditionProfile notNullClassProfile) { + + DynamicObject attrs = vector.getAttributes(); + if (attrs == null && classAttr != null && classAttr.getLength() != 0) { + nullAttrProfile.enter(); + attrs = vector.initAttributes(); + } + if (nullClassProfile.profile(attrs != null && (classAttr == null || classAttr.getLength() == 0))) { + removeAttributeMapping(vector, attrs, removeClassAttrNode); + } else if (notNullClassProfile.profile(classAttr != null && classAttr.getLength() != 0)) { + for (int i = 0; i < classAttr.getLength(); i++) { + String attr = classAttr.getDataAt(i); + if (RRuntime.CLASS_FACTOR.equals(attr)) { + // TODO: Isn't this redundant when the same operation is done after the loop? + setClassAttrNode.execute(attrs, classAttr); + if (vector.getElementClass() != RInteger.class) { + // N.B. there used to be conversion to integer under certain circumstances. + // However, it seems that it was dead/obsolete code so it was removed. + // Notes: this can only happen if the class is set by hand to some + // non-integral vector, i.e. attr(doubles, 'class') <- 'factor'. GnuR also + // does not update the 'class' attr with other, possibly + // valid classes when it reaches this error. + throw RError.error(RError.SHOW_CALLER2, RError.Message.ADDING_INVALID_CLASS, "factor"); + } + } + } + setClassAttrNode.execute(attrs, classAttr); + } + } + + @Specialization + protected void handleAttributable(RAttributable x, @SuppressWarnings("unused") RNull classAttr) { + x.setClassAttr(null); + } + + @Specialization + protected void handleAttributable(RAttributable x, RStringVector classAttr) { + x.setClassAttr(classAttr); + } + + private static void removeAttributeMapping(RAttributable x, DynamicObject attrs, RemoveFixedAttributeNode removeClassAttrNode) { + if (attrs != null) { + removeClassAttrNode.execute(attrs); + if (attrs.isEmpty()) { + x.initAttributes(null); + } + } + } + +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java index 3b7dc03d2d930df8d37386cc0fd332e510823f56..2c495a67ce421a9c7dccf4e07beaf546033c93fa 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/GetS4DataSlot.java @@ -19,6 +19,8 @@ import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode; import com.oracle.truffle.r.nodes.attributes.RemoveFixedAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.unary.CastToVectorNode; import com.oracle.truffle.r.nodes.unary.TypeofNode; import com.oracle.truffle.r.nodes.unary.TypeofNodeGen; @@ -42,6 +44,7 @@ public abstract class GetS4DataSlot extends Node { @Child private GetFixedAttributeNode dotDataAttrAccess; @Child private GetFixedAttributeNode dotXDataAttrAccess; @Child private TypeofNode typeOf = TypeofNodeGen.create(); + @Child private SetClassAttributeNode setClassAttrNode; private final BranchProfile shareable = BranchProfile.create(); @@ -72,6 +75,12 @@ public abstract class GetS4DataSlot extends Node { shareable.enter(); obj = (RAttributable) ((RShareable) obj).copy(); } + + if (setClassAttrNode == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + setClassAttrNode = insert(SetClassAttributeNode.create()); + } + if (s3Class != null) { if (s3ClassAttrRemove == null) { assert castToVector == null; @@ -81,9 +90,9 @@ public abstract class GetS4DataSlot extends Node { } s3ClassAttrRemove.execute(obj.initAttributes()); - obj = obj.setClassAttr((RStringVector) castToVector.execute(s3Class)); + setClassAttrNode.execute(obj, castToVector.execute(s3Class)); } else { - obj = obj.setClassAttr(null); + setClassAttrNode.reset(obj); } obj.unsetS4(); if (type == RType.S4Object) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java index b02d46ea7312a68103d2a0488edad5a155c4bc29..0929f696f491a144ca332bab105074b6109ec94d 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/NewObject.java @@ -12,10 +12,12 @@ */ package com.oracle.truffle.r.nodes.objects; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.access.AccessSlotNode; import com.oracle.truffle.r.nodes.access.AccessSlotNodeGen; import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastNode; @@ -36,6 +38,7 @@ public abstract class NewObject extends RExternalBuiltinNode.Arg1 { @Child private AccessSlotNode accessSlotPrototypeName = AccessSlotNodeGen.create(true, null, null); @Child private DuplicateNode duplicate = DuplicateNodeGen.create(true); @Child private GetFixedAttributeNode pckgAttrAccess = GetFixedAttributeNode.create(RRuntime.PCKG_ATTR_KEY); + @Child private SetClassAttributeNode setClassAttrNode; @Child private CastNode castStringScalar; @Child private CastNode castLogicalScalar; @@ -62,7 +65,13 @@ public abstract class NewObject extends RExternalBuiltinNode.Arg1 { RAttributable valueAttr = (RAttributable) value; if (valueAttr instanceof RS4Object || (e instanceof RAttributable && ((RAttributable) e).getAttributes() != null && pckgAttrAccess.execute(((RAttributable) e).getAttributes()) != null)) { - valueAttr = valueAttr.setClassAttr((RStringVector) e); + + if (setClassAttrNode == null) { + setClassAttrNode = insert(SetClassAttributeNode.create()); + CompilerDirectives.transferToInterpreterAndInvalidate(); + } + + setClassAttrNode.execute(valueAttr, e); valueAttr.setS4(); } return value; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java index 9d53e8623b97de1e410dd4ae8b0619e7fae4f224..0b01117753dd91c60670b8d9d1fb3c9c72bfc694 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastListNode.java @@ -22,11 +22,14 @@ */ package com.oracle.truffle.r.nodes.unary; +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.object.DynamicObject; import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode; +import com.oracle.truffle.r.nodes.attributes.SetClassAttributeNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.context.RContext; @@ -45,6 +48,8 @@ import com.oracle.truffle.r.runtime.env.REnvironment; public abstract class CastListNode extends CastBaseNode { + @Child private SetClassAttributeNode setClassAttrNode; + public abstract RList executeList(Object o); protected CastListNode(boolean preserveNames, boolean preserveDimensions, boolean preserveAttributes) { @@ -93,7 +98,13 @@ public abstract class CastListNode extends CastBaseNode { // result may already have names, so can't call RVector.copyAttributesFrom for (RAttributesLayout.RAttribute attr : attrAttrAccess.execute(operandAttrs)) { if (attr.getName().equals(RRuntime.CLASS_ATTR_KEY)) { - result.setClassAttr((RStringVector) attr.getValue()); + + if (setClassAttrNode == null) { + setClassAttrNode = insert(SetClassAttributeNode.create()); + CompilerDirectives.transferToInterpreterAndInvalidate(); + } + + setClassAttrNode.execute(result, attr.getValue()); } else { result.setAttr(attr.getName(), attr.getValue()); } 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 4d9c43afdf1371f48b3e288e73d3c4bd153d17de..d0983a3caf8b7884217835b32be0f036feb33274 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 @@ -533,6 +533,10 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement return setClassAttrInternal(vector, classAttr); } + public abstract class CNode extends RBaseNode { + + } + private static RAbstractContainer setClassAttrInternal(RVector<?> vector, RStringVector classAttr) { if (vector.attributes == null && classAttr != null && classAttr.getLength() != 0) { vector.initAttributes();