diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java index 7d067318ffd014d0e830cb5de23443bbab1aa67a..3ffe1c5c9b02a97634fb04df2545a7da39146cbe 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsVector.java @@ -24,12 +24,21 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL; +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.VirtualFrame; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.builtin.base.AsVectorNodeGen.AsVectorInternalNodeGen; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; +import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode; +import com.oracle.truffle.r.nodes.function.UseMethodInternalNode; import com.oracle.truffle.r.nodes.unary.CastComplexNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; import com.oracle.truffle.r.nodes.unary.CastExpressionNode; @@ -39,7 +48,9 @@ import com.oracle.truffle.r.nodes.unary.CastListNodeGen; import com.oracle.truffle.r.nodes.unary.CastLogicalNode; import com.oracle.truffle.r.nodes.unary.CastRawNode; import com.oracle.truffle.r.nodes.unary.CastSymbolNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; @@ -52,215 +63,227 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RInteger; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogical; -import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -@RBuiltin(name = "as.vector", kind = INTERNAL, parameterNames = {"x", "mode"}) +@RBuiltin(name = "as.vector", kind = INTERNAL, parameterNames = {"x", "mode"}, dispatch = RDispatch.INTERNAL_GENERIC) public abstract class AsVector extends RBuiltinNode { - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + @Child private AsVectorInternal internal = AsVectorInternalNodeGen.create(); + @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); + @Child private UseMethodInternalNode useMethod; + + private final ConditionProfile hasClassProfile = ConditionProfile.createBinaryProfile(); @Override protected void createCasts(CastBuilder casts) { casts.firstStringWithError(1, RError.Message.INVALID_ARGUMENT, "mode"); } - @Specialization - protected Object asVector(RNull x, @SuppressWarnings("unused") RMissing mode) { - controlVisibility(); - return x; + protected static AsVectorInternal createInternal() { + return AsVectorInternalNodeGen.create(); } - @Specialization(guards = "castToString(mode)") - protected Object asVectorString(Object x, @SuppressWarnings("unused") String mode, // - @Cached("create()") AsCharacter asCharacter) { - controlVisibility(); - return asCharacter.execute(x); - } + private static final ArgumentsSignature SIGNATURE = ArgumentsSignature.get("x", "mode"); - @Specialization(guards = "castToInt(x, mode)") - protected Object asVectorInt(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastIntegerNode cast) { + @Specialization + protected Object asVector(VirtualFrame frame, Object x, String mode) { controlVisibility(); - return cast.execute(x); + RStringVector clazz = classHierarchy.execute(x); + if (hasClassProfile.profile(clazz != null)) { + if (useMethod == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + useMethod = insert(new UseMethodInternalNode("as.vector", SIGNATURE, false)); + } + try { + return useMethod.execute(frame, clazz, new Object[]{x, mode}); + } catch (S3FunctionLookupNode.NoGenericMethodException e) { + // fallthrough + } + } + return internal.execute(x, mode); } - @Specialization(guards = "castToDouble(x, mode)") - protected Object asVectorDouble(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastDoubleNode cast) { - controlVisibility(); - return cast.execute(x); - } + public abstract static class AsVectorInternal extends Node { - @Specialization(guards = "castToComplex(x, mode)") - protected Object asVectorComplex(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastComplexNode cast) { - controlVisibility(); - return cast.execute(x); - } + public abstract Object execute(Object x, String mode); - @Specialization(guards = "castToLogical(x, mode)") - protected Object asVectorLogical(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastLogicalNode cast) { - controlVisibility(); - return cast.execute(x); - } + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - @Specialization(guards = "castToRaw(x, mode)") - protected Object asVectorRaw(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastRawNode cast) { - controlVisibility(); - return cast.execute(x); - } + @Specialization(guards = "castToString(mode)") + protected Object asVectorString(Object x, @SuppressWarnings("unused") String mode, // + @Cached("create()") AsCharacter asCharacter) { + return asCharacter.execute(x); + } - protected static CastListNode createListCast() { - return CastListNodeGen.create(true, false, false); - } + @Specialization(guards = "castToInt(x, mode)") + protected Object asVectorInt(RAbstractContainer x, @SuppressWarnings("unused") String mode, // + @Cached("createNonPreserving()") CastIntegerNode cast) { + return cast.execute(x); + } - @Specialization(guards = "castToList(mode)") - protected Object asVectorList(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createListCast()") CastListNode cast) { - controlVisibility(); - return cast.execute(x); - } + @Specialization(guards = "castToDouble(x, mode)") + protected Object asVectorDouble(RAbstractContainer x, @SuppressWarnings("unused") String mode, // + @Cached("createNonPreserving()") CastDoubleNode cast) { + return cast.execute(x); + } - @Specialization(guards = "castToSymbol(x, mode)") - protected Object asVectorSymbol(RAbstractContainer x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastSymbolNode cast) { - controlVisibility(); - return cast.execute(x); - } + @Specialization(guards = "castToComplex(x, mode)") + protected Object asVectorComplex(RAbstractContainer x, @SuppressWarnings("unused") String mode, // + @Cached("createNonPreserving()") CastComplexNode cast) { + return cast.execute(x); + } - @Specialization(guards = "castToExpression(mode)") - protected Object asVectorExpression(Object x, @SuppressWarnings("unused") String mode, // - @Cached("createNonPreserving()") CastExpressionNode cast) { - controlVisibility(); - return cast.execute(x); - } + @Specialization(guards = "castToLogical(x, mode)") + protected Object asVectorLogical(RAbstractContainer x, @SuppressWarnings("unused") String mode, // + @Cached("createNonPreserving()") CastLogicalNode cast) { + return cast.execute(x); + } - @Specialization(guards = "castToList(mode)") - protected RAbstractVector asVectorList(@SuppressWarnings("unused") RNull x, @SuppressWarnings("unused") String mode) { - controlVisibility(); - return RDataFactory.createList(); - } + @Specialization(guards = "castToRaw(x, mode)") + protected Object asVectorRaw(RAbstractContainer x, @SuppressWarnings("unused") String mode, // + @Cached("createNonPreserving()") CastRawNode cast) { + return cast.execute(x); + } - @Specialization(guards = "isSymbol(x, mode)") - protected RSymbol asVectorSymbol(RSymbol x, @SuppressWarnings("unused") String mode) { - controlVisibility(); - String sName = x.getName(); - return RDataFactory.createSymbol(sName); - } + protected static CastListNode createListCast() { + return CastListNodeGen.create(true, false, false); + } - protected boolean isSymbol(@SuppressWarnings("unused") RSymbol x, String mode) { - return RType.Symbol.getName().equals(mode); - } + @Specialization(guards = "castToList(mode)") + protected Object asVectorList(RAbstractContainer x, @SuppressWarnings("unused") String mode, // + @Cached("createListCast()") CastListNode cast) { + return cast.execute(x); + } - @Specialization(guards = "modeIsAny(mode)") - protected RAbstractVector asVector(RList x, @SuppressWarnings("unused") String mode) { - controlVisibility(); - RList result = x.copyWithNewDimensions(null); - result.copyNamesFrom(attrProfiles, x); - return result; - } + @Specialization(guards = "castToSymbol(x, mode)") + protected Object asVectorSymbol(RAbstractContainer x, @SuppressWarnings("unused") String mode, // + @Cached("createNonPreserving()") CastSymbolNode cast) { + return cast.execute(x); + } - @Specialization(guards = "modeIsAny(mode)") - protected RAbstractVector asVector(RFactor x, @SuppressWarnings("unused") String mode) { - RVector levels = x.getLevels(attrProfiles); - RVector result = levels.createEmptySameType(x.getLength(), RDataFactory.COMPLETE_VECTOR); - RIntVector factorData = x.getVector(); - for (int i = 0; i < result.getLength(); i++) { - result.transferElementSameType(i, levels, factorData.getDataAt(i) - 1); + @Specialization(guards = "castToExpression(mode)") + protected Object asVectorExpression(Object x, @SuppressWarnings("unused") String mode, // + @Cached("createNonPreserving()") CastExpressionNode cast) { + return cast.execute(x); } - return result; - } - @Specialization(guards = "modeIsAny(mode)") - protected RNull asVector(RNull x, @SuppressWarnings("unused") String mode) { - controlVisibility(); - return x; - } + @Specialization(guards = "castToList(mode)") + protected RAbstractVector asVectorList(@SuppressWarnings("unused") RNull x, @SuppressWarnings("unused") String mode) { + return RDataFactory.createList(); + } - @Specialization(guards = "modeIsPairList(mode)") - protected Object asVectorPairList(RList x, @SuppressWarnings("unused") String mode) { - controlVisibility(); - // TODO implement non-empty element list conversion; this is a placeholder for type test - if (x.getLength() == 0) { - return RNull.instance; - } else { - throw RError.nyi(this, "non-empty lists"); + @Specialization(guards = "isSymbol(x, mode)") + protected RSymbol asVectorSymbol(RSymbol x, @SuppressWarnings("unused") String mode) { + String sName = x.getName(); + return RDataFactory.createSymbol(sName); } - } - @Specialization(guards = "modeIsAny(mode)") - protected RAbstractVector asVectorAny(RAbstractVector x, @SuppressWarnings("unused") String mode) { - controlVisibility(); - return x.copyWithNewDimensions(null); - } + protected boolean isSymbol(@SuppressWarnings("unused") RSymbol x, String mode) { + return RType.Symbol.getName().equals(mode); + } - @Specialization(guards = "modeMatches(x, mode)") - protected RAbstractVector asVector(RAbstractVector x, @SuppressWarnings("unused") String mode) { - controlVisibility(); - return x.copyWithNewDimensions(null); - } + @Specialization(guards = "modeIsAny(mode)") + protected RAbstractVector asVector(RList x, @SuppressWarnings("unused") String mode) { + RList result = x.copyWithNewDimensions(null); + result.copyNamesFrom(attrProfiles, x); + return result; + } - protected boolean castToInt(RAbstractContainer x, String mode) { - return x.getElementClass() != RInteger.class && RType.Integer.getName().equals(mode); - } + @Specialization(guards = "modeIsAny(mode)") + protected RAbstractVector asVector(RFactor x, @SuppressWarnings("unused") String mode) { + RVector levels = x.getLevels(attrProfiles); + RVector result = levels.createEmptySameType(x.getLength(), RDataFactory.COMPLETE_VECTOR); + RIntVector factorData = x.getVector(); + for (int i = 0; i < result.getLength(); i++) { + result.transferElementSameType(i, levels, factorData.getDataAt(i) - 1); + } + return result; + } - protected boolean castToDouble(RAbstractContainer x, String mode) { - return x.getElementClass() != RDouble.class && (RType.Double.getClazz().equals(mode) || RType.Double.getName().equals(mode)); - } + @Specialization(guards = "modeIsAny(mode)") + protected RNull asVector(RNull x, @SuppressWarnings("unused") String mode) { + return x; + } - protected boolean castToComplex(RAbstractContainer x, String mode) { - return x.getElementClass() != RComplex.class && RType.Complex.getName().equals(mode); - } + @Specialization(guards = "modeIsPairList(mode)") + protected Object asVectorPairList(RList x, @SuppressWarnings("unused") String mode) { + // TODO implement non-empty element list conversion; this is a placeholder for type test + if (x.getLength() == 0) { + return RNull.instance; + } else { + throw RError.nyi(RError.SHOW_CALLER, "non-empty lists"); + } + } - protected boolean castToLogical(RAbstractContainer x, String mode) { - return x.getElementClass() != RLogical.class && RType.Logical.getName().equals(mode); - } + @Specialization(guards = "modeIsAny(mode)") + protected RAbstractVector asVectorAny(RAbstractVector x, @SuppressWarnings("unused") String mode) { + return x.copyWithNewDimensions(null); + } - protected boolean castToString(String mode) { - return RType.Character.getName().equals(mode); - } + @Specialization(guards = "modeMatches(x, mode)") + protected RAbstractVector asVector(RAbstractVector x, @SuppressWarnings("unused") String mode) { + return x.copyWithNewDimensions(null); + } - protected boolean castToRaw(RAbstractContainer x, String mode) { - return x.getElementClass() != RRaw.class && RType.Raw.getName().equals(mode); - } + protected boolean castToInt(RAbstractContainer x, String mode) { + return x.getElementClass() != RInteger.class && RType.Integer.getName().equals(mode); + } - protected boolean castToList(String mode) { - return RType.List.getName().equals(mode); - } + protected boolean castToDouble(RAbstractContainer x, String mode) { + return x.getElementClass() != RDouble.class && (RType.Double.getClazz().equals(mode) || RType.Double.getName().equals(mode)); + } - protected boolean castToSymbol(RAbstractContainer x, String mode) { - return x.getElementClass() != Object.class && RType.Symbol.getName().equals(mode); - } + protected boolean castToComplex(RAbstractContainer x, String mode) { + return x.getElementClass() != RComplex.class && RType.Complex.getName().equals(mode); + } - protected boolean castToExpression(String mode) { - return RType.Expression.getName().equals(mode); - } + protected boolean castToLogical(RAbstractContainer x, String mode) { + return x.getElementClass() != RLogical.class && RType.Logical.getName().equals(mode); + } - protected boolean modeMatches(RAbstractVector x, String mode) { - return RRuntime.classToString(x.getElementClass()).equals(mode) || x.getElementClass() == RDouble.class && RType.Double.getName().equals(mode); - } + protected boolean castToString(String mode) { + return RType.Character.getName().equals(mode); + } - protected boolean modeIsAny(String mode) { - return RType.Any.getName().equals(mode); - } + protected boolean castToRaw(RAbstractContainer x, String mode) { + return x.getElementClass() != RRaw.class && RType.Raw.getName().equals(mode); + } - protected boolean modeIsPairList(String mode) { - return RType.PairList.getName().equals(mode); - } + protected boolean castToList(String mode) { + return RType.List.getName().equals(mode); + } - @SuppressWarnings("unused") - @Fallback - @TruffleBoundary - protected RAbstractVector asVectorWrongMode(Object x, Object mode) { - controlVisibility(); - throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "mode"); + protected boolean castToSymbol(RAbstractContainer x, String mode) { + return x.getElementClass() != Object.class && RType.Symbol.getName().equals(mode); + } + + protected boolean castToExpression(String mode) { + return RType.Expression.getName().equals(mode); + } + + protected boolean modeMatches(RAbstractVector x, String mode) { + return RRuntime.classToString(x.getElementClass()).equals(mode) || x.getElementClass() == RDouble.class && RType.Double.getName().equals(mode); + } + + protected boolean modeIsAny(String mode) { + return RType.Any.getName().equals(mode); + } + + protected boolean modeIsPairList(String mode) { + return RType.PairList.getName().equals(mode); + } + + @SuppressWarnings("unused") + @Fallback + @TruffleBoundary + protected RAbstractVector asVectorWrongMode(Object x, String mode) { + throw RError.error(RError.SHOW_CALLER, RError.Message.INVALID_ARGUMENT, "mode"); + } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java index 23a3b7157753b159e41743dee462c7fc65b2dbf2..97703f34aec03e9076d2b31ec70b336947378ddc 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DimNames.java @@ -41,7 +41,6 @@ public abstract class DimNames extends RBuiltinNode { private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private final ConditionProfile nullProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile dataframeProfile = BranchProfile.create(); private final BranchProfile factorProfile = BranchProfile.create(); private final BranchProfile otherProfile = BranchProfile.create();