diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java index 80b2d4eb141463eb588c35467f57271848a8d583..eadcc67c1691925fac1754d3f54317dbf876dcd6 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java @@ -48,6 +48,7 @@ import com.oracle.truffle.api.impl.FindContextNode; import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; @@ -102,6 +103,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; import com.oracle.truffle.r.runtime.nodes.RNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** @@ -384,7 +386,7 @@ final class REngine implements Engine, Engine.Timings { for (int i = 0; i < exprs.getLength(); i++) { Object obj = RASTUtils.checkForRSymbol(exprs.getDataAt(i)); if (obj instanceof RLanguage) { - result = evalNode((RNode) ((RLanguage) obj).getRep(), envir, depth); + result = evalNode(((RLanguage) obj).getRep().asRSyntaxNode(), envir, depth); } else { result = obj; } @@ -394,7 +396,7 @@ final class REngine implements Engine, Engine.Timings { @Override public Object eval(RLanguage expr, REnvironment envir, int depth) { - return evalNode((RNode) expr.getRep(), envir, depth); + return evalNode(expr.getRep().asRSyntaxNode(), envir, depth); } @Override @@ -432,11 +434,11 @@ final class REngine implements Engine, Engine.Timings { return func.getTarget().call(rArgs); } - private Object evalNode(RNode exprRep, REnvironment envir, int depth) { + private Object evalNode(RSyntaxElement exprRep, REnvironment envir, int depth) { // we need to copy the node, otherwise it (and its children) will specialized to a specific // frame descriptor and will fail on subsequent re-executions - RNode n = (RNode) exprRep.deepCopy(); - RootCallTarget callTarget = doMakeCallTarget(n, EVAL_FUNCTION_NAME, false, false); + RSyntaxNode n = RContext.getASTBuilder().process(exprRep); + RootCallTarget callTarget = doMakeCallTarget(n.asRNode(), EVAL_FUNCTION_NAME, false, false); RCaller call = RArguments.getCall(envir.getFrame()); return evalTarget(callTarget, call, envir, depth); } @@ -484,6 +486,7 @@ final class REngine implements Engine, Engine.Timings { private final class AnonymousRootNode extends RootNode { private final ValueProfile frameTypeProfile = ValueProfile.createClassProfile(); + private final ConditionProfile isVirtualFrameProfile = ConditionProfile.createBinaryProfile(); private final String description; private final boolean printResult; @@ -499,10 +502,21 @@ final class REngine implements Engine, Engine.Timings { this.topLevel = topLevel; } + private VirtualFrame prepareFrame(VirtualFrame frame) { + VirtualFrame vf; + MaterializedFrame originalFrame = (MaterializedFrame) frameTypeProfile.profile(frame.getArguments()[0]); + if (isVirtualFrameProfile.profile(originalFrame instanceof VirtualFrame)) { + vf = (VirtualFrame) originalFrame; + } else { + vf = SubstituteVirtualFrame.create(originalFrame); + } + return vf; + } + @Override public Object execute(VirtualFrame frame) { assert frame.getArguments().length == 1; - VirtualFrame vf = SubstituteVirtualFrame.create((MaterializedFrame) frameTypeProfile.profile(frame.getArguments()[0])); + VirtualFrame vf = prepareFrame(frame); Object result = null; try { result = body.execute(vf); diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java index 590fdc5b8f241f2ab63c3b14aabe3d21965309d5..3387c39a9edb20d3fe757c41f8760495f60b4932 100644 --- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java +++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java @@ -48,7 +48,6 @@ import com.oracle.truffle.r.nodes.control.IfNode; import com.oracle.truffle.r.nodes.control.ReplacementNode; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.function.FunctionExpressionNode; -import com.oracle.truffle.r.nodes.function.GroupDispatchNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.Arguments; @@ -268,16 +267,14 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { private static RNode unwrapToRNode(Object objArg) { Object obj = objArg; + // obj is RSymbol or a primitive value. + // A symbol needs to be converted back to a ReadVariableNode if (obj instanceof RLanguage) { return (RNode) RASTUtils.unwrap(((RLanguage) obj).getRep()); + } else if (obj instanceof RSymbol) { + return ReadVariableNode.create(((RSymbol) obj).getName()); } else { - // obj is RSymbol or a primitive value. - // A symbol needs to be converted back to a ReadVariableNode - if (obj instanceof RSymbol) { - return ReadVariableNode.create(((RSymbol) obj).getName()); - } else { - return ConstantNode.create(obj); - } + return ConstantNode.create(obj); } } @@ -299,7 +296,8 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { @TruffleBoundary public RStringVector getNames(RLanguage rl) { RBaseNode node = rl.getRep(); - if (node instanceof RCallNode || node instanceof GroupDispatchNode) { + if (node instanceof RCallNode) { + RCallNode call = (RCallNode) node; /* * If the function or any argument has a name, then all arguments (and the function) are * given names, with unnamed arguments getting "". However, if no arguments have names, @@ -307,13 +305,12 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { */ boolean hasName = false; String functionName = ""; - RNode fnNode = RASTUtils.getFunctionNode(node); + RNode fnNode = call.getFunctionNode(); if (fnNode instanceof NamedRNode) { hasName = true; functionName = ((NamedRNode) fnNode).name; } - Arguments<RSyntaxNode> args = RASTUtils.findCallArguments(node); - ArgumentsSignature sig = args.getSignature(); + ArgumentsSignature sig = call.getSyntaxSignature(); if (!hasName) { for (int i = 0; i < sig.getLength(); i++) { if (sig.getName(i) != null) { @@ -342,7 +339,8 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { public void setNames(RLanguage rl, RStringVector names) { RNode node = (RNode) rl.getRep(); if (node instanceof RCallNode) { - Arguments<RSyntaxNode> args = RASTUtils.findCallArguments(node); + RCallNode call = (RCallNode) node; + Arguments<RSyntaxNode> args = call.getArguments(); ArgumentsSignature sig = args.getSignature(); String[] newNames = new String[sig.getLength()]; int argNamesLength = names.getLength() - 1; @@ -354,8 +352,6 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { } // copying is already handled by RShareable rl.setRep(RCallNode.createCall(RSyntaxNode.INTERNAL, ((RCallNode) node).getFunctionNode(), ArgumentsSignature.get(newNames), args.getArguments())); - } else if (node instanceof GroupDispatchNode) { - throw RError.nyi(null, "group dispatch names update"); } else { throw RInternalError.shouldNotReachHere(); } @@ -601,7 +597,7 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess { String className = tag.getSimpleName(); switch (className) { case "CallTag": - return node instanceof RCallNode || node instanceof GroupDispatchNode; + return node instanceof RCallNode; case "StatementTag": { Node parent = ((RInstrumentableNode) node).unwrapParent(); diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java index 8b323a7fdcc6a4628f197ac642032030265de0ec..682b91fa607cef84a868fd069418f2b0e9bef573 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/methods/MethodsListDispatch.java @@ -379,7 +379,7 @@ public class MethodsListDispatch { } RCallNode callNode = (RCallNode) matchedCall.getRep(); RNode f = ReadVariableNode.create(RRuntime.R_DOT_NEXT_METHOD); - ArgumentsSignature sig = callNode.getArguments().getSignature(); + ArgumentsSignature sig = callNode.getSyntaxSignature(); RSyntaxNode[] args = new RSyntaxNode[sig.getLength()]; for (int i = 0; i < args.length; i++) { args[i] = ReadVariableNode.create(sig.getName(i)); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java index 38789f6c31b05e8622637f3bbde62bb4dfd9fa29..f7be50677a4077bef69c530505b797df8c0d4892 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AnyNA.java @@ -33,17 +33,10 @@ import com.oracle.truffle.r.runtime.RBuiltinKind; import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.ops.na.NACheck; @RBuiltin(name = "anyNA", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"x"}, dispatch = RDispatch.INTERNAL_GENERIC) @@ -140,11 +133,6 @@ public abstract class AnyNA extends RBuiltinNode { return doScalar(false); } - @Specialization - protected byte isNA(RFactor value) { - return doVector(value.getVector(), (v, i) -> naCheck.check(v.getDataAt(i))); - } - protected AnyNA createRecursive() { return AnyNANodeGen.create(null); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java index fa8dec148fd08e6e98b32a2e18097b45c6269008..5b8d1e5d4807c0f7d0af5120f518d7946bbbd4de 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsDouble.java @@ -30,13 +30,7 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNodeGen; import com.oracle.truffle.r.runtime.RBuiltin; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @RBuiltin(name = "as.double", aliases = {"as.numeric"}, kind = PRIMITIVE, parameterNames = {"x", "..."}) @@ -116,9 +110,4 @@ public abstract class AsDouble extends RBuiltinNode { initCast(); return (RDoubleVector) castDoubleNode.executeDouble(vector); } - - @Specialization - protected RDoubleVector asDouble(RFactor vector) { - return asDouble(vector.getVector()); - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java index 5f760658c2501b741868d7cbef536235cd53c8ea..02ea4ef335d976d9c416d0d91fc283a6866b1990 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/AsInteger.java @@ -31,13 +31,7 @@ import com.oracle.truffle.r.nodes.unary.CastIntegerNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.conn.RConnection; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RRaw; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -119,11 +113,6 @@ public abstract class AsInteger extends RBuiltinNode { return (RAbstractIntVector) castIntNode.executeInt(vector); } - @Specialization - protected RIntVector asInteger(RFactor factor) { - return asInteger(factor.getVector()); - } - @Specialization protected int asInteger(RConnection conn) { return conn.getDescriptor(); 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..b7c3348fa9ac9ac44554ad2aa232bf2802507337 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,243 +24,233 @@ 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.dsl.TypeSystemReference; +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.unary.CastComplexNode; -import com.oracle.truffle.r.nodes.unary.CastDoubleNode; -import com.oracle.truffle.r.nodes.unary.CastExpressionNode; -import com.oracle.truffle.r.nodes.unary.CastIntegerNode; -import com.oracle.truffle.r.nodes.unary.CastListNode; -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.RBuiltin; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.RFactor; -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.RSymbol; -import com.oracle.truffle.r.runtime.data.RVector; +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.*; +import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.data.*; 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"}) 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) { + // Note: this dispatch takes care of factor, because there is as.vector.factor + // specialization in R + 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); - } + @TypeSystemReference(RTypes.class) + 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 RNull asVector(RNull x, @SuppressWarnings("unused") String mode) { + return x; + } - protected boolean castToDouble(RAbstractContainer x, String mode) { - return x.getElementClass() != RDouble.class && (RType.Double.getClazz().equals(mode) || RType.Double.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 castToComplex(RAbstractContainer x, String mode) { - return x.getElementClass() != RComplex.class && RType.Complex.getName().equals(mode); - } + @Specialization(guards = "modeIsAny(mode)") + protected RAbstractVector asVectorAny(RAbstractVector x, @SuppressWarnings("unused") String mode) { + return x.copyWithNewDimensions(null); + } - protected boolean castToLogical(RAbstractContainer x, String mode) { - return x.getElementClass() != RLogical.class && RType.Logical.getName().equals(mode); - } + @Specialization(guards = "modeMatches(x, mode)") + protected RAbstractVector asVector(RAbstractVector x, @SuppressWarnings("unused") String mode) { + return x.copyWithNewDimensions(null); + } - protected boolean castToString(String mode) { - return RType.Character.getName().equals(mode); - } + protected boolean castToInt(RAbstractContainer x, String mode) { + return x.getElementClass() != RInteger.class && RType.Integer.getName().equals(mode); + } - protected boolean castToRaw(RAbstractContainer x, String mode) { - return x.getElementClass() != RRaw.class && RType.Raw.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 castToList(String mode) { - return RType.List.getName().equals(mode); - } + protected boolean castToComplex(RAbstractContainer x, String mode) { + return x.getElementClass() != RComplex.class && RType.Complex.getName().equals(mode); + } - protected boolean castToSymbol(RAbstractContainer x, String mode) { - return x.getElementClass() != Object.class && RType.Symbol.getName().equals(mode); - } + protected boolean castToLogical(RAbstractContainer x, String mode) { + return x.getElementClass() != RLogical.class && RType.Logical.getName().equals(mode); + } - protected boolean castToExpression(String mode) { - return RType.Expression.getName().equals(mode); - } + protected boolean castToString(String mode) { + return RType.Character.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 castToRaw(RAbstractContainer x, String mode) { + return x.getElementClass() != RRaw.class && RType.Raw.getName().equals(mode); + } - protected boolean modeIsAny(String mode) { - return RType.Any.getName().equals(mode); - } + protected boolean castToList(String mode) { + return RType.List.getName().equals(mode); + } - protected boolean modeIsPairList(String mode) { - return RType.PairList.getName().equals(mode); - } + protected boolean castToSymbol(RAbstractContainer x, String mode) { + return x.getElementClass() != Object.class && RType.Symbol.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 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/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index 52adbf3a11dea8a445eb6363720156f718f2a1e5..1d6e7c0216b1f24f7c0f5b7e558329c11e8bba30 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -45,8 +45,6 @@ import com.oracle.truffle.r.nodes.builtin.base.foreign.ForeignFunctions; import com.oracle.truffle.r.nodes.builtin.base.foreign.ForeignFunctionsFactory; import com.oracle.truffle.r.nodes.builtin.fastr.FastRCallCounting; import com.oracle.truffle.r.nodes.builtin.fastr.FastRCallCountingFactory; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRCompile; -import com.oracle.truffle.r.nodes.builtin.fastr.FastRCompileNodeGen; import com.oracle.truffle.r.nodes.builtin.fastr.FastRContext; import com.oracle.truffle.r.nodes.builtin.fastr.FastRContextFactory; import com.oracle.truffle.r.nodes.builtin.fastr.FastRDebug; @@ -277,7 +275,6 @@ public class BasePackage extends RBuiltinPackage { add(Expression.class, ExpressionNodeGen::create); add(FastRCallCounting.CreateCallCounter.class, FastRCallCountingFactory.CreateCallCounterNodeGen::create); add(FastRCallCounting.GetCallCounter.class, FastRCallCountingFactory.GetCallCounterNodeGen::create); - add(FastRCompile.class, FastRCompileNodeGen::create); add(FastRContext.CloseChannel.class, FastRContextFactory.CloseChannelNodeGen::create); add(FastRContext.Create.class, FastRContextFactory.CreateNodeGen::create); add(FastRContext.CreateChannel.class, FastRContextFactory.CreateChannelNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java index 010d68a7e827fa350a899c70a8bfb3118c30bf2b..c541a7b83417fb90c612cd060f6240e680e7b0bd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Bind.java @@ -27,58 +27,51 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL; import java.util.Arrays; 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.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.Node; 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.RASTUtils; -import com.oracle.truffle.r.nodes.builtin.RPrecedenceBuiltinNode; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; 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.CastIntegerNode; -import com.oracle.truffle.r.nodes.unary.CastListNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNode; -import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; -import com.oracle.truffle.r.nodes.unary.CastNode; -import com.oracle.truffle.r.nodes.unary.CastStringNode; -import com.oracle.truffle.r.nodes.unary.CastToVectorNode; -import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; -import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RArguments; -import com.oracle.truffle.r.runtime.RBuiltin; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPromise; -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.nodes.helpers.InheritsCheckNode; +import com.oracle.truffle.r.nodes.unary.*; +import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; -public abstract class Bind extends RPrecedenceBuiltinNode { +public abstract class Bind extends RBaseNode { + + protected enum BindType { + rbind, + cbind; + } + + protected static final int NO_PRECEDENCE = PrecedenceNode.NO_PRECEDENCE; + protected static final int RAW_PRECEDENCE = PrecedenceNode.RAW_PRECEDENCE; + protected static final int LOGICAL_PRECEDENCE = PrecedenceNode.LOGICAL_PRECEDENCE; + protected static final int INT_PRECEDENCE = PrecedenceNode.INT_PRECEDENCE; + protected static final int DOUBLE_PRECEDENCE = PrecedenceNode.DOUBLE_PRECEDENCE; + protected static final int COMPLEX_PRECEDENCE = PrecedenceNode.COMPLEX_PRECEDENCE; + protected static final int STRING_PRECEDENCE = PrecedenceNode.STRING_PRECEDENCE; + protected static final int LIST_PRECEDENCE = PrecedenceNode.LIST_PRECEDENCE; + protected static final int EXPRESSION_PRECEDENCE = PrecedenceNode.EXPRESSION_PRECEDENCE; + + public abstract Object execute(VirtualFrame frame, Object deparseLevelObj, Object[] args, RArgsValuesAndNames promiseArgs, int precedence); @Child private CastToVectorNode castVector; @Child private UseMethodInternalNode dcn; @Child private CastLogicalNode castLogical; + private final BindType type; + private final ConditionProfile nullNamesProfile = ConditionProfile.createBinaryProfile(); private final ConditionProfile emptyVectorProfile = ConditionProfile.createBinaryProfile(); private final BranchProfile nonNullNames = BranchProfile.create(); @@ -87,10 +80,19 @@ public abstract class Bind extends RPrecedenceBuiltinNode { protected final ValueProfile resultProfile = ValueProfile.createClassProfile(); protected final ValueProfile vectorProfile = ValueProfile.createClassProfile(); - protected String getBindType() { - // this method should be abstract but due to annotation processor problem it does not work - RInternalError.unimplemented("getBindType() method must be overridden in a subclass"); - return null; + @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); + + protected int precedence(RArgsValuesAndNames args) { + int precedence = -1; + Object[] array = args.getArguments(); + for (int i = 0; i < array.length; i++) { + precedence = Math.max(precedence, precedenceNode.executeInteger(array[i], RRuntime.LOGICAL_FALSE)); + } + return precedence; + } + + protected Bind(BindType type) { + this.type = type; } protected RAbstractVector castVector(Object value) { @@ -110,9 +112,8 @@ public abstract class Bind extends RPrecedenceBuiltinNode { } @SuppressWarnings("unused") - @Specialization(guards = "isNullPrecedence(args)") - protected RNull allNull(VirtualFrame frame, Object deparseLevelObj, RArgsValuesAndNames args) { - controlVisibility(); + @Specialization(guards = "precedence == NO_PRECEDENCE") + protected RNull allNull(VirtualFrame frame, Object deparseLevelObj, Object[] args, RArgsValuesAndNames promiseArgs, int precedence) { return RNull.instance; } @@ -120,35 +121,33 @@ public abstract class Bind extends RPrecedenceBuiltinNode { private static final RStringVector DATA_FRAME_CLASS = RDataFactory.createStringVectorFromScalar("data.frame"); - @Specialization(guards = {"args.getLength() > 1", "isDataFrame(args)"}) - protected Object allDataFrame(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args) { + @Specialization(guards = {"args.length > 1", "isDataFrame(args)"}) + protected Object allDataFrame(VirtualFrame frame, Object deparseLevel, @SuppressWarnings("unused") Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence) { if (dcn == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - dcn = insert(new UseMethodInternalNode(getBindType(), SIGNATURE, false)); + dcn = insert(new UseMethodInternalNode(type.toString(), SIGNATURE, false)); } try { - return dcn.execute(frame, DATA_FRAME_CLASS, new Object[]{deparseLevel, args}); + return dcn.execute(frame, DATA_FRAME_CLASS, new Object[]{deparseLevel, promiseArgs}); } catch (S3FunctionLookupNode.NoGenericMethodException e) { throw RInternalError.shouldNotReachHere(); } } - private Object bindInternal(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args, CastNode castNode, boolean needsVectorCast) { - controlVisibility(); - Object[] array = args.getArguments(); - ArgumentsSignature signature = args.getSignature(); + private Object bindInternal(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, CastNode castNode, boolean needsVectorCast) { + ArgumentsSignature signature = promiseArgs.getSignature(); String[] vecNames = nullNamesProfile.profile(signature.getNonNullCount() == 0) ? null : new String[signature.getLength()]; - RAbstractVector[] vectors = new RAbstractVector[args.getLength()]; + RAbstractVector[] vectors = new RAbstractVector[args.length]; boolean complete = true; int ind = 0; naCheck.enable(true); - for (int i = 0; i < array.length; i++) { + for (int i = 0; i < args.length; i++) { if (vecNames != null) { nonNullNames.enter(); vecNames[ind] = signature.getName(i); naCheck.check(vecNames[ind]); } - Object result = castNode.execute(array[i]); + Object result = castNode.execute(args[i]); RAbstractVector vector; if (needsVectorCast) { vector = castVector(result); @@ -163,80 +162,48 @@ public abstract class Bind extends RPrecedenceBuiltinNode { ind++; } } - if (emptyVectorProfile.profile(ind < array.length)) { + if (emptyVectorProfile.profile(ind < args.length)) { if (vecNames != null) { nonNullNames.enter(); vecNames = Arrays.copyOf(vecNames, ind); } vectors = Arrays.copyOf(vectors, ind); } - return genericBind(frame, vectors, complete, vecNames, naCheck.neverSeenNA(), deparseLevel); + if (type == BindType.cbind) { + return genericCBind(promiseArgs, vectors, complete, vecNames, naCheck.neverSeenNA(), deparseLevel); + } else { + return genericRBind(promiseArgs, vectors, complete, vecNames, naCheck.neverSeenNA(), deparseLevel); + } } - @Specialization(guards = {"isIntegerPrecedence(args)", "args.getLength() > 1", "!isDataFrame(args)"}) - protected Object allInt(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args, // + @Specialization(guards = {"precedence == INT_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"}) + protected Object allInt(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastIntegerNode cast) { - return bindInternal(frame, deparseLevel, args, cast, true); + return bindInternal(deparseLevel, args, promiseArgs, cast, true); } - @Specialization(guards = {"isDoublePrecedence( args)", "args.getLength() > 1", "!isDataFrame(args)"}) - protected Object allDouble(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args, // + @Specialization(guards = {"precedence == DOUBLE_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"}) + protected Object allDouble(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastDoubleNode cast) { - return bindInternal(frame, deparseLevel, args, cast, true); + return bindInternal(deparseLevel, args, promiseArgs, cast, true); } - @Specialization(guards = {"isStringPrecedence( args)", "args.getLength() > 1", "!isDataFrame(args)"}) - protected Object allString(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args, // + @Specialization(guards = {"precedence == STRING_PRECEDENCE", "args.length> 1", "!isDataFrame(args)"}) + protected Object allString(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastStringNode cast) { - return bindInternal(frame, deparseLevel, args, cast, true); + return bindInternal(deparseLevel, args, promiseArgs, cast, true); } - @Specialization(guards = {"isComplexPrecedence( args)", "args.getLength() > 1", "!isDataFrame(args)"}) - protected Object allComplex(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args, // + @Specialization(guards = {"precedence == COMPLEX_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"}) + protected Object allComplex(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastComplexNode cast) { - return bindInternal(frame, deparseLevel, args, cast, true); + return bindInternal(deparseLevel, args, promiseArgs, cast, true); } - @Specialization(guards = {"isListPrecedence( args)", "args.getLength() > 1", "!isDataFrame(args)"}) - protected Object allList(VirtualFrame frame, Object deparseLevel, RArgsValuesAndNames args, // + @Specialization(guards = {"precedence == LIST_PRECEDENCE", "args.length > 1", "!isDataFrame(args)"}) + protected Object allList(Object deparseLevel, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence, // @Cached("create()") CastListNode cast) { - return bindInternal(frame, deparseLevel, args, cast, false); - } - - protected Object allOneElem(VirtualFrame frame, Object deparseLevelObj, RArgsValuesAndNames args, boolean cbind) { - RAbstractVector vec = castVector(args.getArgument(0)); - if (vec.isMatrix()) { - return vec; - } - int[] dims = getDimensions(vec, cbind); - // for cbind dimNamesA is names for the 1st dim and dimNamesB is names for 2nd dim; for - // rbind the other way around - Object dimNamesA = vec.getNames(attrProfiles) == null ? RNull.instance : vec.getNames(attrProfiles); - Object dimNamesB; - - ArgumentsSignature signature = args.getSignature(); - if (signature.getNonNullCount() == 0) { - int deparseLevel = deparseLevel(deparseLevelObj); - if (deparseLevel == 0) { - dimNamesB = RNull.instance; - } else { - // var arg is at the first position - as in the R bind call - RArgsValuesAndNames varArg = (RArgsValuesAndNames) RArguments.getArgument(frame, 0); - String deparsedName = deparseArgName(varArg, deparseLevel, 0); - dimNamesB = deparsedName == RRuntime.NAMES_ATTR_EMPTY_VALUE ? RNull.instance : RDataFactory.createStringVector(deparsedName); - } - } else { - String[] names = new String[signature.getLength()]; - for (int i = 0; i < names.length; i++) { - names[i] = signature.getName(i); - } - dimNamesB = RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR); - } - - RVector res = (RVector) vec.copyWithNewDimensions(dims); - res.setDimNames(RDataFactory.createList(cbind ? new Object[]{dimNamesA, dimNamesB} : new Object[]{dimNamesB, dimNamesA})); - res.copyRegAttributesFrom(vec); - return res; + return bindInternal(deparseLevel, args, promiseArgs, cast, false); } /** @@ -273,18 +240,9 @@ public abstract class Bind extends RPrecedenceBuiltinNode { /** * Compute dimnames for columns (cbind) or rows (rbind) from names of vectors being combined or * by deparsing. - * - * @param frame - * @param vec - * @param argNames - * @param resDim - * @param oldInd - * @param vecInd - * @param deparseLevelObj - * @param dimNamesArray - * @return dimnames */ - protected int getDimResultNamesFromVectors(VirtualFrame frame, RAbstractVector vec, String[] argNames, int resDim, int oldInd, int vecInd, Object deparseLevelObj, String[] dimNamesArray, + protected int getDimResultNamesFromVectors(RArgsValuesAndNames promiseArgs, RAbstractVector vec, String[] argNames, int resDim, int oldInd, int vecInd, Object deparseLevelObj, + String[] dimNamesArray, int dimNamesInd) { int ind = oldInd; if (vec.isMatrix()) { @@ -311,8 +269,7 @@ public abstract class Bind extends RPrecedenceBuiltinNode { dimNamesArray[ind++] = RRuntime.NAMES_ATTR_EMPTY_VALUE; return -ind; } else { - RArgsValuesAndNames varArg = (RArgsValuesAndNames) RArguments.getArgument(frame, 0); - String deparsedName = deparseArgName(varArg, deparseLevel, vecInd); + String deparsedName = deparseArgName(promiseArgs, deparseLevel, vecInd); dimNamesArray[ind++] = deparsedName; return deparsedName == RRuntime.NAMES_ATTR_EMPTY_VALUE ? -ind : ind; } @@ -331,33 +288,25 @@ public abstract class Bind extends RPrecedenceBuiltinNode { } } - @SuppressWarnings("unused") - protected RVector genericBind(VirtualFrame frame, RAbstractVector[] vectors, boolean complete, String[] vacNames, boolean vecNamesComplete, Object deparseLevel) { - // this method should be abstract but due to annotation processor problem it does not work - RInternalError.unimplemented("genericBind() method must be overridden in a subclass"); - return null; - } - /** * * @param vectors vectors to be combined * @param res result dims * @param bindDims columns dim (cbind) or rows dim (rbind) - * @param cbind to be used for cbind function (true) or rbind function (false) * @return whether number of rows (cbind) or columns (rbind) in vectors is the same */ - protected static boolean getResultDimensions(RAbstractVector[] vectors, int[] res, int[] bindDims, boolean cbind) { - int srcDim1Ind = cbind ? 0 : 1; - int srcDim2Ind = cbind ? 1 : 0; + protected boolean getResultDimensions(RAbstractVector[] vectors, int[] res, int[] bindDims) { + int srcDim1Ind = type == BindType.cbind ? 0 : 1; + int srcDim2Ind = type == BindType.cbind ? 1 : 0; assert vectors.length > 0; - int[] dim = getDimensions(vectors[0], cbind); + int[] dim = getDimensions(vectors[0]); assert dim.length == 2; bindDims[0] = dim[srcDim2Ind]; res[srcDim1Ind] = dim[srcDim1Ind]; res[srcDim2Ind] = dim[srcDim2Ind]; boolean notEqualDims = false; for (int i = 1; i < vectors.length; i++) { - int[] dims = getDimensions(vectors[i], cbind); + int[] dims = getDimensions(vectors[i]); assert dims.length == 2; bindDims[i] = dims[srcDim2Ind]; if (dims[srcDim1Ind] != res[srcDim1Ind]) { @@ -380,10 +329,10 @@ public abstract class Bind extends RPrecedenceBuiltinNode { } } - protected static int[] getDimensions(RAbstractVector vector, boolean cbind) { + protected int[] getDimensions(RAbstractVector vector) { int[] dimensions = vector.getDimensions(); if (dimensions == null || dimensions.length != 2) { - return cbind ? new int[]{vector.getLength(), 1} : new int[]{1, vector.getLength()}; + return type == BindType.cbind ? new int[]{vector.getLength(), 1} : new int[]{1, vector.getLength()}; } else { assert dimensions.length == 2; return dimensions; @@ -391,9 +340,9 @@ public abstract class Bind extends RPrecedenceBuiltinNode { } @TruffleBoundary - protected static String deparseArgName(RArgsValuesAndNames varArg, int deparseLevel, int argInd) { - assert varArg.getLength() >= argInd; - Object argValue = varArg.getArgument(argInd); + protected static String deparseArgName(RArgsValuesAndNames promiseArgs, int deparseLevel, int argInd) { + assert promiseArgs.getLength() >= argInd; + Object argValue = promiseArgs.getArgument(argInd); if (argValue instanceof RPromise) { RPromise p = (RPromise) argValue; Object node = RASTUtils.createLanguageElement(RASTUtils.unwrap(p.getRep())); @@ -409,191 +358,209 @@ public abstract class Bind extends RPrecedenceBuiltinNode { @Child private InheritsCheckNode inheritsCheck = new InheritsCheckNode(RRuntime.CLASS_DATA_FRAME); - public static final class InheritsCheckNode extends Node { + protected boolean isDataFrame(Object[] args) { + for (int i = 0; i < args.length; i++) { + if (inheritsCheck.execute(args[i])) { + return true; + } + } - @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); - private final ConditionProfile nullClassProfile = ConditionProfile.createBinaryProfile(); - @CompilationFinal private ConditionProfile exactMatchProfile; - private final String checkedClazz; + return false; + } - public InheritsCheckNode(String checkedClazz) { - this.checkedClazz = checkedClazz; - assert RType.fromMode(checkedClazz) == null; - } + @RBuiltin(name = "cbind", kind = INTERNAL, parameterNames = {"deparse.level", "..."}) + public abstract static class CbindInternal extends RBuiltinNode { - public boolean execute(Object value) { - RStringVector clazz = classHierarchy.execute(value); - if (nullClassProfile.profile(clazz != null)) { - for (int j = 0; j < clazz.getLength(); ++j) { - if (exactMatchProfile == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - exactMatchProfile = ConditionProfile.createBinaryProfile(); - } - if (exactMatchProfile.profile(clazz.getDataAt(j) == checkedClazz) || clazz.getDataAt(j).equals(checkedClazz)) { - return true; - } - } + @Child private Bind bind = BindNodeGen.create(BindType.cbind); + @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); + + private int precedence(Object[] args) { + int precedence = -1; + for (int i = 0; i < args.length; i++) { + precedence = Math.max(precedence, precedenceNode.executeInteger(args[i], RRuntime.LOGICAL_FALSE)); } - return false; + return precedence; + } + + @Specialization + protected Object bind(VirtualFrame frame, Object deparseLevelObj, RArgsValuesAndNames args) { + controlVisibility(); + return bind.execute(frame, deparseLevelObj, args.getArguments(), (RArgsValuesAndNames) RArguments.getArgument(frame, 0), precedence(args.getArguments())); } } - protected boolean isDataFrame(RArgsValuesAndNames args) { - for (int i = 0; i < args.getLength(); i++) { - if (inheritsCheck.execute(args.getArgument(i))) { - return true; + private final BranchProfile everSeenNotEqualRows = BranchProfile.create(); + private final BranchProfile everSeenNotEqualColumns = BranchProfile.create(); + + @Specialization(guards = {"precedence != NO_PRECEDENCE", "args.length == 1"}) + protected Object allOneElem(Object deparseLevelObj, Object[] args, RArgsValuesAndNames promiseArgs, @SuppressWarnings("unused") int precedence) { + RAbstractVector vec = castVector(args[0]); + if (vec.isMatrix()) { + return vec; + } + int[] dims = getDimensions(vec); + // for cbind dimNamesA is names for the 1st dim and dimNamesB is names for 2nd dim; for + // rbind the other way around + Object dimNamesA = vec.getNames(attrProfiles) == null ? RNull.instance : vec.getNames(attrProfiles); + Object dimNamesB; + + ArgumentsSignature signature = promiseArgs.getSignature(); + if (signature.getNonNullCount() == 0) { + int deparseLevel = deparseLevel(deparseLevelObj); + if (deparseLevel == 0) { + dimNamesB = RNull.instance; + } else { + // var arg is at the first position - as in the R bind call + String deparsedName = deparseArgName(promiseArgs, deparseLevel, 0); + dimNamesB = deparsedName == RRuntime.NAMES_ATTR_EMPTY_VALUE ? RNull.instance : RDataFactory.createStringVector(deparsedName); } + } else { + String[] names = new String[signature.getLength()]; + for (int i = 0; i < names.length; i++) { + names[i] = signature.getName(i); + } + dimNamesB = RDataFactory.createStringVector(names, RDataFactory.COMPLETE_VECTOR); } - return false; + RVector res = (RVector) vec.copyWithNewDimensions(dims); + res.setDimNames(RDataFactory.createList(type == BindType.cbind ? new Object[]{dimNamesA, dimNamesB} : new Object[]{dimNamesB, dimNamesA})); + res.copyRegAttributesFrom(vec); + return res; } - @RBuiltin(name = "cbind", kind = INTERNAL, parameterNames = {"deparse.level", "..."}) - public abstract static class CbindInternal extends Bind { - private final BranchProfile everSeenNotEqualRows = BranchProfile.create(); + public RVector genericCBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, Object deparseLevel) { - @Override - public String getBindType() { - return "cbind"; - } + int[] resultDimensions = new int[2]; + int[] secondDims = new int[vectors.length]; + boolean notEqualRows = getResultDimensions(vectors, resultDimensions, secondDims); + RVector result = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); - @Specialization(guards = {"!isNullPrecedence(args)", "args.getLength() == 1"}) - protected Object allOneElem(VirtualFrame frame, Object deparseLevelObj, RArgsValuesAndNames args) { - controlVisibility(); - return allOneElem(frame, deparseLevelObj, args, true); - } + int ind = 0; + Object rowDimResultNames = RNull.instance; + String[] colDimNamesArray = new String[resultDimensions[1]]; + int colInd = 0; + boolean allColDimNamesNull = true; + for (int i = 0; i < vectors.length; i++) { + RAbstractVector vec = vectorProfile.profile(vectors[i]); + if (rowDimResultNames == RNull.instance) { + // get the first valid names value + rowDimResultNames = getDimResultNamesFromElements(vec, resultDimensions[0], 0); + } - @Override - public RVector genericBind(VirtualFrame frame, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, Object deparseLevel) { - - int[] resultDimensions = new int[2]; - int[] secondDims = new int[vectors.length]; - boolean notEqualRows = getResultDimensions(vectors, resultDimensions, secondDims, true); - RVector result = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); - - int ind = 0; - Object rowDimResultNames = RNull.instance; - String[] colDimNamesArray = new String[resultDimensions[1]]; - int colInd = 0; - boolean allColDimNamesNull = true; - for (int i = 0; i < vectors.length; i++) { - RAbstractVector vec = vectorProfile.profile(vectors[i]); - if (rowDimResultNames == RNull.instance) { - // get the first valid names value - rowDimResultNames = getDimResultNamesFromElements(vec, resultDimensions[0], 0); - } + // compute dimnames for the second dimension + int newColInd = getDimResultNamesFromVectors(promiseArgs, vec, vecNames, secondDims[i], colInd, i, deparseLevel, colDimNamesArray, 1); + if (newColInd < 0) { + colInd = -newColInd; + } else { + allColDimNamesNull = false; + colInd = newColInd; + } - // compute dimnames for the second dimension - int newColInd = getDimResultNamesFromVectors(frame, vec, vecNames, secondDims[i], colInd, i, deparseLevel, colDimNamesArray, 1); - if (newColInd < 0) { - colInd = -newColInd; - } else { - allColDimNamesNull = false; - colInd = newColInd; - } + // compute result vector values + int vecLength = vec.getLength(); + for (int j = 0; j < vecLength; j++) { + result.transferElementSameType(ind++, vec, j); + } + if (notEqualRows) { + everSeenNotEqualRows.enter(); + if (vecLength < resultDimensions[0]) { + // re-use vector elements + int k = 0; + for (int j = 0; j < resultDimensions[0] - vecLength; j++, k = Utils.incMod(k, vecLength)) { + result.transferElementSameType(ind++, vectors[i], k); + } - // compute result vector values - int vecLength = vec.getLength(); - for (int j = 0; j < vecLength; j++) { - result.transferElementSameType(ind++, vec, j); - } - if (notEqualRows) { - everSeenNotEqualRows.enter(); - if (vecLength < resultDimensions[0]) { - // re-use vector elements - int k = 0; - for (int j = 0; j < resultDimensions[0] - vecLength; j++, k = Utils.incMod(k, vecLength)) { - result.transferElementSameType(ind++, vectors[i], k); - } - - if (k != 0) { - RError.warning(this, RError.Message.ROWS_NOT_MULTIPLE, i + 1); - } + if (k != 0) { + RError.warning(this, RError.Message.ROWS_NOT_MULTIPLE, i + 1); } } - } - Object colDimResultNames = allColDimNamesNull ? RNull.instance : RDataFactory.createStringVector(colDimNamesArray, vecNamesComplete); - result.setDimensions(resultDimensions); - result.setDimNames(RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames})); - return result; + } + Object colDimResultNames = allColDimNamesNull ? RNull.instance : RDataFactory.createStringVector(colDimNamesArray, vecNamesComplete); + result.setDimensions(resultDimensions); + result.setDimNames(RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames})); + return result; } @RBuiltin(name = "rbind", kind = INTERNAL, parameterNames = {"deparse.level", "..."}) - public abstract static class RbindInternal extends Bind { - private final BranchProfile everSeenNotEqualColumns = BranchProfile.create(); + public abstract static class RbindInternal extends RBuiltinNode { - @Override - public String getBindType() { - return "rbind"; + @Child private Bind bind = BindNodeGen.create(BindType.rbind); + @Child private PrecedenceNode precedenceNode = PrecedenceNodeGen.create(); + + private int precedence(Object[] args) { + int precedence = -1; + for (int i = 0; i < args.length; i++) { + precedence = Math.max(precedence, precedenceNode.executeInteger(args[i], RRuntime.LOGICAL_FALSE)); + } + return precedence; } - @Specialization(guards = {"!isNullPrecedence(args)", "args.getLength() == 1"}) - protected Object allOneElem(VirtualFrame frame, Object deparseLevelObj, RArgsValuesAndNames args) { + @Specialization + protected Object bind(VirtualFrame frame, Object deparseLevelObj, RArgsValuesAndNames args) { controlVisibility(); - return allOneElem(frame, deparseLevelObj, args, false); + return bind.execute(frame, deparseLevelObj, args.getArguments(), (RArgsValuesAndNames) RArguments.getArgument(frame, 0), precedence(args.getArguments())); } + } - @Override - public RVector genericBind(VirtualFrame frame, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, Object deparseLevel) { - - int[] resultDimensions = new int[2]; - int[] firstDims = new int[vectors.length]; - boolean notEqualColumns = getResultDimensions(vectors, resultDimensions, firstDims, false); - RVector result = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); - - Object colDimResultNames = RNull.instance; - String[] rowDimNamesArray = new String[resultDimensions[0]]; - int rowInd = 0; - boolean allRowDimNamesNull = true; - int dstRowInd = 0; - for (int i = 0; i < vectors.length; i++) { - RAbstractVector vec = vectorProfile.profile(vectors[i]); - if (colDimResultNames == RNull.instance) { - // get the first valid names value - colDimResultNames = getDimResultNamesFromElements(vec, resultDimensions[1], 1); - } + public RVector genericRBind(RArgsValuesAndNames promiseArgs, RAbstractVector[] vectors, boolean complete, String[] vecNames, boolean vecNamesComplete, Object deparseLevel) { + + int[] resultDimensions = new int[2]; + int[] firstDims = new int[vectors.length]; + boolean notEqualColumns = getResultDimensions(vectors, resultDimensions, firstDims); + RVector result = resultProfile.profile(vectors[0].createEmptySameType(resultDimensions[0] * resultDimensions[1], complete)); + + Object colDimResultNames = RNull.instance; + String[] rowDimNamesArray = new String[resultDimensions[0]]; + int rowInd = 0; + boolean allRowDimNamesNull = true; + int dstRowInd = 0; + for (int i = 0; i < vectors.length; i++) { + RAbstractVector vec = vectorProfile.profile(vectors[i]); + if (colDimResultNames == RNull.instance) { + // get the first valid names value + colDimResultNames = getDimResultNamesFromElements(vec, resultDimensions[1], 1); + } - // compute dimnames for the second dimension - int newRowInd = getDimResultNamesFromVectors(frame, vec, vecNames, firstDims[i], rowInd, i, deparseLevel, rowDimNamesArray, 0); - if (newRowInd < 0) { - rowInd = -newRowInd; - } else { - allRowDimNamesNull = false; - rowInd = newRowInd; - } + // compute dimnames for the second dimension + int newRowInd = getDimResultNamesFromVectors(promiseArgs, vec, vecNames, firstDims[i], rowInd, i, deparseLevel, rowDimNamesArray, 0); + if (newRowInd < 0) { + rowInd = -newRowInd; + } else { + allRowDimNamesNull = false; + rowInd = newRowInd; + } - // compute result vector values - int vecLength = vec.getLength(); - int srcInd = 0; - int j = 0; - for (; j < vecLength / firstDims[i]; j++) { - for (int k = dstRowInd; k < dstRowInd + firstDims[i]; k++) { - result.transferElementSameType(j * resultDimensions[0] + k, vec, srcInd++); - } + // compute result vector values + int vecLength = vec.getLength(); + int srcInd = 0; + int j = 0; + for (; j < vecLength / firstDims[i]; j++) { + for (int k = dstRowInd; k < dstRowInd + firstDims[i]; k++) { + result.transferElementSameType(j * resultDimensions[0] + k, vec, srcInd++); } - if (notEqualColumns) { - everSeenNotEqualColumns.enter(); - if (j < resultDimensions[1]) { - // re-use vector elements - int k = 0; - for (; j < resultDimensions[1]; j++, k = Utils.incMod(k, vecLength % resultDimensions[1])) { - result.transferElementSameType(j * resultDimensions[0] + (dstRowInd + firstDims[i] - 1), vectors[i], k); - } - - if (k != 0) { - RError.warning(this, RError.Message.COLUMNS_NOT_MULTIPLE, i + 1); - } + } + if (notEqualColumns) { + everSeenNotEqualColumns.enter(); + if (j < resultDimensions[1]) { + // re-use vector elements + int k = 0; + for (; j < resultDimensions[1]; j++, k = Utils.incMod(k, vecLength % resultDimensions[1])) { + result.transferElementSameType(j * resultDimensions[0] + (dstRowInd + firstDims[i] - 1), vectors[i], k); } - } - dstRowInd += firstDims[i]; + if (k != 0) { + RError.warning(this, RError.Message.COLUMNS_NOT_MULTIPLE, i + 1); + } + } } - Object rowDimResultNames = allRowDimNamesNull ? RNull.instance : RDataFactory.createStringVector(rowDimNamesArray, vecNamesComplete); - result.setDimensions(resultDimensions); - result.setDimNames(RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames})); - return result; + dstRowInd += firstDims[i]; + } + Object rowDimResultNames = allRowDimNamesNull ? RNull.instance : RDataFactory.createStringVector(rowDimNamesArray, vecNamesComplete); + result.setDimensions(resultDimensions); + result.setDimNames(RDataFactory.createList(new Object[]{rowDimResultNames, colDimResultNames})); + return result; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java index 101c464098932c834c544d786422577517ef74d6..2d4ed6aa7be1ea01176849c374d913dfbc82c11f 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CopyDFAttr.java @@ -29,7 +29,6 @@ import com.oracle.truffle.r.nodes.builtin.RInvisibleBuiltinNode; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributable; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RFactor; 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; @@ -45,11 +44,4 @@ public abstract class CopyDFAttr extends RInvisibleBuiltinNode { res.resetAllAttributes(false); return res.copyAttributesFrom(attrProfiles, in); } - - @Specialization() - protected RAttributable copy(RAbstractContainer in, RFactor out) { - RVector res = out.getVector(); - res.resetAllAttributes(false); - return res.copyAttributesFrom(attrProfiles, in); - } } 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..269a3a17a3ca5e0e54c063e6cc907ad9ce5fdefb 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 @@ -26,12 +26,10 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE; import static com.oracle.truffle.r.runtime.RDispatch.INTERNAL_GENERIC; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; @@ -41,9 +39,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(); @Specialization protected RNull getDimNames(@SuppressWarnings("unused") RNull operand) { @@ -54,14 +49,7 @@ public abstract class DimNames extends RBuiltinNode { @Specialization protected Object getDimNames(RAbstractContainer container) { controlVisibility(); - RList names; - if (container instanceof RFactor) { - factorProfile.enter(); - names = ((RFactor) container).getVector().getDimNames(); - } else { - otherProfile.enter(); - names = container.getDimNames(attrProfiles); - } + RList names = container.getDimNames(attrProfiles); return nullProfile.profile(names == null) ? RNull.instance : names; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java index c3136361e36c15445c5d4912009641c6f641f233..f1828f586f2ec87bd74c3ae75c76ccec60e0ee65 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java @@ -25,48 +25,30 @@ 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.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.nodes.CallInlineCacheNode; -import com.oracle.truffle.r.nodes.CallInlineCacheNodeGen; import com.oracle.truffle.r.nodes.RASTUtils; -import com.oracle.truffle.r.nodes.access.ConstantNode; +import com.oracle.truffle.r.nodes.access.FrameSlotNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen; -import com.oracle.truffle.r.nodes.function.ArgumentMatcher; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; -import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; -import com.oracle.truffle.r.nodes.function.EvaluatedArguments; -import com.oracle.truffle.r.nodes.function.GroupDispatchNode; -import com.oracle.truffle.r.nodes.function.PromiseHelperNode; -import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; -import com.oracle.truffle.r.nodes.function.RCallNode.RootCallNode; -import com.oracle.truffle.r.nodes.function.RCallerHelper; -import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode; -import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result; -import com.oracle.truffle.r.nodes.function.signature.GetCallerFrameNode; -import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; +import com.oracle.truffle.r.nodes.function.GetCallerFrameNode; +import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RArguments; 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; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RSymbol; @@ -79,26 +61,18 @@ import com.oracle.truffle.r.runtime.nodes.RBaseNode; @RBuiltin(name = "do.call", kind = INTERNAL, parameterNames = {"what", "args", "envir"}) public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNodeChildren { - @Child private CallInlineCacheNode callCache = CallInlineCacheNodeGen.create(); @Child private GetFunctions.Get getNode; - @Child private GroupDispatchNode groupDispatch; @Child private GetCallerFrameNode getCallerFrame; - @Child private PromiseHelperNode promiseHelper = new PromiseHelperNode(); - @CompilationFinal private boolean needsCallerFrame; - - @Child private S3FunctionLookupNode dispatchLookup; - @Child private PromiseCheckHelperNode hierarchyPromiseHelper; - @Child private ClassHierarchyNode classHierarchyNode; - @Child private RootCallNode internalDispatchCall; - - @Child private RArgumentsNode argsNode = RArgumentsNode.create(); - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private final BranchProfile errorProfile = BranchProfile.create(); private final BranchProfile containsRLanguageProfile = BranchProfile.create(); private final BranchProfile containsRSymbolProfile = BranchProfile.create(); + private final Object argsIdentifier = new Object(); + @Child private RCallNode call = RCallNode.createExplicitCall(argsIdentifier); + @Child private FrameSlotNode slot = FrameSlotNode.createTemp(argsIdentifier, true); + @Specialization protected Object doDoCall(VirtualFrame frame, Object what, RList argsAsList, REnvironment env) { /* @@ -155,85 +129,9 @@ public abstract class DoCall extends RBuiltinNode implements InternalRSyntaxNode } } } - - /* Step 3: Perform the actual evaluation, checking for builtin special cases. */ - return executeCall(frame, func, argValues, signature, callerFrame); - } - - /* This exists solely for forceAndCall builtin (R3.2.3) */ - @Specialization - protected Object doDoCall(VirtualFrame frame, RFunction func, RArgsValuesAndNames args, @SuppressWarnings("unused") RNull env) { - return executeCall(frame, func, args.getArguments(), args.getSignature(), null); - } - - private Object executeCall(VirtualFrame frame, RFunction funcArg, Object[] argValues, ArgumentsSignature signature, MaterializedFrame callerFrameArg) { - RFunction func = funcArg; - MaterializedFrame callerFrame = callerFrameArg; - RBuiltinDescriptor builtin = func.getRBuiltin(); - if (func.isBuiltin() && builtin.getDispatch() == RDispatch.INTERNAL_GENERIC) { - if (dispatchLookup == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - dispatchLookup = insert(S3FunctionLookupNode.create(true, false)); - classHierarchyNode = insert(ClassHierarchyNodeGen.create(true, true)); - hierarchyPromiseHelper = insert(new PromiseCheckHelperNode()); - } - RStringVector type = classHierarchyNode.execute(hierarchyPromiseHelper.checkEvaluate(frame, argValues[0])); - Result result = dispatchLookup.execute(frame, builtin.getName(), type, null, frame.materialize(), null); - if (result != null) { - func = result.function; - } - } - if (func.isBuiltin() && builtin.getDispatch() != null && builtin.getDispatch().isGroupGeneric()) { - if (groupDispatch == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - /* This child is not being used in a syntax context so remove tags */ - groupDispatch = insert(GroupDispatchNode.create(builtin.getName(), null, func, getOriginalCall().getSourceSection())); - } - for (int i = 0; i < argValues.length; i++) { - Object arg = argValues[i]; - if (arg instanceof RPromise) { - argValues[i] = promiseHelper.evaluate(frame, (RPromise) arg); - } - } - return groupDispatch.executeDynamic(frame, new RArgsValuesAndNames(argValues, signature), builtin.getName().intern(), builtin.getDispatch(), func); - } - EvaluatedArguments evaledArgs = EvaluatedArguments.create(argValues, signature); - EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(func, evaledArgs, this, false); - if (func.isBuiltin()) { - Object[] argArray = reorderedArgs.getArguments(); - for (int i = 0; i < argArray.length; i++) { - Object arg = argArray[i]; - if (builtin.evaluatesArg(i)) { - if (arg instanceof RPromise) { - argArray[i] = promiseHelper.evaluate(frame, (RPromise) arg); - } else if (arg instanceof RArgsValuesAndNames) { - Object[] varArgValues = ((RArgsValuesAndNames) arg).getArguments(); - for (int j = 0; j < varArgValues.length; j++) { - if (varArgValues[j] instanceof RPromise) { - varArgValues[j] = promiseHelper.evaluate(frame, (RPromise) varArgValues[j]); - } - } - } - } else { - if (!(arg instanceof RPromise) && arg != RMissing.instance && !(arg instanceof RArgsValuesAndNames)) { - callerFrame = getCallerFrame(frame, callerFrame); - argArray[i] = createArgPromise(callerFrame, ConstantNode.create(arg)); - } - } - } - } - if (!needsCallerFrame && func.containsDispatch()) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - needsCallerFrame = true; - } - callerFrame = needsCallerFrame ? getCallerFrame(frame, callerFrame) : null; - Object[] callArgs = argsNode.execute(func, new RCallerHelper.Representation(func, argValues), callerFrame, RArguments.getDepth(frame) + 1, - RArguments.getPromiseFrame(frame), - reorderedArgs.getArguments(), reorderedArgs.getSignature(), - null); - RArguments.setIsIrregular(callArgs, true); - return callCache.execute(frame, func.getTarget(), callArgs); - + FrameSlot frameSlot = slot.executeFrameSlot(frame); + frame.setObject(frameSlot, new RArgsValuesAndNames(argValues, signature)); + return call.execute(frame, func); } private MaterializedFrame getCallerFrame(VirtualFrame frame, MaterializedFrame callerFrame) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java index d6cc39970113f6710dc95d28f58cfa00b43e2a59..289e049b082d60bafa210a567f341f4c93019d83 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/EnvFunctions.java @@ -47,9 +47,9 @@ import com.oracle.truffle.r.nodes.builtin.RList2EnvNode; import com.oracle.truffle.r.nodes.builtin.RList2EnvNodeGen; import com.oracle.truffle.r.nodes.builtin.base.EnvFunctionsFactory.CopyNodeGen; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; +import com.oracle.truffle.r.nodes.function.GetCallerFrameNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode; -import com.oracle.truffle.r.nodes.function.signature.GetCallerFrameNode; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RError; @@ -170,7 +170,7 @@ public class EnvFunctions { @Specialization protected Object asEnvironment(RS4Object obj) { // generic dispatch tried already - Object xData = obj.getAttribute(RRuntime.DOT_XDATA); + Object xData = obj.getAttr(RRuntime.DOT_XDATA); if (xData == null || !(xData instanceof REnvironment)) { throw RError.error(this, RError.Message.S4OBJECT_NX_ENVIRONMENT); } else { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java index 7d8fdb265ffa1463ea75894a9dff0e42056059de..f93bc9ca83a5e5ab2d4a9951eaf3da03d45dc2a1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/ForceAndCall.java @@ -28,22 +28,28 @@ import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.access.FrameSlotNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; +import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; @RBuiltin(name = "forceAndCall", kind = PRIMITIVE, parameterNames = {"n", "FUN", "..."}, nonEvalArgs = 2) public abstract class ForceAndCall extends RBuiltinNode { - @Child private DoCall doCallNode; + private final Object argsIdentifier = new Object(); + + @Child private RCallNode call = RCallNode.createExplicitCall(argsIdentifier); + @Child private FrameSlotNode slot = FrameSlotNode.createTemp(argsIdentifier, true); + @Child private PromiseHelperNode promiseHelper; protected PromiseHelperNode initPromiseHelper() { @@ -59,29 +65,22 @@ public abstract class ForceAndCall extends RBuiltinNode { casts.toInteger(0); } - private DoCall getDoCallNode() { - if (doCallNode == null) { - doCallNode = insert(DoCallNodeGen.create(null)); + @Specialization + protected Object forceAndCallBuiltin(VirtualFrame frame, int n, RFunction fun, RArgsValuesAndNames args) { + if (!fun.isBuiltin()) { + initPromiseHelper(); + RArgsValuesAndNames flattened = flatten(args); + // In GnuR there appears to be no error checks on n > args.length + int cnt = Math.min(flattened.getLength(), n); + for (int i = 0; i < cnt; i++) { + RPromise arg = (RPromise) args.getArgument(i); + initPromiseHelper().evaluate(frame, arg); + } } - return doCallNode; - } - @Specialization(guards = "isBuiltin(fun)") - protected Object forceAndCallBuiltin(VirtualFrame frame, @SuppressWarnings("unused") int n, RFunction fun, RArgsValuesAndNames args) { - return getDoCallNode().execute(frame, fun, args, RNull.instance); - } - - @Specialization(guards = "!isBuiltin(fun)") - protected Object forceAndCall(VirtualFrame frame, int n, RFunction fun, RArgsValuesAndNames args) { - initPromiseHelper(); - RArgsValuesAndNames flattened = flatten(args); - // In GnuR there appears to be no error checks on n > args.length - int cnt = Math.min(flattened.getLength(), n); - for (int i = 0; i < cnt; i++) { - RPromise arg = (RPromise) args.getArgument(i); - initPromiseHelper().evaluate(frame, arg); - } - return getDoCallNode().execute(frame, fun, flattened, RNull.instance); + FrameSlot frameSlot = slot.executeFrameSlot(frame); + frame.setObject(frameSlot, args); + return call.execute(frame, fun); } @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java index f6abfbfb732aab168b3a772697c8d145f103862c..9d47816e0c14736baf9d583785dcc0a327adf998 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Format.java @@ -13,16 +13,20 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL; -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.dsl.*; -import com.oracle.truffle.api.profiles.*; -import com.oracle.truffle.r.nodes.builtin.*; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.printer.AnyVectorToStringVectorWriter; import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNode; import com.oracle.truffle.r.nodes.builtin.base.printer.ValuePrinterNodeGen; -import com.oracle.truffle.r.nodes.unary.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.context.*; +import com.oracle.truffle.r.nodes.unary.CastIntegerNode; +import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; +import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.*; @@ -157,12 +161,6 @@ public abstract class Format extends RBuiltinNode { return value.materialize(); } - @Specialization - protected RStringVector format(RFactor value, RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, - RAbstractVector sciVec, RAbstractStringVector decimalMark) { - return format(value.getVector(), trimVec, digitsVec, nsmallVec, widthVec, justifyVec, naEncodeVec, sciVec, decimalMark); - } - // TruffleDSL bug - should not need multiple guards here protected void checkArgs(RLogicalVector trimVec, RIntVector digitsVec, RIntVector nsmallVec, RIntVector widthVec, RIntVector justifyVec, RLogicalVector naEncodeVec, RAbstractVector sciVec, RAbstractStringVector decimalMark) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java index 6692048fd2bec706d00e11fed9dc42404396b3b0..f69729837e082b5e82f1287bb909725f79ecfab1 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FrameFunctions.java @@ -47,16 +47,15 @@ import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.ArgumentMatcher; import com.oracle.truffle.r.nodes.function.CallArgumentsNode; -import com.oracle.truffle.r.nodes.function.GroupDispatchNode; -import com.oracle.truffle.r.nodes.function.MatchedArguments; import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseDeoptimizeFrameNode; import com.oracle.truffle.r.nodes.function.PromiseNode; import com.oracle.truffle.r.nodes.function.PromiseNode.VarArgNode; import com.oracle.truffle.r.nodes.function.PromiseNode.VarArgsPromiseNode; import com.oracle.truffle.r.nodes.function.RCallNode; -import com.oracle.truffle.r.nodes.function.UnrolledVariadicArguments; +import com.oracle.truffle.r.nodes.function.UnmatchedArguments; import com.oracle.truffle.r.nodes.function.signature.FrameDepthNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.HasSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.S3Args; import com.oracle.truffle.r.runtime.RBuiltin; @@ -260,10 +259,10 @@ public class FrameFunctions { */ RCallNode callNode = (RCallNode) RASTUtils.unwrap(call.getRep()); CallArgumentsNode callArgs = callNode.createArguments(null, false, false); - UnrolledVariadicArguments executeFlatten = callArgs.executeFlatten(cframe); - MatchedArguments matchedArgs = ArgumentMatcher.matchArguments(definition, executeFlatten, null, true); - ArgumentsSignature sig = matchedArgs.getSignature(); - RNode[] matchedArgNodes = matchedArgs.getArguments(); + ArgumentsSignature inputVarArgSignature = callArgs.containsVarArgsSymbol() ? CallArgumentsNode.getVarargsAndNames(cframe).getSignature() : null; + UnmatchedArguments executeFlatten = callArgs.unrollArguments(inputVarArgSignature); + RNode[] matchedArgNodes = ArgumentMatcher.matchArguments(definition, executeFlatten, null, true); + ArgumentsSignature sig = ((HasSignature) definition.getRootNode()).getSignature(); // expand any varargs ArrayList<RNode> nodes = new ArrayList<>(); ArrayList<String> names = new ArrayList<>(); @@ -406,7 +405,7 @@ public class FrameFunctions { if (callObj instanceof RLanguage) { RLanguage call = (RLanguage) callObj; RNode node = (RNode) RASTUtils.unwrap(call.getRep()); - if (node instanceof RCallNode || node instanceof GroupDispatchNode) { + if (node instanceof RCallNode) { return call; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java index d302e0459de0d2dc674180e6929bf20bcd547976..f69af929c49b70b59219713690c75394a39ceeac 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/GetFunctions.java @@ -41,11 +41,13 @@ import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; import com.oracle.truffle.r.nodes.function.RCallerHelper; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; +import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RList; @@ -293,7 +295,8 @@ public class GetFunctions { } MaterializedFrame callerFrame = needsCallerFrame ? frame.materialize() : null; FormalArguments formals = ((RRootNode) ifnFunc.getRootNode()).getFormalArguments(); - Object[] callArgs = argsNode.execute(ifnFunc, new RCallerHelper.Representation(ifnFunc, new Object[]{x}), callerFrame, RArguments.getDepth(frame) + 1, + RArgsValuesAndNames args = new RArgsValuesAndNames(new Object[]{x}, ArgumentsSignature.empty(1)); + Object[] callArgs = argsNode.execute(ifnFunc, new RCallerHelper.Representation(ifnFunc, args), callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame), new Object[]{x}, formals.getSignature(), null); return callCache.execute(frame, ifnFunc.getTarget(), callArgs); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java index 3cafe87eb6cba1625f4fc0f7feb186bbe4c4a558..f1dfce08df908a60d2d230e92b8b0d97f69fb3a6 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Identical.java @@ -37,18 +37,8 @@ import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.conn.RConnection; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributes; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RS4Object; -import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -273,14 +263,6 @@ public abstract class Identical extends RBuiltinNode { return identicalAttr(x, y, numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment); } - @Specialization - protected byte doInternalIdenticalGeneric(RFactor x, RFactor y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { - if (!recursive) { - controlVisibility(); - } - return doInternalIdenticalGeneric(x.getVector(), y.getVector(), numEq, singleNA, attribAsSet, ignoreBytecode, ignoreEnvironment); - } - @SuppressWarnings("unused") @Specialization protected byte doInternalIdenticalGeneric(RFunction x, RAbstractContainer y, boolean numEq, boolean singleNA, boolean attribAsSet, boolean ignoreBytecode, boolean ignoreEnvironment) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java index 5d49715dff6ec09ec62e8143229377e56aeeb2f1..ef3b28c279d6a831e30e80ec16fd847fc5f5ccb7 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Internal.java @@ -25,7 +25,6 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeCost; @@ -35,7 +34,6 @@ import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.function.RCallNode; -import com.oracle.truffle.r.nodes.function.RCallNode.LeafCallNode; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RBuiltinKind; import com.oracle.truffle.r.runtime.RError; @@ -66,8 +64,7 @@ public abstract class Internal extends RBuiltinNode { private final BranchProfile errorProfile = BranchProfile.create(); - @Child private LeafCallNode builtinCallNode; - @CompilationFinal private RFunction builtinFunction; + @Child private RNode builtinCallNode; @Specialization protected Object doInternal(@SuppressWarnings("unused") RMissing x) { @@ -101,10 +98,9 @@ public abstract class Internal extends RBuiltinNode { // .Internal function is validated CompilerDirectives.transferToInterpreterAndInvalidate(); - builtinCallNode = insert(RCallNode.createInternalCall(frame, callNode, function, name)); - builtinFunction = function; + builtinCallNode = insert(RCallNode.createInternalCall(callNode, function)); } - return builtinCallNode.execute(frame, builtinFunction, null); + return builtinCallNode.execute(frame); } private static boolean notImplemented(String name) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java index 5d2cc51956505cc994123bccef5f81f17b6bdd74..329afd4da9c4d1ed10e68d1d3d4fff2390a54c8a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsNA.java @@ -29,25 +29,14 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; 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.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RLanguage; -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.RRaw; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -@RBuiltin(name = "is.na", kind = PRIMITIVE, parameterNames = {"x"}) +@RBuiltin(name = "is.na", kind = PRIMITIVE, parameterNames = {"x"}, dispatch = RDispatch.INTERNAL_GENERIC) public abstract class IsNA extends RBuiltinNode { @Child private IsNA recursiveIsNA; @@ -172,11 +161,6 @@ public abstract class IsNA extends RBuiltinNode { return RRuntime.asLogical(RRuntime.isNA(value)); } - @Specialization - protected RLogicalVector isNA(RFactor value) { - return isNA(value.getVector()); - } - @Specialization protected byte isNA(@SuppressWarnings("unused") RRaw value) { controlVisibility(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java index 0d01a9641fc5ad1dd2bdfd3fac46295c79e0ae5a..34efd3d0d0c0ea36340c68c51bd4342d447c85cf 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/IsTypeFunctions.java @@ -30,32 +30,10 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.runtime.RBuiltin; -import com.oracle.truffle.r.runtime.RBuiltinKind; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; +import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.nodes.RNode; /** @@ -121,12 +99,6 @@ public class IsTypeFunctions { return RRuntime.LOGICAL_TRUE; } - @Specialization - protected byte isRecursive(RFactor arg) { - controlVisibility(); - return RRuntime.LOGICAL_FALSE; - } - protected boolean isListVector(RAbstractVector arg) { return arg instanceof RList; } @@ -141,6 +113,8 @@ public class IsTypeFunctions { @RBuiltin(name = "is.atomic", kind = PRIMITIVE, parameterNames = {"x"}) public abstract static class IsAtomic extends MissingAdapter { + @Child private InheritsCheckNode inheritsFactorCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR); + @Specialization protected byte isAtomic(RNull arg) { controlVisibility(); @@ -153,18 +127,16 @@ public class IsTypeFunctions { return RRuntime.LOGICAL_TRUE; } - @Specialization - protected byte isAtomic(RFactor arg) { - controlVisibility(); - return RRuntime.LOGICAL_TRUE; - } - protected static boolean isNonListVector(Object value) { return value instanceof Integer || value instanceof Double || value instanceof RComplex || value instanceof String || value instanceof RRaw || (value instanceof RAbstractVector && !(value instanceof RList)); } - @Specialization(guards = {"!isRMissing(value)", "!isRNull(value)", "!isRFactor(value)", "!isNonListVector(value)"}) + protected boolean isFactor(Object value) { + return inheritsFactorCheck.execute(value); + } + + @Specialization(guards = {"!isRMissing(value)", "!isRNull(value)", "!isFactor(value)", "!isNonListVector(value)"}) protected byte isType(Object value) { controlVisibility(); return RRuntime.LOGICAL_FALSE; @@ -403,12 +375,18 @@ public class IsTypeFunctions { @RBuiltin(name = "is.numeric", kind = PRIMITIVE, parameterNames = {"x"}) public abstract static class IsNumeric extends MissingAdapter { - @Specialization + @Specialization(guards = "!isFactor(value)") protected byte isType(RAbstractIntVector value) { controlVisibility(); return RRuntime.LOGICAL_TRUE; } + @Specialization(guards = "isFactor(value)") + protected byte isTypeFactor(RAbstractIntVector value) { + controlVisibility(); + return RRuntime.LOGICAL_FALSE; + } + @Specialization protected byte isType(RAbstractDoubleVector value) { controlVisibility(); @@ -424,6 +402,12 @@ public class IsTypeFunctions { controlVisibility(); return RRuntime.LOGICAL_FALSE; } + + @Child private InheritsCheckNode inheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR); + + protected boolean isFactor(Object o) { + return inheritsCheck.execute(o); + } } @RBuiltin(name = "is.null", kind = PRIMITIVE, parameterNames = {"x"}) diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java index c1a5a755da1c6a80ffa7b4aea176e8b8b198e506..830ee2595ed20a68d9fdf3e9c74b04211d48acc8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Lapply.java @@ -13,40 +13,34 @@ package com.oracle.truffle.r.nodes.builtin.base; import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.RootCallTarget; -import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.LoopNode; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode; import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode; +import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode; +import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNodeGen; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.LapplyNodeGen.LapplyInternalNodeGen; -import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; -import com.oracle.truffle.r.nodes.function.PromiseNode; +import com.oracle.truffle.r.nodes.control.RLengthNode; +import com.oracle.truffle.r.nodes.control.RLengthNodeGen; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.AnonymousFrameVariable; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RBuiltin; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.nodes.InternalRSyntaxNodeChildren; import com.oracle.truffle.r.runtime.nodes.RBaseNode; -import com.oracle.truffle.r.runtime.nodes.RCodeBuilder; -import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; /** * The {@code lapply} builtin. {@code lapply} is an important implicit iterator in R. This @@ -64,13 +58,9 @@ public abstract class Lapply extends RBuiltinNode { @Child private LapplyInternalNode lapply = LapplyInternalNodeGen.create(); - @Child private PromiseCheckHelperNode promiseCheck; - @Specialization protected Object lapply(VirtualFrame frame, RAbstractVector vec, RFunction fun) { - RArgsValuesAndNames optionalArgs = (RArgsValuesAndNames) RArguments.getArgument(frame, 2); - // forceVarArgs(frame, optionalArgs); - Object[] result = lapply.execute(frame, vec, fun, optionalArgs); + Object[] result = lapply.execute(frame, vec, fun); // set here else it gets overridden by the iterator evaluation controlVisibility(); return RDataFactory.createList(result, vec.getNames(attrProfiles)); @@ -78,108 +68,41 @@ public abstract class Lapply extends RBuiltinNode { public abstract static class LapplyInternalNode extends RBaseNode implements InternalRSyntaxNodeChildren { - private static final String INDEX_NAME = AnonymousFrameVariable.create("LAPPLY_ITER_INDEX"); private static final String VECTOR_ELEMENT = AnonymousFrameVariable.create("LAPPLY_VEC_ELEM"); - @Child private Length lengthNode = LengthNodeGen.create(null); + @Child private RLengthNode lengthNode = RLengthNodeGen.create(); @Child private WriteVariableNode writeVectorElement = WriteVariableNode.createAnonymous(VECTOR_ELEMENT, null, Mode.REGULAR); - @Child private WriteVariableNode writeIndex = WriteVariableNode.createAnonymous(INDEX_NAME, null, Mode.REGULAR); - @Child private RNode indexedLoadNode = createIndexedLoad(); - - public abstract Object[] execute(VirtualFrame frame, Object vector, RFunction function, RArgsValuesAndNames additionalArguments); + @Child private ExtractVectorNode extractElementNode = ExtractVectorNodeGen.create(ElementAccessMode.SUBSCRIPT, false); + @Child private RCallNode callNode = createCallNode(); - private Object[] lApplyInternal(VirtualFrame frame, Object vector, RFunction function, RCallNode callNode) { + public abstract Object[] execute(VirtualFrame frame, Object vector, RFunction function); - int length = lengthNode.executeInt(frame, vector); + @Specialization + protected Object[] cachedLApply(VirtualFrame frame, Object vector, RFunction function) { + // TODO: R switches to double if x.getLength() is greater than 2^31-1 + int length = lengthNode.executeInteger(frame, vector); Object[] result = new Object[length]; for (int i = 1; i <= length; i++) { - writeIndex.execute(frame, i); - writeVectorElement.execute(frame, indexedLoadNode.execute(frame)); + writeVectorElement.execute(frame, extractElementNode.apply(frame, vector, new Object[]{i}, RRuntime.LOGICAL_TRUE, RRuntime.LOGICAL_TRUE)); result[i - 1] = callNode.execute(frame, function); } return result; } - @SuppressWarnings("unused") - @Specialization(limit = "5", guards = {"function.getTarget() == cachedTarget", "additionalArguments.getSignature() == cachedSignature"}) - protected Object[] cachedLApply(VirtualFrame frame, Object vector, RFunction function, RArgsValuesAndNames additionalArguments, // - @Cached("function.getTarget()") RootCallTarget cachedTarget, // - @Cached("additionalArguments.getSignature()") ArgumentsSignature cachedSignature, // - @Cached("createCallNode(additionalArguments)") RCallNode callNode) { - return lApplyInternal(frame, vector, function, callNode); - } - - @Specialization(contains = "cachedLApply") - protected Object[] genericLApply(VirtualFrame frame, Object vector, RFunction function, RArgsValuesAndNames additionalArguments) { - - // TODO: implement more efficiently (how much does it matter considering that there is - // cached version?); previous comment here implied that having RCallNode executing with - // an evaluated RArgsValuesAndNames would help - return lApplyInternal(frame, vector, function, createCallNode(additionalArguments)); - } - - private static RNode createIndexedLoad() { - RCodeBuilder<RSyntaxNode> builder = RContext.getASTBuilder(); - RSyntaxNode receiver = builder.lookup(RSyntaxNode.INTERNAL, "X", false); - RSyntaxNode index = builder.lookup(RSyntaxNode.INTERNAL, INDEX_NAME, false); - RSyntaxNode access = builder.lookup(RSyntaxNode.INTERNAL, "[[", true); - return builder.call(RSyntaxNode.INTERNAL, access, receiver, index).asRNode(); - } - /** * Creates the {@link RCallNode} for this target and {@code varArgs}. - * - * @param additionalArguments may be {@link RMissing#instance} to indicate empty "..."! */ - @TruffleBoundary - protected RCallNode createCallNode(RArgsValuesAndNames additionalArguments) { - /* TODO: R switches to double if x.getLength() is greater than 2^31-1 */ - - ReadVariableNode readVector = ReadVariableNode.create(VECTOR_ELEMENT); - - // The remaining parameters are passed from {@code ...}. The call node will take - // care of matching. - RSyntaxNode[] args; - String[] names; - if (additionalArguments.isEmpty()) { // == null || (varArgs.length() == 1 && - // varArgs.getValue(0) - // == RMissing.instance)) { - args = new RSyntaxNode[]{readVector}; - names = new String[]{null}; - } else { - // Insert expressions found inside "..." as arguments - args = new RSyntaxNode[additionalArguments.getLength() + 1]; - args[0] = readVector; - Object[] varArgsValues = additionalArguments.getArguments(); - for (int i = 0; i < additionalArguments.getLength(); i++) { - args[i + 1] = (RSyntaxNode) wrapVarArgValue(varArgsValues[i], i); - - } - names = new String[additionalArguments.getLength() + 1]; - names[0] = null; - for (int i = 0; i < additionalArguments.getLength(); i++) { - String name = additionalArguments.getSignature().getName(i); - if (name != null && !name.isEmpty()) { - // change "" to null - names[i + 1] = name; - } - } - } - ArgumentsSignature argsSig = ArgumentsSignature.get(names); - // Errors can be thrown from the modified call so a SourceSection is required - return RCallNode.createCall(createCallSourceSection(), null, argsSig, args); + protected RCallNode createCallNode() { + CompilerAsserts.neverPartOfCompilation(); + + ReadVariableNode readVector = ReadVariableNode.createSilent(VECTOR_ELEMENT, RType.Any); + ReadVariableNode readArgs = ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any); + + return RCallNode.createCall(createCallSourceSection(), null, ArgumentsSignature.get(null, "..."), readVector, readArgs); } } static SourceSection createCallSourceSection() { return CALL_SOURCE.createSection("", 0, CALL_SOURCE.getLength()); } - - private static RNode wrapVarArgValue(Object varArgValue, int varArgIndex) { - if (varArgValue instanceof RPromise) { - return PromiseNode.createVarArg(varArgIndex); - } else { - return ConstantNode.create(varArgValue); - } - } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java index 24c6e65e3f655e2e3378c8b03387308bae5c2af4..0211b1e052040aa33a31e1f497a07d163310034a 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Match.java @@ -33,25 +33,15 @@ import com.oracle.truffle.api.profiles.BranchProfile; 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.helpers.InheritsCheckNode; import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.closures.RClosures; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.ops.na.NACheck; import com.oracle.truffle.r.runtime.ops.na.NAProfile; @@ -116,22 +106,22 @@ public abstract class Match extends RBuiltinNode { return RDataFactory.createIntVector(data, naCheck.neverSeenNA()); } - @Specialization - protected Object match(RFactor x, RFactor table, RAbstractIntVector nomatchObj, Object incomparables) { - naCheck.enable(x.getVector()); - naCheck.enable(table.getVector()); + @Specialization(guards = {"isFactor(x)", "isFactor(table)"}) + protected Object matchFactor(RAbstractIntVector x, RAbstractIntVector table, RAbstractIntVector nomatchObj, Object incomparables) { + naCheck.enable(x); + naCheck.enable(table); return matchRecursive(RClosures.createFactorToVector(x, true, attrProfiles), RClosures.createFactorToVector(table, true, attrProfiles), nomatchObj, incomparables); } - @Specialization - protected Object match(RFactor x, RAbstractVector table, RAbstractIntVector nomatchObj, Object incomparables) { - naCheck.enable(x.getVector()); + @Specialization(guards = {"isFactor(x)", "!isFactor(table)"}) + protected Object matchFactor(RAbstractIntVector x, RAbstractVector table, RAbstractIntVector nomatchObj, Object incomparables) { + naCheck.enable(x); return matchRecursive(RClosures.createFactorToVector(x, true, attrProfiles), table, nomatchObj, incomparables); } - @Specialization - protected Object match(RAbstractVector x, RFactor table, RAbstractIntVector nomatchObj, Object incomparables) { - naCheck.enable(table.getVector()); + @Specialization(guards = {"!isFactor(x)", "isFactor(table)"}) + protected Object matchFactor(RAbstractVector x, RAbstractIntVector table, RAbstractIntVector nomatchObj, Object incomparables) { + naCheck.enable(table); return matchRecursive(x, RClosures.createFactorToVector(table, true, attrProfiles), nomatchObj, incomparables); } @@ -514,6 +504,12 @@ public abstract class Match extends RBuiltinNode { return table.getElementClass() == String.class; } + @Child private InheritsCheckNode factorInheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR); + + protected boolean isFactor(Object o) { + return factorInheritsCheck.execute(o); + } + private static int[] initResult(int length, int nomatch) { int[] result = new int[length]; Arrays.fill(result, nomatch); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java index d22d7cc5de0037762f2fc70e726cb5d80155aa12..a90acdd3f05996d26b537da99104d3c44df84fc9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatchFun.java @@ -39,8 +39,8 @@ import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.MatchFunNodeGen.MatchFunInternalNodeGen; +import com.oracle.truffle.r.nodes.function.GetCallerFrameNode; import com.oracle.truffle.r.nodes.function.PromiseHelperNode; -import com.oracle.truffle.r.nodes.function.signature.GetCallerFrameNode; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RError; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java index 61b1c873ab9292923225d81a7b0c6ae5e159ff7d..6089d1efca02f36a976f96ecce2eb05cbeea04dd 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Mean.java @@ -28,6 +28,7 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RBuiltin; +import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; @@ -36,7 +37,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; -@RBuiltin(name = "mean", kind = INTERNAL, parameterNames = {"x"}) +@RBuiltin(name = "mean", kind = INTERNAL, parameterNames = {"x"}, dispatch = RDispatch.INTERNAL_GENERIC) public abstract class Mean extends RBuiltinNode { private final BranchProfile emptyProfile = BranchProfile.create(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java index 2fd7dcd2d573eb429624b06442c8aed04d77a155..9fb021ee9d1d4a05c1ecb5baefbe32bcec831ad8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/NChar.java @@ -29,6 +29,7 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; import com.oracle.truffle.r.nodes.unary.ConversionFailedException; @@ -38,7 +39,6 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @@ -49,6 +49,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public abstract class NChar extends RBuiltinNode { @Child private CastStringNode convertString; + @Child private InheritsCheckNode factorInheritsCheck; private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @@ -127,9 +128,15 @@ public abstract class NChar extends RBuiltinNode { @Fallback protected RIntVector nchar(Object obj, Object type, Object allowNA, Object keepNA) { controlVisibility(); - if (obj instanceof RFactor) { + if (factorInheritsCheck == null) { + CompilerDirectives.transferToInterpreter(); + factorInheritsCheck = insert(new InheritsCheckNode(RRuntime.CLASS_FACTOR)); + } + + if (factorInheritsCheck.execute(obj)) { throw RError.error(this, RError.Message.REQUIRES_CHAR_VECTOR, "nchar"); } + if (obj instanceof RAbstractVector) { RAbstractVector vector = (RAbstractVector) obj; int len = vector.getLength(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java index d4610cda7c2bb5c9a4ec460a82b86bb885ce2262..80c47dc37cab89037064f954c443331d0d1b3293 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/PrettyPrinterNode.java @@ -37,56 +37,20 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.access.ConstantNode; -import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrettyPrinterSingleListElementNodeGen; -import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrettyPrinterSingleVectorElementNodeGen; -import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrintDimNodeGen; -import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrintVector2DimNodeGen; -import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.PrintVectorMultiDimNodeGen; +import com.oracle.truffle.r.nodes.builtin.base.PrettyPrinterNodeGen.*; import com.oracle.truffle.r.nodes.function.FormalArguments; +import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; +import com.oracle.truffle.r.nodes.helpers.RFactorNodes; import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; -import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RArguments; -import com.oracle.truffle.r.runtime.RDeparse; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.conn.SocketConnections; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RAttributes; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; -import com.oracle.truffle.r.runtime.data.RBuiltinDescriptor; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RPromise; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RS4Object; -import com.oracle.truffle.r.runtime.data.RString; -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.closures.RClosures; import com.oracle.truffle.r.runtime.data.closures.RFactorToStringVectorClosure; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -1185,7 +1149,7 @@ public abstract class PrettyPrinterNode extends RNode { } @TruffleBoundary - @Specialization + @Specialization(guards = "!isFactor(operand)") protected String prettyPrintListElement(RAbstractVector operand, Object listElementName, byte quote, byte right) { return prettyPrintSingleElement(operand, listElementName, quote, right); } @@ -1220,10 +1184,22 @@ public abstract class PrettyPrinterNode extends RNode { return prettyPrintSingleElement(operand, listElementName, quote, right); } + @Child InheritsCheckNode factorInheritsCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR); + @Child RFactorNodes.GetLevels getFactorLevels; + + protected boolean isFactor(Object o) { + return this.factorInheritsCheck.execute(o); + } + // TODO: this should be handled by an S3 function - @Specialization - protected String prettyPrintListElement(RFactor operand, Object listElementName, byte quote, byte right) { - RVector vec = operand.getLevels(attrProfiles); + @Specialization(guards = "isFactor(factor)") + protected String prettyPrintListElement(RAbstractIntVector factor, Object listElementName, byte quote, byte right) { + if (getFactorLevels == null) { + CompilerDirectives.transferToInterpreter(); + getFactorLevels = insert(new RFactorNodes.GetLevels()); + } + + RVector vec = getFactorLevels.execute(factor); String[] strings; if (vec == null) { strings = new String[0]; @@ -1234,11 +1210,11 @@ public abstract class PrettyPrinterNode extends RNode { strings[i] = (String) castStringNode.executeString(vec.getDataAtAsObject(i)); } } - return formatLevelStrings(operand, listElementName, right, vec, strings); + return formatLevelStrings(factor, listElementName, right, vec, strings); } @TruffleBoundary - private String formatLevelStrings(RFactor operand, Object listElementName, byte right, RVector vec, String[] strings) { + private String formatLevelStrings(RAbstractIntVector operand, Object listElementName, byte right, RVector vec, String[] strings) { StringBuilder sb = new StringBuilder(prettyPrintSingleElement(RClosures.createFactorToVector(operand, true, attrProfiles), listElementName, RRuntime.LOGICAL_FALSE, right)); sb.append("\nLevels:"); if (vec != 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 eb19a426e9033c2025c18d6f82d1476f51c1babf..cc1f2ce326cfc7298fdbe351ce68f1af6115875c 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 @@ -26,22 +26,16 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.PRIMITIVE; import java.util.Arrays; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.BranchProfile; 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.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.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -66,27 +60,17 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractVector; * </ul> * </ol> */ -@RBuiltin(name = "rep", kind = PRIMITIVE, parameterNames = {"x", "times", "length.out", "each"}) +@RBuiltin(name = "rep", kind = PRIMITIVE, parameterNames = {"x", "times", "length.out", "each"}, dispatch = RDispatch.INTERNAL_GENERIC) public abstract class Repeat extends RBuiltinNode { protected abstract Object execute(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each); - @Child private Repeat repeatRecursive; - private final ConditionProfile lengthOutOrTimes = ConditionProfile.createBinaryProfile(); private final BranchProfile errorBranch = BranchProfile.create(); private final ConditionProfile oneTimeGiven = ConditionProfile.createBinaryProfile(); private final ConditionProfile replicateOnce = ConditionProfile.createBinaryProfile(); private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - private Object repeatRecursive(RAbstractVector x, RAbstractIntVector times, int lengthOut, int each) { - if (repeatRecursive == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - repeatRecursive = insert(RepeatNodeGen.create(null)); - } - return repeatRecursive.execute(x, times, lengthOut, each); - } - @Override public Object[] getDefaultParameterValues() { return new Object[]{RMissing.instance, 1, RRuntime.INT_NA, 1}; @@ -174,13 +158,6 @@ public abstract class Repeat extends RBuiltinNode { } } - @Specialization - protected RAbstractContainer rep(RFactor x, RAbstractIntVector times, int lengthOut, int each) { - RVector vec = (RVector) repeatRecursive(x.getVector(), times, lengthOut, each); - vec.setAttr(RRuntime.LEVELS_ATTR_KEY, x.getLevels(attrProfiles)); - return RVector.setVectorClassAttr(vec, x.getClassAttr(attrProfiles), null); - } - /** * Prepare the input vector by replicating its elements. */ diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java index e1d45d77d9521b86cf4245a8d4143d3f6914d04d..0edc9d0761c24c95455103fda2bc949061b6fb2c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java @@ -26,27 +26,18 @@ import static com.oracle.truffle.r.runtime.RBuiltinKind.INTERNAL; import java.util.Arrays; -import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastStringNode; -import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; +import com.oracle.truffle.r.nodes.helpers.RFactorNodes; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; /** - * The {@code split} internal. + * The {@code split} internal. Internal version of 'split' is invoked from 'split.default' function + * implemented in R, which makes sure that the second argument is always a R factor. * * TODO Can we find a way to efficiently write the specializations as generics? The code is * identical except for the argument type. @@ -54,18 +45,23 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; @RBuiltin(name = "split", kind = INTERNAL, parameterNames = {"x", "f"}) public abstract class Split extends RBuiltinNode { - @Child private CastStringNode castString; + @Child private RFactorNodes.GetLevels getLevelNode = new RFactorNodes.GetLevels(); private final ConditionProfile noStringLevels = ConditionProfile.createBinaryProfile(); - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); private static final int INITIAL_SIZE = 5; private static final int SCALE_FACTOR = 2; + public static class SplitTemplate { + private int[] collectResulSize; + private int nLevels; + } + @Specialization - protected RList split(RAbstractIntVector x, RFactor f) { - int[] factor = f.getVector().getDataWithoutCopying(); - final int nLevels = f.getNLevels(attrProfiles); + protected RList split(RAbstractIntVector x, RAbstractIntVector f) { + int[] factor = f.materialize().getDataWithoutCopying(); + RStringVector names = getLevelNode.execute(f); + final int nLevels = getNLevels(names); // initialise result arrays int[][] collectResults = new int[nLevels][]; @@ -91,13 +87,14 @@ public abstract class Split extends RBuiltinNode { results[i] = RDataFactory.createIntVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), x.isComplete()); } - return RDataFactory.createList(results, makeNames(f)); + return RDataFactory.createList(results, names); } @Specialization - protected RList split(RAbstractDoubleVector x, RFactor f) { - int[] factor = f.getVector().getDataWithoutCopying(); - final int nLevels = f.getNLevels(attrProfiles); + protected RList split(RAbstractDoubleVector x, RAbstractIntVector f) { + int[] factor = f.materialize().getDataWithoutCopying(); + RStringVector names = getLevelNode.execute(f); + final int nLevels = getNLevels(names); // initialise result arrays double[][] collectResults = new double[nLevels][]; @@ -123,13 +120,14 @@ public abstract class Split extends RBuiltinNode { results[i] = RDataFactory.createDoubleVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), RDataFactory.COMPLETE_VECTOR); } - return RDataFactory.createList(results, makeNames(f)); + return RDataFactory.createList(results, names); } @Specialization - protected RList split(RAbstractStringVector x, RFactor f) { - int[] factor = f.getVector().getDataWithoutCopying(); - final int nLevels = f.getNLevels(attrProfiles); + protected RList split(RAbstractStringVector x, RAbstractIntVector f) { + int[] factor = f.materialize().getDataWithoutCopying(); + RStringVector names = getLevelNode.execute(f); + final int nLevels = getNLevels(names); // initialise result arrays String[][] collectResults = new String[nLevels][]; @@ -155,13 +153,14 @@ public abstract class Split extends RBuiltinNode { results[i] = RDataFactory.createStringVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), RDataFactory.COMPLETE_VECTOR); } - return RDataFactory.createList(results, makeNames(f)); + return RDataFactory.createList(results, names); } @Specialization - protected RList split(RAbstractLogicalVector x, RFactor f) { - int[] factor = f.getVector().getDataWithoutCopying(); - final int nLevels = f.getNLevels(attrProfiles); + protected RList split(RAbstractLogicalVector x, RAbstractIntVector f) { + int[] factor = f.materialize().getDataWithoutCopying(); + RStringVector names = getLevelNode.execute(f); + final int nLevels = getNLevels(names); // initialise result arrays byte[][] collectResults = new byte[nLevels][]; @@ -187,20 +186,10 @@ public abstract class Split extends RBuiltinNode { results[i] = RDataFactory.createLogicalVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), x.isComplete()); } - return RDataFactory.createList(results, makeNames(f)); + return RDataFactory.createList(results, names); } - private RStringVector makeNames(RFactor f) { - RVector levels = f.getLevels(attrProfiles); - if (noStringLevels.profile(!(levels instanceof RStringVector))) { - if (castString == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castString = insert(CastStringNodeGen.create(false, false, false, false)); - } - RStringVector slevels = (RStringVector) castString.executeString(f.getLevels(attrProfiles)); - return RDataFactory.createStringVector(slevels.getDataWithoutCopying(), RDataFactory.COMPLETE_VECTOR); - } else { - return RDataFactory.createStringVector(((RStringVector) levels).getDataCopy(), RDataFactory.COMPLETE_VECTOR); - } + private int getNLevels(RStringVector levels) { + return levels != null ? levels.getLength() : 0; } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java index e10fb7d5ba8a50dc897dbc49c3494301dfbbbfa5..829cc8dcc93baee18b08e6ff57b7def021e0eda8 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Tabulate.java @@ -22,7 +22,6 @@ import com.oracle.truffle.r.runtime.RBuiltinKind; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -55,11 +54,6 @@ public abstract class Tabulate extends RBuiltinNode { return RDataFactory.createIntVector(ans, RDataFactory.COMPLETE_VECTOR); } - @Specialization - protected RIntVector tabulate(RFactor bin, int nBins) { - return tabulate(bin.getVector(), nBins); - } - @SuppressWarnings("unused") @Fallback @TruffleBoundary diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java index 22fc1a59678a9cd65c782a19ceba5eaec0d77c2b..92572424d17d380f3828b5d4a8bda9ffa9e41b49 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UnClass.java @@ -20,7 +20,6 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RS4Object; import com.oracle.truffle.r.runtime.data.RVector; @@ -48,19 +47,6 @@ public abstract class UnClass extends RBuiltinNode { return arg; } - @Specialization - @TruffleBoundary - protected Object unClass(RFactor arg) { - controlVisibility(); - RFactor resultFactor = arg; - if (!resultFactor.isTemporary()) { - resultFactor = resultFactor.copy(); - assert resultFactor.isTemporary(); - resultFactor.incRefCount(); - } - return RVector.setVectorClassAttr(resultFactor.getVector(), null, arg); - } - @Specialization protected Object unClass(RLanguage arg) { controlVisibility(); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java index 5f954d44f38633e733a4005c6b6b89a205957053..7e7efef62fbe2f3ec3e406d0a44acbf323668797 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Unique.java @@ -35,27 +35,8 @@ import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RIntVector; -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.RRaw; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; // Implements default S3 method @RBuiltin(name = "unique", kind = INTERNAL, parameterNames = {"x", "incomparables", "fromLast", "nmax", "..."}) @@ -86,11 +67,6 @@ public abstract class Unique extends RBuiltinNode { return vec; } - @Specialization - protected RAbstractContainer doUnique(VirtualFrame frame, RFactor factor, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { - return uniqueRecursive(frame, factor.getVector(), incomparables, fromLast, nmax, vararg); - } - @SuppressWarnings("unused") @Specialization protected RStringVector doUnique(RAbstractStringVector vec, byte incomparables, byte fromLast, Object nmax, RArgsValuesAndNames vararg) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java index 16426dd276fd6dcdbc7d0e2dc9e5a5ee15ca25a7..0d3d387ae3876196022c19cb9b30c9986a3764fa 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateLevels.java @@ -14,24 +14,21 @@ package com.oracle.truffle.r.nodes.builtin.base; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RInvisibleBuiltinNode; -import com.oracle.truffle.r.nodes.unary.CastStringNode; -import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; import com.oracle.truffle.r.nodes.unary.CastToVectorNode; import com.oracle.truffle.r.nodes.unary.CastToVectorNodeGen; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RBuiltinKind; +import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -@RBuiltin(name = "levels<-", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"x", "value"}) +@RBuiltin(name = "levels<-", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"x", "value"}, dispatch = RDispatch.INTERNAL_GENERIC) public abstract class UpdateLevels extends RInvisibleBuiltinNode { @Child private CastToVectorNode castVector; - @Child private CastStringNode castString; private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); @@ -43,14 +40,6 @@ public abstract class UpdateLevels extends RInvisibleBuiltinNode { return (RAbstractVector) castVector.execute(value); } - private Object castString(Object operand) { - if (castString == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - castString = insert(CastStringNodeGen.create(false, true, false, false)); - } - return castString.execute(operand); - } - @Specialization protected RAbstractVector updateLevels(RAbstractVector vector, @SuppressWarnings("unused") RNull levels) { controlVisibility(); @@ -67,20 +56,6 @@ public abstract class UpdateLevels extends RInvisibleBuiltinNode { return v; } - @Specialization - protected RFactor updateLevels(RFactor factor, @SuppressWarnings("unused") RNull levels) { - controlVisibility(); - factor.getVector().removeAttr(attrProfiles, RRuntime.LEVELS_ATTR_KEY); - return factor; - } - - @Specialization(guards = "levelsNotNull(levels)") - protected RFactor updateLevels(RFactor factor, Object levels) { - controlVisibility(); - factor.getVector().setAttr(RRuntime.LEVELS_ATTR_KEY, castString(castVector(levels))); - return factor; - } - protected boolean levelsNotNull(Object levels) { return levels != RNull.instance; } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java index c8d3bee04b3018e0ad0081c02e1acf441bacd3b0..f7af4bdaca193ced16ae3d395051cf139ed7f589 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/VApply.java @@ -43,12 +43,10 @@ import com.oracle.truffle.r.nodes.unary.CastLogicalNode; import com.oracle.truffle.r.nodes.unary.CastLogicalNodeGen; import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; -import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -132,14 +130,13 @@ public abstract class VApply extends RBuiltinNode { @Specialization protected Object vapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, Object funValue, byte useNames) { - RArgsValuesAndNames optionalArgs = (RArgsValuesAndNames) RArguments.getArgument(frame, 3); - RVector result = delegateToLapply(frame, vec, fun, funValue, useNames, optionalArgs); + RVector result = delegateToLapply(frame, vec, fun, funValue, useNames); // set here else it gets overridden by the iterator evaluation controlVisibility(); return result; } - private RVector delegateToLapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, Object funValueArg, byte useNames, RArgsValuesAndNames optionalArgs) { + private RVector delegateToLapply(VirtualFrame frame, RAbstractVector vec, RFunction fun, Object funValueArg, byte useNames) { /* * The implementation is complicated by the existence of scalar length 1 vectors (e.g. * Integer) and concrete length 1 vectors (e.g. RIntVector), as either form can occur in @@ -155,7 +152,7 @@ public abstract class VApply extends RBuiltinNode { int funValueVecLen = funValueVec.getLength(); RVector vecMat = vec.materialize(); - Object[] applyResult = doApply.execute(frame, vecMat, fun, optionalArgs); + Object[] applyResult = doApply.execute(frame, vecMat, fun); RVector result = null; boolean applyResultZeroLength = applyResult.length == 0; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java index b92ab79ade065e95f2a6724b8ec6f46f0190c861..595240c6942ddc969e97d1170dca5ceced16a96d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/FactorPrinter.java @@ -29,9 +29,10 @@ import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.closures.RClosures; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; -final class FactorPrinter extends AbstractValuePrinter<RFactor> { +final class FactorPrinter extends AbstractValuePrinter<RAbstractIntVector> { static final FactorPrinter INSTANCE = new FactorPrinter(); @@ -42,28 +43,30 @@ final class FactorPrinter extends AbstractValuePrinter<RFactor> { private static RAttributeProfiles dummyAttrProfiles = RAttributeProfiles.create(); @Override - protected void printValue(RFactor operand, PrintContext printCtx) throws IOException { - // TODO: this should be handled by an S3 function - RVector vec = operand.getLevels(dummyAttrProfiles); + protected void printValue(RAbstractIntVector operand, PrintContext printCtx) throws IOException { + // TODO: this should be handled by an S3 function. Should it? For example, in C code for + // split, there is direct call to getAttrib. This should be refactored to use + // AttributeAccess node or even Factor.GetLevels node. The same holds for the access + RVector levels = RFactor.getLevels(operand); String[] strings; - if (vec == null) { + if (levels == null) { strings = new String[0]; } else { - strings = new String[vec.getLength()]; - for (int i = 0; i < vec.getLength(); i++) { - strings[i] = printCtx.printerNode().castString(vec.getDataAtAsObject(i)); + strings = new String[levels.getLength()]; + for (int i = 0; i < levels.getLength(); i++) { + strings[i] = printCtx.printerNode().castString(levels.getDataAtAsObject(i)); } } - RAbstractVector v = RClosures.createFactorToVector(operand, true, dummyAttrProfiles); + RAbstractVector v = RClosures.createFactorToVector(operand, true, levels); PrintContext vectorPrintCtx = printCtx.cloneContext(); vectorPrintCtx.parameters().setQuote(false); ValuePrinters.INSTANCE.println(v, vectorPrintCtx); final PrintWriter out = printCtx.output(); out.print("Levels:"); - if (vec != null) { - for (int i = 0; i < vec.getLength(); i++) { + if (levels != null) { + for (int i = 0; i < levels.getLength(); i++) { out.print(" "); out.print(strings[i]); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java index 8e4fb77736917b561ad1bf6339037598e0993758..fc0f02ef92c2aeac9cacac2dca11e249d2b8c94b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/printer/ValuePrinters.java @@ -23,15 +23,8 @@ package com.oracle.truffle.r.nodes.builtin.base.printer; import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RS4Object; -import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -59,7 +52,6 @@ final class ValuePrinters implements ValuePrinter<Object> { printers.put(RExternalPtr.class, ExternalPtrPrinter.INSTANCE); printers.put(RS4Object.class, S4ObjectPrinter.INSTANCE); printers.put(RPairList.class, PairListPrinter.INSTANCE); - printers.put(RFactor.class, FactorPrinter.INSTANCE); } @SuppressWarnings({"rawtypes", "unchecked"}) @@ -74,7 +66,9 @@ final class ValuePrinters implements ValuePrinter<Object> { Object x = printCtx.printerNode().boxPrimitive(v); ValuePrinter printer = printers.get(x.getClass()); if (printer == null) { - if (x instanceof RAbstractStringVector) { + if (x instanceof RAbstractIntVector && ((RAttributable) x).hasClass(RRuntime.CLASS_FACTOR)) { + printer = FactorPrinter.INSTANCE; + } else if (x instanceof RAbstractStringVector) { printer = StringVectorPrinter.INSTANCE; } else if (x instanceof RAbstractDoubleVector) { printer = DoubleVectorPrinter.INSTANCE; @@ -91,7 +85,7 @@ final class ValuePrinters implements ValuePrinter<Object> { } else if (x instanceof REnvironment) { printer = EnvironmentPrinter.INSTANCE; } else { - RInternalError.shouldNotReachHere(); + RInternalError.shouldNotReachHere("unexpected type: " + (x == null ? "null" : x.getClass())); } } printer.print(x, printCtx); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRCompile.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRCompile.java deleted file mode 100644 index 5b8b725e6e32e02c83676aca334a22d06e3c60b2..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRCompile.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2013, 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.builtin.fastr; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.util.concurrent.Future; - -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.dsl.Fallback; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.runtime.RBuiltin; -import com.oracle.truffle.r.runtime.RBuiltinKind; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RMissing; - -@RBuiltin(name = ".fastr.compile", kind = RBuiltinKind.PRIMITIVE, parameterNames = {"func", "background"}) -public abstract class FastRCompile extends RBuiltinNode { - - private static final class Compiler { - private final Class<?> optimizedCallTarget; - private final Class<?> graalTruffleRuntime; - private final Method submitForCompilationMethod; - private final Method finishCompilationMethod; - - private Compiler() { - try { - optimizedCallTarget = Class.forName("com.oracle.graal.truffle.OptimizedCallTarget", false, Truffle.getRuntime().getClass().getClassLoader()); - graalTruffleRuntime = Class.forName("com.oracle.graal.truffle.GraalTruffleRuntime", false, Truffle.getRuntime().getClass().getClassLoader()); - submitForCompilationMethod = graalTruffleRuntime.getDeclaredMethod("submitForCompilation", optimizedCallTarget); - finishCompilationMethod = graalTruffleRuntime.getDeclaredMethod("finishCompilation", optimizedCallTarget, Future.class, boolean.class); - } catch (ClassNotFoundException | IllegalArgumentException | NoSuchMethodException | SecurityException e) { - throw Utils.fail("fastr.compile: failed to find 'compile' method"); - } - } - - static Compiler getCompiler() { - if (System.getProperty("fastr.truffle.compile", "true").equals("true") && Truffle.getRuntime().getName().contains("Graal")) { - return new Compiler(); - } else { - return null; - } - } - - boolean compile(CallTarget callTarget, boolean background) throws InvocationTargetException, IllegalAccessException { - if (optimizedCallTarget.isInstance(callTarget)) { - Future<?> submitted = (Future<?>) submitForCompilationMethod.invoke(Truffle.getRuntime(), callTarget); - finishCompilationMethod.invoke(Truffle.getRuntime(), callTarget, submitted, background); - return true; - } else { - return false; - } - } - } - - private static final Compiler compiler = Compiler.getCompiler(); - - @Override - public Object[] getDefaultParameterValues() { - return new Object[]{RMissing.instance, RRuntime.LOGICAL_FALSE}; - } - - @Specialization - protected byte compileFunction(RFunction function, byte background) { - controlVisibility(); - if (compiler != null) { - try { - if (compiler.compile(function.getTarget(), background == RRuntime.LOGICAL_TRUE)) { - return RRuntime.LOGICAL_TRUE; - } - } catch (InvocationTargetException | IllegalAccessException e) { - throw RError.error(this, RError.Message.GENERIC, e.toString()); - } - } else { - throw RError.error(this, RError.Message.GENERIC, "fastr.compile not supported in this environment"); - } - return RRuntime.LOGICAL_FALSE; - } - - @SuppressWarnings("unused") - @Fallback - protected Object fallback(Object a1, Object a2) { - throw RError.error(this, RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS); - } -} diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java index 34b9ab3141c55b3c626ea9f0f4e9730a52c8a580..cbfb84aa0fbfd4c31bff273cdec73584d94342c2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/BrowserInteractNode.java @@ -147,10 +147,10 @@ public abstract class BrowserInteractNode extends RNode { } private static String getSrcinfo(RStringVector element) { - Object srcref = element.getAttribute(RRuntime.R_SRCREF); + Object srcref = element.getAttr(RRuntime.R_SRCREF); if (srcref != null) { RIntVector lloc = (RIntVector) srcref; - Object srcfile = lloc.getAttribute(RRuntime.R_SRCFILE); + Object srcfile = lloc.getAttr(RRuntime.R_SRCFILE); if (srcfile != null) { REnvironment env = (REnvironment) srcfile; return " at " + RRuntime.asString(env.get(RSrcref.SrcrefFields.filename.name())) + "#" + lloc.getDataAt(0); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java index d7383de899da867de3a815ae9a7c125849030626..1418ab39e90504bb45fd8867c7bec30ed9562d02 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/helpers/TraceHandling.java @@ -170,7 +170,7 @@ public class TraceHandling { if (!disabled()) { int depth = RArguments.getDepth(frame); try { - for (int i = 0; i < depth; i++) { + for (int i = 0; i < depth - 1; i++) { outputHandler.writeString(" ", false); } String callString = getCallSource(frame); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java index 8bd5d1b65a89c763abe6ee2c33fde7567445e887..da6c3c3242a5235a27cb6416132d5626e25bf949 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTBuilder.java @@ -44,7 +44,6 @@ import com.oracle.truffle.r.nodes.control.WhileNode; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.nodes.function.FunctionDefinitionNode; import com.oracle.truffle.r.nodes.function.FunctionExpressionNode; -import com.oracle.truffle.r.nodes.function.GroupDispatchNode; import com.oracle.truffle.r.nodes.function.PostProcessArgumentsNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.nodes.function.SaveArgumentsNode; @@ -53,15 +52,13 @@ import com.oracle.truffle.r.nodes.unary.GetNonSharedNodeGen; import com.oracle.truffle.r.parser.tools.EvaluatedArgumentsVisitor; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.FastROptions; -import com.oracle.truffle.r.runtime.RDispatch; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.FastPathFactory; -import com.oracle.truffle.r.runtime.data.RBuiltinDescriptor; import com.oracle.truffle.r.runtime.data.RComplex; import com.oracle.truffle.r.runtime.data.REmpty; +import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RSymbol; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -133,11 +130,6 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { return new NextNode(source); } } else if (args.size() == 1) { - // handle unary arithmetics, for the time being - RBuiltinDescriptor builtin = RContext.lookupBuiltinDescriptor(symbol); - if (builtin != null && builtin.getDispatch() == RDispatch.OPS_GROUP_GENERIC) { - return GroupDispatchNode.create(symbol, source, ArgumentsSignature.empty(1), args.get(0).value); - } switch (symbol) { case "repeat": return WhileNode.create(source, ConstantNode.create(RRuntime.LOGICAL_TRUE), args.get(0).value, true); @@ -145,11 +137,6 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { return args.get(0).value; } } else if (args.size() == 2) { - // handle binary arithmetics, for the time being - RBuiltinDescriptor builtin = RContext.lookupBuiltinDescriptor(symbol); - if (builtin != null && builtin.getDispatch() == RDispatch.OPS_GROUP_GENERIC) { - return GroupDispatchNode.create(symbol, source, ArgumentsSignature.empty(2), args.get(0).value, args.get(1).value); - } switch (symbol) { case "while": return WhileNode.create(source, args.get(0).value, args.get(1).value, false); @@ -190,13 +177,6 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { arg -> (arg.value == null && arg.name == null) ? ConstantNode.create(arg.source == null ? RSyntaxNode.SOURCE_UNAVAILABLE : arg.source, REmpty.instance) : arg.value).toArray( RSyntaxNode[]::new); - if (lhs instanceof RSyntaxLookup) { - String symbol = ((RSyntaxLookup) lhs).getIdentifier(); - RBuiltinDescriptor builtin = RContext.lookupBuiltinDescriptor(symbol); - if (builtin != null && builtin.getDispatch().isGroupGeneric()) { - return GroupDispatchNode.create(symbol, source, signature, nodes); - } - } return RCallNode.createCall(source, lhs.asRNode(), signature, nodes); } @@ -457,8 +437,6 @@ public final class RASTBuilder implements RCodeBuilder<RSyntaxNode> { @Override public RSyntaxNode constant(SourceSection source, Object value) { - assert value instanceof Byte || value instanceof Integer || value instanceof Double || value instanceof RComplex || value instanceof String || value instanceof RNull || - value instanceof REmpty || value instanceof RSymbol || value instanceof RAbstractVector : value.getClass(); if (value instanceof String && !RRuntime.isNA((String) value)) { return ConstantNode.create(source, ((String) value).intern()); } else { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java index bd7831a895ffe8d55b70a95654b9aed682441073..20e39ffd491a6b5d87a7874a30c066370e140772 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RASTUtils.java @@ -22,7 +22,6 @@ */ package com.oracle.truffle.r.nodes; -import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.VirtualFrame; @@ -34,15 +33,11 @@ import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.ReadVariadicComponentNode; import com.oracle.truffle.r.nodes.access.variables.NamedRNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.function.CallArgumentsNode; -import com.oracle.truffle.r.nodes.function.GroupDispatchNode; import com.oracle.truffle.r.nodes.function.PromiseNode.VarArgNode; import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.nodes.function.WrapArgumentBaseNode; import com.oracle.truffle.r.nodes.function.WrapArgumentNode; -import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RDeparse; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDataFactory; @@ -67,6 +62,7 @@ public class RASTUtils { * . */ public static <T extends RBaseNode> T cloneNode(T node) { + // TODO: use RASTBuilder here as well? return NodeUtil.cloneNode(node); } @@ -126,6 +122,9 @@ public class RASTUtils { return value; } else if (argNode instanceof ReadVariableNode) { return RASTUtils.createRSymbol(argNode); + } else if (argNode instanceof VarArgNode) { + VarArgNode varArgNode = (VarArgNode) argNode; + return RDataFactory.createSymbolInterned(varArgNode.getIdentifier()); } else { assert !(argNode instanceof VarArgNode); return RDataFactory.createLanguage((RNode) argNode); @@ -224,9 +223,6 @@ public class RASTUtils { return RCallNode.createCall(sourceSection, (ReadVariableNode) fn, signature, arguments); } else if (fn instanceof NamedRNode) { return RCallNode.createCall(RSyntaxNode.SOURCE_UNAVAILABLE, (NamedRNode) fn, signature, arguments); - } else if (fn instanceof GroupDispatchNode) { - GroupDispatchNode gdcn = (GroupDispatchNode) fn; - return GroupDispatchNode.create(gdcn.getGenericName(), gdcn.getCallSrc(), signature, arguments); } else if (fn instanceof RFunction) { RFunction rfn = (RFunction) fn; return RCallNode.createCall(sourceSection, ConstantNode.create(rfn), signature, arguments); @@ -240,55 +236,6 @@ public class RASTUtils { } } - /** - * Find the {@link CallArgumentsNode} that is the child of {@code node}. N.B. Does not copy. - */ - public static Arguments<RSyntaxNode> findCallArguments(Node node) { - if (node instanceof RCallNode) { - return ((RCallNode) node).getArguments(); - } else if (node instanceof GroupDispatchNode) { - return ((GroupDispatchNode) node).getArguments(); - } - throw RInternalError.shouldNotReachHere(); - } - - /** - * Returns the name (as an {@link RSymbol} of the function associated with an {@link RCallNode} - * or {@link GroupDispatchNode}. - */ - public static Object findFunctionName(RBaseNode node) { - CompilerAsserts.neverPartOfCompilation(); // for string interning - RNode child = (RNode) unwrap(getFunctionNode(node)); - if (child instanceof ConstantNode && ConstantNode.isFunction(child)) { - return ((ConstantNode) child).getValue(); - } else if (child instanceof ReadVariableNode) { - String name = ((ReadVariableNode) child).getIdentifier(); - assert name == name.intern(); - return RDataFactory.createSymbol(name); - } else if (child instanceof GroupDispatchNode) { - GroupDispatchNode groupDispatchNode = (GroupDispatchNode) child; - String gname = groupDispatchNode.getGenericName(); - return RDataFactory.createSymbolInterned(gname); - } else { - // TODO This should really fail in some way as (clearly) this is not a "name" - // some more complicated expression, just deparse it - return RDataFactory.createSymbolInterned(RDeparse.deparse(child)); - } - } - - /** - * Unifies {@link RCallNode} and {@link GroupDispatchNode} for accessing (likely) function name. - */ - public static RNode getFunctionNode(Node node) { - if (node instanceof RCallNode) { - return ((RCallNode) node).getFunctionNode(); - } else if (node instanceof GroupDispatchNode) { - return (RNode) node; - } - assert false; - return null; - } - @TruffleBoundary /** * The heart of the {@code substitute} function, where we look up the value of {@code name} in diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ConstantNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ConstantNode.java index b71392f90ed51fe0dd42d83c02dad648e03a5295..ae23ed865a3cd740638ecaa3feda691e0bcc2cd3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ConstantNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/ConstantNode.java @@ -29,7 +29,6 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSerialize; import com.oracle.truffle.r.runtime.VisibilityController; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RSymbol; @@ -46,10 +45,6 @@ public abstract class ConstantNode extends RSourceSectionNode implements RSyntax super(sourceSection); } - public static boolean isFunction(RNode node) { - return node instanceof ConstantObjectNode && ((ConstantObjectNode) node).value instanceof RFunction; - } - public static boolean isMissing(RNode node) { return node instanceof ConstantObjectNode && ((ConstantObjectNode) node).value == RMissing.instance; } @@ -198,16 +193,4 @@ public abstract class ConstantNode extends RSourceSectionNode implements RSyntax } } } - - public static Integer asIntConstant(RSyntaxNode argument, boolean castFromDouble) { - if (argument instanceof ConstantNode) { - Object value = ((ConstantNode) argument).getValue(); - if (value instanceof Integer) { - return (int) value; - } else if (castFromDouble && value instanceof Double) { - return (int) (double) value; - } - } - return 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 4c7357aab540ba5c9244ceeca17857f63ecdb39d..0b43bf6c4e06d0a319e64c173fec67cedcccd335 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 @@ -39,19 +39,7 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RAttributes; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogical; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RString; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RTypedValue; -import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -139,10 +127,6 @@ final class CachedExtractVectorNode extends CachedVectorNode { */ return doEnvironment((REnvironment) castVector, positions); case Integer: - if (castVector instanceof RFactor) { - vector = ((RFactor) castVector).getVector(); - break; - } vector = (RAbstractContainer) castVector; break; default: diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java index a9a7f880199bbbe254747b6b9c6bf593fefa9cac..cc23fc946510bec07252a4d59f56135d1ab37f1a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedReplaceVectorNode.java @@ -41,20 +41,7 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RScalarVector; -import com.oracle.truffle.r.runtime.data.RShareable; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RTypedValue; -import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -146,11 +133,7 @@ final class CachedReplaceVectorNode extends CachedVectorNode { value = castType.getEmpty(); } } else { - if (!isList() && castValue instanceof RFactor) { - value = ((RFactor) castValue).getVector(); - } else { - value = (RTypedValue) castValue; - } + value = (RTypedValue) castValue; } int appliedValueLength; @@ -183,9 +166,6 @@ final class CachedReplaceVectorNode extends CachedVectorNode { case Null: vector = castType.getEmpty(); break; - case Factor: - vector = ((RFactor) castVector).getVector(); - break; case PairList: vector = ((RPairList) castVector).toRList(); break; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java index b2084a03d51f5ae5f39df81c8f72d0af18a2620f..2622dfc83ebb23d9920416d187264533e4ce06fe 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/CachedVectorNode.java @@ -142,7 +142,6 @@ abstract class CachedVectorNode extends RBaseNode { switch (type) { case Null: case Language: - case Factor: case PairList: case Environment: case Expression: diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java index 8cbb1b12d1d4d09459843b17e4417dd6f7fb5b36..6579b8088ef89d2b44493e1fc01361734f2dfc2e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/vector/PositionCastNode.java @@ -30,26 +30,8 @@ import com.oracle.truffle.r.nodes.unary.CastIntegerNode; import com.oracle.truffle.r.nodes.unary.CastIntegerNodeGen; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.REmpty; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RInteger; -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.RString; -import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.RTypedValue; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -93,11 +75,6 @@ abstract class PositionCastNode extends Node { return position; } - @Specialization - protected RAbstractVector doFactor(RFactor position) { - return position.getVector(); - } - @Specialization protected RAbstractVector doDouble(double position, @Cached("create()") NACheck check) { if (mode.isSubscript()) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccess.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccess.java index 0656f9ee9564215a5fba681332f49c5e9f2588ad..eff4b0c6e2f5e882b6d44441c7f6c68af3d5017c 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccess.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/attributes/AttributeAccess.java @@ -47,6 +47,10 @@ public abstract class AttributeAccess extends RBaseNode { this.name = name.intern(); } + public static AttributeAccess create(String name) { + return AttributeAccessNodeGen.create(name); + } + public abstract Object execute(RAttributes attr); protected boolean nameMatches(RAttributes attr, int index) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java index 7f5e12b3398960ed20185c99cf21c10092bb0312..a9c8c2fbf982d538e46ef3c846fd7cf8af5f8528 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryArithmeticNode.java @@ -31,7 +31,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.profiles.ValueProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.control.RLengthNode; import com.oracle.truffle.r.nodes.primitive.BinaryMapNode; import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode; @@ -41,19 +40,19 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.BinaryArithmeticFactory; import com.oracle.truffle.r.runtime.ops.UnaryArithmeticFactory; -public abstract class BinaryArithmeticNode extends RBuiltinNode { +/** + * Represents a binary or unary operation from the 'arithmetic' subset of Ops R group. The concrete + * operation is implemented by factory object given as a constructor parameter, e.g. + * {@link com.oracle.truffle.r.runtime.ops.BinaryArithmetic.Add} + */ +public abstract class BinaryArithmeticNode extends BinaryNodeBase { protected static final int CACHE_LIMIT = 5; @@ -74,13 +73,15 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { return BinaryArithmeticNodeGen.create(binary, unary, null); } - @Specialization(limit = "CACHE_LIMIT", guards = {"cached != null", "cached.isSupported(left, right)"}) + @Specialization(limit = "CACHE_LIMIT", guards = {"cached != null", "cached.isSupported(left, right)", + "!isFactor(left)", "!isFactor(right)"}) protected Object doNumericVectorCached(Object left, Object right, // @Cached("createFastCached(left, right)") BinaryMapNode cached) { return cached.apply(left, right); } - @Specialization(contains = "doNumericVectorCached", guards = {"isNumericVector(left)", "isNumericVector(right)"}) + @Specialization(contains = "doNumericVectorCached", guards = {"isNumericVector(left)", "isNumericVector(right)", + "!isFactor(left)", "!isFactor(right)"}) @TruffleBoundary protected Object doNumericVectorGeneric(Object left, Object right, // @Cached("binary.create()") BinaryArithmetic arithmetic, // @@ -117,33 +118,25 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { } } - protected static boolean isFactor(Object value) { - return value instanceof RFactor; - } - @Specialization(guards = "isFactor(left) || isFactor(right)") - protected Object doFactor(VirtualFrame frame, Object left, Object right, @Cached("create()") RLengthNode lengthNode) { + protected Object doFactor(VirtualFrame frame, RAbstractIntVector left, RAbstractIntVector right, @Cached("create()") RLengthNode lengthNode) { Message warning; - if (left instanceof RFactor) { - warning = getFactorWarning((RFactor) left); + if (isFactor(left)) { + warning = getFactorWarning(left); } else { - warning = getFactorWarning((RFactor) right); + warning = getFactorWarning(right); } RError.warning(this, warning, binary.create().opName()); return RDataFactory.createNAVector(Math.max(lengthNode.executeInteger(frame, left), lengthNode.executeInteger(frame, right))); } - private static Message getFactorWarning(RFactor factor) { - return factor.isOrdered() ? Message.NOT_MEANINGFUL_FOR_ORDERED_FACTORS : Message.NOT_MEANINGFUL_FOR_FACTORS; - } - @Specialization @SuppressWarnings("unused") protected static Object doBothNull(RNull left, RNull right) { return RType.Double.getEmpty(); } - @Specialization(guards = "isNumericVector(right)") + @Specialization(guards = {"isNumericVector(right)", "!isFactor(right)"}) protected static Object doLeftNull(@SuppressWarnings("unused") RNull left, Object right, // @Cached("createClassProfile()") ValueProfile classProfile) { if (((RAbstractVector) classProfile.profile(right)).getRType() == RType.Complex) { @@ -153,7 +146,7 @@ public abstract class BinaryArithmeticNode extends RBuiltinNode { } } - @Specialization(guards = "isNumericVector(left)") + @Specialization(guards = {"isNumericVector(left)", "!isFactor(left)"}) protected static Object doRightNull(Object left, RNull right, // @Cached("createClassProfile()") ValueProfile classProfile) { return doLeftNull(right, left, classProfile); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java index e6480ed1fdc8aabe8740b72af06938ea81a2ad99..19c7b12cbb295cc31af46f47477e359350c09acd 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryBooleanNode.java @@ -28,8 +28,8 @@ 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.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.builtin.CastBuilder; -import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.control.RLengthNode; import com.oracle.truffle.r.nodes.primitive.BinaryMapNode; import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode; @@ -39,16 +39,9 @@ import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RInteger; import com.oracle.truffle.r.runtime.data.closures.RClosures; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.ops.BinaryCompare; import com.oracle.truffle.r.runtime.ops.BinaryLogic; import com.oracle.truffle.r.runtime.ops.BinaryLogic.And; @@ -56,7 +49,12 @@ import com.oracle.truffle.r.runtime.ops.BinaryLogic.Or; import com.oracle.truffle.r.runtime.ops.BooleanOperation; import com.oracle.truffle.r.runtime.ops.BooleanOperationFactory; -public abstract class BinaryBooleanNode extends RBuiltinNode { +/** + * Represents a binary or unary operation from the 'logical' subset of Ops R group. The concrete + * operation is implemented by factory object given as a constructor parameter, e.g. + * {@link com.oracle.truffle.r.runtime.ops.BinaryLogic.And}. + */ +public abstract class BinaryBooleanNode extends BinaryNodeBase { protected static final int CACHE_LIMIT = 5; @@ -123,10 +121,6 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { (!isLogicOp(factory) && (value instanceof RAbstractStringVector || value instanceof RAbstractRawVector)); } - protected static boolean isFactor(Object value) { - return value instanceof RFactor; - } - @Specialization(guards = {"isRConnection(left) || isRConnection(right)"}) protected Object doConnection(VirtualFrame frame, Object left, Object right, // @Cached("createRecursive()") BinaryBooleanNode recursive) { @@ -146,13 +140,15 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { @Cached("createRecursive()") BinaryBooleanNode recursive, // @Cached("create()") RAttributeProfiles attrProfiles) { Object recursiveLeft = left; - if (recursiveLeft instanceof RFactor) { - recursiveLeft = RClosures.createFactorToVector((RFactor) recursiveLeft, false, attrProfiles); + if (isFactor(left)) { + recursiveLeft = RClosures.createFactorToVector((RAbstractIntVector) left, false, attrProfiles); } + Object recursiveRight = right; - if (recursiveRight instanceof RFactor) { - recursiveRight = RClosures.createFactorToVector((RFactor) recursiveRight, false, attrProfiles); + if (isFactor(right)) { + recursiveRight = RClosures.createFactorToVector((RAbstractIntVector) right, false, attrProfiles); } + return recursive.execute(frame, recursiveLeft, recursiveRight); } @@ -163,34 +159,32 @@ public abstract class BinaryBooleanNode extends RBuiltinNode { @Specialization(guards = {"isFactor(left) || isFactor(right)", "!meaningfulFactorOp(left, right)"}) protected Object doFactorNotMeaniningful(VirtualFrame frame, Object left, Object right, @Cached("create()") RLengthNode lengthNode) { Message warning; - if (left instanceof RFactor) { - warning = getFactorWarning((RFactor) left); + if (isFactor(left)) { + warning = getFactorWarning((RAbstractIntVector) left); } else { - warning = getFactorWarning((RFactor) right); + warning = getFactorWarning((RAbstractIntVector) right); } RError.warning(this, warning, factory.create().opName()); return RDataFactory.createNAVector(Math.max(lengthNode.executeInteger(frame, left), lengthNode.executeInteger(frame, right))); } + private ConditionProfile meaningfulOpForFactors = ConditionProfile.createBinaryProfile(); + protected boolean meaningfulFactorOp(Object left, Object right) { - if (factory == BinaryCompare.EQUAL || factory == BinaryCompare.NOT_EQUAL) { + if (meaningfulOpForFactors.profile(factory == BinaryCompare.EQUAL || factory == BinaryCompare.NOT_EQUAL)) { return true; - } else if (left instanceof RFactor) { - boolean ordered = ((RFactor) left).isOrdered(); - if (right instanceof RFactor) { - return ordered && ((RFactor) right).isOrdered(); + } else if (isFactor(left)) { + boolean ordered = isOrderedFactor((RAbstractIntVector) left); + if (isFactor(right)) { + return ordered && isOrderedFactor((RAbstractIntVector) right); } return ordered; } else { - assert right instanceof RFactor; - return ((RFactor) right).isOrdered(); + assert isFactor(right) : "meaningfulFactorOp is expected to be invoked with at least one factor."; + return isOrderedFactor((RAbstractIntVector) right); } } - private static Message getFactorWarning(RFactor factor) { - return factor.isOrdered() ? Message.NOT_MEANINGFUL_FOR_ORDERED_FACTORS : Message.NOT_MEANINGFUL_FOR_FACTORS; - } - @SuppressWarnings("unused") @Specialization(guards = {"isRNullOrEmptyAndNotMissing(left, right)"}) protected static Object doEmptyOrNull(Object left, Object right) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNodeBase.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNodeBase.java new file mode 100644 index 0000000000000000000000000000000000000000..4e2ff2270da74913382344965eba3973639b1c85 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/BinaryNodeBase.java @@ -0,0 +1,65 @@ +/* + * 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.binary; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; +import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; +import com.oracle.truffle.r.nodes.helpers.RFactorNodes; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; + +/** + * Provides some shared code for nodes implemented in this package. + * + * TODO: for the time being, this code is only concerned with R factor class. Code specific to + * factors is necessary only because the proper R dispatch of operations implemented in this java + * package is not implemented yet. Once this is done, we can remove this base class. It also seems + * that {@link BinaryBooleanNode} and {@link BinaryArithmeticNode} are separate classes only to + * handle the difference in R specializations that implement them, e.g. Ops.factor handles + * 'arithmetic' subset of Ops differently than the 'logical'. + */ +abstract class BinaryNodeBase extends RBuiltinNode { + + @Child private InheritsCheckNode factorInheritCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR); + @Child private RFactorNodes.GetOrdered isOrderedFactor = null; + + protected boolean isFactor(Object value) { + return factorInheritCheck.execute(value); + } + + protected boolean isOrderedFactor(RAbstractIntVector factor) { + if (isOrderedFactor == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + isOrderedFactor = insert(new RFactorNodes.GetOrdered()); + } + + return isOrderedFactor.execute(factor); + } + + protected RError.Message getFactorWarning(RAbstractIntVector factor) { + return isOrderedFactor(factor) ? RError.Message.NOT_MEANINGFUL_FOR_ORDERED_FACTORS : RError.Message.NOT_MEANINGFUL_FOR_FACTORS; + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java index 469e1f11006c8e8e69da4727cc240e876f48f2a7..274546d254248bd72cdbfac3d4569b65c5d4eea5 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinNode.java @@ -117,9 +117,9 @@ public abstract class RBuiltinNode extends RNode implements VisibilityController return Truffle.getRuntime().createCallTarget(root); } - static final RBuiltinNode inline(RBuiltinFactory factory, RNode[] args) { + public static final RBuiltinNode inline(RBuiltinDescriptor factory, RNode[] args) { // static number of arguments - return factory.getConstructor().apply(args); + return ((RBuiltinFactory) factory).getConstructor().apply(args); } protected final RBuiltin getRBuiltin() { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java index 12f2fcec908deb0fd01b40454efc78dffc0201f2..c502085a2ae82c892dde1e72786bd74617bcac96 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/RBuiltinRootNode.java @@ -31,7 +31,6 @@ import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.function.FormalArguments; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor; -import com.oracle.truffle.r.runtime.nodes.RNode; public final class RBuiltinRootNode extends RRootNode { @@ -76,10 +75,6 @@ public final class RBuiltinRootNode extends RRootNode { return factory.isAlwaysSplit(); } - public RBuiltinNode inline(RNode[] args) { - return RBuiltinNode.inline(factory, args); - } - @Override public String getSourceCode() { throw RInternalError.shouldNotReachHere(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java index 60c18c59803d2938eb30bfeec9880e070c842264..73dded63d284599fb6fdd1606af7dd5c288d10da 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentMatcher.java @@ -62,9 +62,8 @@ import com.oracle.truffle.r.runtime.nodes.RNode; * {@link FormalArguments} of a specific function, see * {@link #matchArguments(RFunction, UnmatchedArguments, RBaseNode, boolean)} . The other match * functions are used for special cases, where builtins make it necessary to re-match parameters, - * e.g.: {@link #matchArgumentsEvaluated(RFunction, EvaluatedArguments, RBaseNode, boolean)} for - * 'UseMethod' and {@link #matchArgumentsInlined(RFunction, UnmatchedArguments, RBaseNode)} for - * builtins which are implemented in Java. + * e.g.: {@link #matchArgumentsEvaluated(RFunction, RArgsValuesAndNames, RBaseNode, boolean)} for + * 'UseMethod'. * </p> * * <p> @@ -130,33 +129,13 @@ public class ArgumentMatcher { * @return A fresh {@link MatchedArguments} containing the arguments in correct order and * wrapped in {@link PromiseNode}s */ - public static MatchedArguments matchArguments(RFunction function, UnmatchedArguments suppliedArgs, RBaseNode callingNode, boolean noOpt) { - RNode[] wrappedArgs = matchNodes(function, suppliedArgs.getArguments(), suppliedArgs.getSignature(), callingNode, suppliedArgs, noOpt); - FormalArguments formals = ((RRootNode) function.getTarget().getRootNode()).getFormalArguments(); - return MatchedArguments.create(wrappedArgs, formals.getSignature()); + public static RNode[] matchArguments(RFunction function, UnmatchedArguments suppliedArgs, RBaseNode callingNode, boolean noOpt) { + return matchNodes(function, suppliedArgs.getArguments(), suppliedArgs.getSignature(), callingNode, suppliedArgs, noOpt); } - /** - * Match arguments supplied for a specific function call to the formal arguments and wraps them - * in special {@link PromiseNode}s. Used for calls to builtins which are built into FastR and - * thus are implemented in Java - * - * @param function The function which is to be called - * @param suppliedArgs The arguments supplied to the call - * @param callingNode The {@link Node} invoking the match - * @return A fresh {@link InlinedArguments} containing the arguments in correct order and - * wrapped in special {@link PromiseNode}s - */ - public static RNode[] matchArgumentsInlined(RFunction function, UnmatchedArguments suppliedArgs, RBaseNode callingNode) { - return matchNodes(function, suppliedArgs.getArguments(), suppliedArgs.getSignature(), callingNode, suppliedArgs, false); - } - - public static MatchPermutation matchArguments(ArgumentsSignature suppliedSignature, ArgumentsSignature formalSignature, RBaseNode callingNode, boolean forNextMethod, RBuiltinDescriptor builtin) { + public static MatchPermutation matchArguments(ArgumentsSignature supplied, ArgumentsSignature formal, RBaseNode callingNode, boolean forNextMethod, RBuiltinDescriptor builtin) { CompilerAsserts.neverPartOfCompilation(); - MatchPermutation match = permuteArguments(suppliedSignature, formalSignature, callingNode, forNextMethod, index -> { - throw RInternalError.unimplemented("S3Dispatch should not have arg length mismatch"); - }, index -> suppliedSignature.getName(index), builtin); - return match; + return permuteArguments(supplied, formal, callingNode, forNextMethod, index -> false, index -> supplied.getName(index) == null ? "" : supplied.getName(index), builtin); } public static ArgumentsSignature getFunctionSignature(RFunction function) { @@ -213,10 +192,10 @@ public class ArgumentMatcher { * @param callingNode The {@link Node} invoking the match * @param forNextMethod matching when evaluating NextMethod * - * @return A Fresh {@link EvaluatedArguments} containing the arguments rearranged and stuffed + * @return A Fresh {@link RArgsValuesAndNames} containing the arguments rearranged and stuffed * with default values (in the form of {@link RPromise}s where needed) */ - public static EvaluatedArguments matchArgumentsEvaluated(RFunction function, EvaluatedArguments evaluatedArgs, RBaseNode callingNode, boolean forNextMethod) { + public static RArgsValuesAndNames matchArgumentsEvaluated(RFunction function, RArgsValuesAndNames evaluatedArgs, RBaseNode callingNode, boolean forNextMethod) { RRootNode rootNode = (RRootNode) function.getTarget().getRootNode(); FormalArguments formals = rootNode.getFormalArguments(); MatchPermutation match = permuteArguments(evaluatedArgs.getSignature(), formals.getSignature(), callingNode, forNextMethod, index -> { @@ -248,7 +227,7 @@ public class ArgumentMatcher { evaledArgs[formalIndex] = evaluatedArgs.getArgument(suppliedIndex); } } - return new EvaluatedArguments(evaledArgs, formals.getSignature()); + return new RArgsValuesAndNames(evaledArgs, formals.getSignature()); } private static String getErrorForArgument(RNode[] suppliedArgs, ArgumentsSignature suppliedSignature, int index) { @@ -430,7 +409,7 @@ public class ArgumentMatcher { } } - static final class MatchPermutation { + public static final class MatchPermutation { public static final int UNMATCHED = -1; public static final int VARARGS = -2; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java index 2179fffe501dc67fc0263546c18b0e8731b2834c..a6b47df08fbe1e6680aceccc60eb82e8b5dbc14e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallArgumentsNode.java @@ -22,10 +22,8 @@ */ package com.oracle.truffle.r.nodes.function; -import java.util.ArrayList; import java.util.Arrays; import java.util.IdentityHashMap; -import java.util.List; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; @@ -97,33 +95,20 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum * @param modeChangeForAll * @param args {@link #arguments}; new array gets created. Every {@link RNode} (except * <code>null</code>) gets wrapped into a {@link WrapArgumentNode}. + * @param varArgsSymbolIndicesArr * @return A fresh {@link CallArgumentsNode} */ - public static CallArgumentsNode create(boolean modeChange, boolean modeChangeForAll, RNode[] args, ArgumentsSignature signature) { + public static CallArgumentsNode create(boolean modeChange, boolean modeChangeForAll, RNode[] args, ArgumentsSignature signature, int[] varArgsSymbolIndicesArr) { // Prepare arguments: wrap in WrapArgumentNode RNode[] wrappedArgs = new RNode[args.length]; - List<Integer> varArgsSymbolIndices = new ArrayList<>(); for (int i = 0; i < wrappedArgs.length; i++) { RNode arg = args[i]; if (arg == null) { wrappedArgs[i] = null; } else { - if (arg instanceof ReadVariableNode) { - // Check for presence of "..." in the arguments - ReadVariableNode rvn = (ReadVariableNode) arg; - if (ArgumentsSignature.VARARG_NAME.equals(rvn.getIdentifier())) { - varArgsSymbolIndices.add(i); - } - } wrappedArgs[i] = WrapArgumentNode.create(arg, i == 0 || modeChangeForAll ? modeChange : true, i); } } - - // Setup and return - int[] varArgsSymbolIndicesArr = new int[varArgsSymbolIndices.size()]; - for (int i = 0; i < varArgsSymbolIndicesArr.length; i++) { - varArgsSymbolIndicesArr[i] = varArgsSymbolIndices.get(i); - } return new CallArgumentsNode(wrappedArgs, signature, varArgsSymbolIndicesArr); } @@ -140,10 +125,11 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum * This methods unrolls all "..." in the argument list. The result varies if the number of * arguments in the varargs or their names change. */ - public UnrolledVariadicArguments executeFlatten(Frame frame) { + public UnmatchedArguments unrollArguments(ArgumentsSignature varArgSignature) { CompilerAsserts.neverPartOfCompilation(); + assert containsVarArgsSymbol() == (varArgSignature != null); if (!containsVarArgsSymbol()) { - return UnrolledVariadicArguments.create(getArguments(), getSignature(), this); + return this; } else { RNode[] values = new RNode[arguments.length]; String[] newNames = new String[arguments.length]; @@ -152,19 +138,18 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum int index = 0; for (int i = 0; i < arguments.length; i++) { if (vargsSymbolsIndex < varArgsSymbolIndices.length && varArgsSymbolIndices[vargsSymbolsIndex] == i) { - RArgsValuesAndNames varArgInfo = getVarargsAndNames(frame); - if (varArgInfo.isEmpty()) { + if (varArgSignature.isEmpty()) { // An empty "..." vanishes values = Utils.resizeArray(values, values.length - 1); newNames = Utils.resizeArray(newNames, newNames.length - 1); continue; } - values = Utils.resizeArray(values, values.length + varArgInfo.getLength() - 1); - newNames = Utils.resizeArray(newNames, newNames.length + varArgInfo.getLength() - 1); - for (int j = 0; j < varArgInfo.getLength(); j++) { + values = Utils.resizeArray(values, values.length + varArgSignature.getLength() - 1); + newNames = Utils.resizeArray(newNames, newNames.length + varArgSignature.getLength() - 1); + for (int j = 0; j < varArgSignature.getLength(); j++) { values[index] = PromiseNode.createVarArg(j); - newNames[index] = varArgInfo.getSignature().getName(j); + newNames[index] = varArgSignature.getName(j); index++; } vargsSymbolsIndex++; @@ -174,18 +159,17 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum index++; } } - return UnrolledVariadicArguments.create(values, ArgumentsSignature.get(newNames), this); } } @ExplodeLoop - public RArgsValuesAndNames evaluateFlatten(VirtualFrame frame, RArgsValuesAndNames varArgInfo) { + public RArgsValuesAndNames evaluateFlatten(VirtualFrame frame, RArgsValuesAndNames varArgs) { int size = arguments.length; ArgumentsSignature resultSignature = null; String[] names = null; if (containsVarArgsSymbol()) { - size += (varArgInfo.getLength() - 1) * varArgsSymbolIndices.length; + size += (varArgs.getLength() - 1) * varArgsSymbolIndices.length; names = new String[size]; } else { resultSignature = signature; @@ -195,7 +179,7 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum int index = 0; for (int i = 0; i < arguments.length; i++) { if (vargsSymbolsIndex < varArgsSymbolIndices.length && varArgsSymbolIndices[vargsSymbolsIndex] == i) { - index = flattenVarArgs(frame, varArgInfo, names, values, index); + index = flattenVarArgs(frame, varArgs, names, values, index); vargsSymbolsIndex++; } else { values[index] = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame); @@ -212,19 +196,17 @@ public final class CallArgumentsNode extends RBaseNode implements UnmatchedArgum } @ExplodeLoop - public Object[] evaluateFlattenObjects(VirtualFrame frame) { + public Object[] evaluateFlattenObjects(VirtualFrame frame, RArgsValuesAndNames varArgs) { int size = arguments.length; - RArgsValuesAndNames varArgInfo = null; if (containsVarArgsSymbol()) { - varArgInfo = getVarargsAndNames(frame); - size += (varArgInfo.getLength() - 1) * varArgsSymbolIndices.length; + size += (varArgs.getLength() - 1) * varArgsSymbolIndices.length; } Object[] values = new Object[size]; int vargsSymbolsIndex = 0; int index = 0; for (int i = 0; i < arguments.length; i++) { if (vargsSymbolsIndex < varArgsSymbolIndices.length && varArgsSymbolIndices[vargsSymbolsIndex] == i) { - index = flattenVarArgsObject(frame, varArgInfo, values, index); + index = flattenVarArgsObject(frame, varArgs, values, index); vargsSymbolsIndex++; } else { values[index] = arguments[i] == null ? RMissing.instance : arguments[i].execute(frame); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java index f5c513c67f84737f621acd6c4f892a0381f0fa8b..3aba0d373115b90028403ad2c73a024a95ef0698 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java @@ -24,7 +24,6 @@ import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.RRootNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; -import com.oracle.truffle.r.nodes.builtin.RBuiltinRootNode; import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; import com.oracle.truffle.r.nodes.unary.CastNode; @@ -200,8 +199,7 @@ public abstract class CallMatcherNode extends RBaseNode { this.next = next; this.formals = ((RRootNode) cachedFunction.getRootNode()).getFormalArguments(); if (function.isBuiltin()) { - RBuiltinRootNode builtinRoot = RCallNode.findBuiltinRootNode(function.getTarget()); - this.builtin = builtinRoot.inline(null); + this.builtin = RBuiltinNode.inline(function.getRBuiltin(), null); this.builtinArgumentCasts = builtin.getCasts(); } else { this.call = Truffle.getRuntime().createDirectCallNode(function.getTarget()); @@ -218,7 +216,8 @@ public abstract class CallMatcherNode extends RBaseNode { Object[] reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(permutation, preparedArguments, formals); evaluatePromises(frame, cachedFunction, reorderedArgs, formals.getSignature().getVarArgIndex()); if (call != null) { - RCaller caller = functionName == null ? RCallerHelper.InvalidRepresentation.instance : new RCallerHelper.Representation(functionName, reorderedArgs); + RCaller caller = functionName == null ? RCallerHelper.InvalidRepresentation.instance + : new RCallerHelper.Representation(functionName, new RArgsValuesAndNames(reorderedArgs, ArgumentsSignature.empty(reorderedArgs.length))); Object[] arguments = prepareArguments(frame, reorderedArgs, formals.getSignature(), cachedFunction, dispatchArgs, caller); return call.call(frame, arguments); } else { @@ -297,10 +296,11 @@ public abstract class CallMatcherNode extends RBaseNode { @Override public Object execute(VirtualFrame frame, ArgumentsSignature suppliedSignature, Object[] suppliedArguments, RFunction function, String functionName, DispatchArgs dispatchArgs) { - EvaluatedArguments reorderedArgs = reorderArguments(suppliedArguments, function, suppliedSignature); + RArgsValuesAndNames reorderedArgs = reorderArguments(suppliedArguments, function, suppliedSignature); evaluatePromises(frame, function, reorderedArgs.getArguments(), reorderedArgs.getSignature().getVarArgIndex()); - RCaller caller = functionName == null ? RCallerHelper.InvalidRepresentation.instance : new RCallerHelper.Representation(functionName, reorderedArgs.getArguments()); + RCaller caller = functionName == null ? RCallerHelper.InvalidRepresentation.instance + : new RCallerHelper.Representation(functionName, new RArgsValuesAndNames(reorderedArgs.getArguments(), ArgumentsSignature.empty(reorderedArgs.getLength()))); Object[] arguments = prepareArguments(frame, reorderedArgs.getArguments(), reorderedArgs.getSignature(), function, dispatchArgs, caller); return call.call(frame, function.getTarget(), arguments); } @@ -317,7 +317,7 @@ public abstract class CallMatcherNode extends RBaseNode { } @TruffleBoundary - protected EvaluatedArguments reorderArguments(Object[] args, RFunction function, ArgumentsSignature paramSignature) { + protected RArgsValuesAndNames reorderArguments(Object[] args, RFunction function, ArgumentsSignature paramSignature) { assert paramSignature.getLength() == args.length; int argCount = args.length; @@ -362,10 +362,10 @@ public abstract class CallMatcherNode extends RBaseNode { } // ...and use them as 'supplied' arguments... - EvaluatedArguments evaledArgs = EvaluatedArguments.create(argValues, signature); + RArgsValuesAndNames evaledArgs = new RArgsValuesAndNames(argValues, signature); // ...to match them against the chosen function's formal arguments - EvaluatedArguments evaluated = ArgumentMatcher.matchArgumentsEvaluated(function, evaledArgs, this, forNextMethod); + RArgsValuesAndNames evaluated = ArgumentMatcher.matchArgumentsEvaluated(function, evaledArgs, this, forNextMethod); return evaluated; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java index ca6b156c7254d882a617aeadf605ffc8392466a7..69037c6399a16f843fe699d9e9199287543b6f78 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ClassHierarchyNode.java @@ -74,6 +74,10 @@ public abstract class ClassHierarchyNode extends UnaryNode { this.withS4 = withS4; } + public static ClassHierarchyNode create() { + return ClassHierarchyNodeGen.create(false, false); + } + @Override public abstract RStringVector execute(Object arg); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/EvaluatedArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/EvaluatedArguments.java deleted file mode 100644 index 3d20ec3c550d744ad3cc213f5235c0606d719a6d..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/EvaluatedArguments.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2013, 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.function; - -import com.oracle.truffle.r.runtime.Arguments; -import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RArguments; - -/** - * Simple container class for holding arguments which are ready to be pushed into {@link RArguments} - * (or are taken from there!). 'argument missing' is denoted by <code>null</code>. - */ -public class EvaluatedArguments extends Arguments<Object> { - - EvaluatedArguments(Object[] evaluatedArgs, ArgumentsSignature signature) { - super(evaluatedArgs, signature); - } - - public static EvaluatedArguments create(Object[] args, ArgumentsSignature signature) { - return new EvaluatedArguments(args, signature); - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/GetCallerFrameNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java similarity index 91% rename from com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/GetCallerFrameNode.java rename to com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java index b41b824f8bf90adba7b3dc0e5b6740a4ba59f331..cbab2849930de3a423a0482124bb88ff15dfb08e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/GetCallerFrameNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GetCallerFrameNode.java @@ -20,7 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.truffle.r.nodes.function.signature; +package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.Frame; @@ -30,7 +30,7 @@ import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.r.nodes.PromiseEvalFrameDebug; -import com.oracle.truffle.r.nodes.function.RCallNode.CallWithCallerFrame; +import com.oracle.truffle.r.nodes.function.signature.FrameDepthNode; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.RError; @@ -54,8 +54,8 @@ public final class GetCallerFrameNode extends RBaseNode { if (frameDepthNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); RCaller call = RArguments.getCall(frame); - if (call != null && call.getSyntaxNode() instanceof CallWithCallerFrame) { - if (!((CallWithCallerFrame) call.getSyntaxNode()).setNeedsCallerFrame()) { + if (call instanceof RCallNode) { + if (!((RCallNode) call).setNeedsCallerFrame()) { reset = true; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java deleted file mode 100644 index 1b104f9bc09a57223d60f70153be6608c6bc836c..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * This material is distributed under the GNU General Public License - * Version 2. You may review the terms of this license at - * http://www.gnu.org/licenses/gpl-2.0.html - * - * Copyright (c) 2014, Purdue University - * Copyright (c) 2015, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.nodes.function; - -import java.util.Arrays; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.nodes.UnexpectedResultException; -import com.oracle.truffle.api.profiles.ConditionProfile; -import com.oracle.truffle.api.source.SourceSection; -import com.oracle.truffle.r.nodes.RASTUtils; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; -import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.NoGenericMethodException; -import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result; -import com.oracle.truffle.r.runtime.Arguments; -import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.RArguments.S3Args; -import com.oracle.truffle.r.runtime.RDispatch; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RInternalError; -import com.oracle.truffle.r.runtime.RSerialize; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.env.REnvironment; -import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; -import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; -import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; - -public final class GroupDispatchNode extends RSourceSectionNode implements RSyntaxNode, RSyntaxCall { - - @Child private CallArgumentsNode callArgsNode; - @Child private S3FunctionLookupNode functionLookupL; - @Child private S3FunctionLookupNode functionLookupR; - @Child private ClassHierarchyNode classHierarchyL; - @Child private ClassHierarchyNode classHierarchyR; - @Child private CallMatcherNode callMatcher = CallMatcherNode.create(false, true); - @Child private ReadVariableNode lookupVarArgs; - - private final String fixedGenericName; - private final RDispatch fixedDispatch; - private final RFunction fixedBuiltinFunction; - - private final ConditionProfile mismatchProfile = ConditionProfile.createBinaryProfile(); - - @CompilationFinal private boolean dynamicLookup; - private final ConditionProfile exactEqualsProfile = ConditionProfile.createBinaryProfile(); - - private GroupDispatchNode(SourceSection sourceSection, String genericName, CallArgumentsNode callArgNode, RFunction builtinFunction) { - super(sourceSection); - this.fixedGenericName = genericName.intern(); - this.fixedDispatch = builtinFunction.getRBuiltin().getDispatch(); - this.callArgsNode = callArgNode; - this.fixedBuiltinFunction = builtinFunction; - } - - public static GroupDispatchNode create(String genericName, SourceSection sourceSection, ArgumentsSignature signature, RSyntaxNode... arguments) { - CallArgumentsNode callArgNode = CallArgumentsNode.create(false, true, Arrays.copyOf(arguments, arguments.length, RNode[].class), signature); - GroupDispatchNode gdcn = new GroupDispatchNode(sourceSection, genericName, callArgNode, RContext.lookupBuiltin(genericName)); - return gdcn; - } - - public static GroupDispatchNode create(String genericName, CallArgumentsNode callArgNode, RFunction builtinFunction, SourceSection sourceSection) { - GroupDispatchNode gdcn = new GroupDispatchNode(sourceSection, genericName, callArgNode, builtinFunction); - return gdcn; - } - - public Arguments<RSyntaxNode> getArguments() { - return new Arguments<>(callArgsNode.getSyntaxArguments(), callArgsNode.getSignature()); - } - - public String getGenericName() { - return fixedGenericName; - } - - public SourceSection getCallSrc() { - return getSourceSection(); - } - - @Override - public void serializeImpl(RSerialize.State state) { - String name = getGenericName(); - state.setAsBuiltin(name); - RCallNode.serializeArguments(state, callArgsNode.getSyntaxArguments(), callArgsNode.signature, false); - } - - @Override - public RSyntaxNode substituteImpl(REnvironment env) { - // TODO substitute aDispatchNode - Arguments<RSyntaxNode> substituteArguments = RCallNode.substituteArguments(env, callArgsNode.getSyntaxArguments(), callArgsNode.signature); - return RASTUtils.createCall(this, false, substituteArguments.getSignature(), substituteArguments.getArguments()); - } - - @Override - public Object execute(VirtualFrame frame) { - RArgsValuesAndNames varArgs = null; - if (callArgsNode.containsVarArgsSymbol()) { - if (lookupVarArgs == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - lookupVarArgs = insert(ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any)); - } - try { - varArgs = lookupVarArgs.executeRArgsValuesAndNames(frame); - } catch (UnexpectedResultException e) { - throw RInternalError.shouldNotReachHere(e, "'...' should always be represented by RArgsValuesAndNames"); - } - } - RArgsValuesAndNames argAndNames = callArgsNode.evaluateFlatten(frame, varArgs); - return executeInternal(frame, argAndNames, fixedGenericName, fixedDispatch, fixedBuiltinFunction); - } - - public Object executeDynamic(VirtualFrame frame, RArgsValuesAndNames argAndNames, String genericName, RDispatch dispatch, RFunction builtinFunction) { - if (!dynamicLookup) { - if (builtinFunction == fixedBuiltinFunction && (exactEqualsProfile.profile(fixedGenericName == genericName) || fixedGenericName.equals(genericName))) { - return executeInternal(frame, argAndNames, fixedGenericName, fixedDispatch, fixedBuiltinFunction); - } - CompilerDirectives.transferToInterpreterAndInvalidate(); - dynamicLookup = true; - } - return executeInternal(frame, argAndNames, genericName, dispatch, builtinFunction); - } - - private Object executeInternal(VirtualFrame frame, RArgsValuesAndNames argAndNames, String genericName, RDispatch dispatch, RFunction builtinFunction) { - assert dispatch.isGroupGeneric(); - Object[] evaluatedArgs = argAndNames.getArguments(); - - if (classHierarchyL == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - classHierarchyL = insert(ClassHierarchyNodeGen.create(false, true)); - } - RStringVector typeL = evaluatedArgs.length == 0 ? null : classHierarchyL.execute(evaluatedArgs[0]); - - Result resultL = null; - if (typeL != null) { - try { - if (functionLookupL == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - functionLookupL = insert(S3FunctionLookupNode.create(false, false)); - } - resultL = functionLookupL.execute(frame, genericName, typeL, dispatch.getGroupGenericName(), frame.materialize(), null); - } catch (NoGenericMethodException e) { - // fall-through - } - } - Result resultR = null; - if (dispatch == RDispatch.OPS_GROUP_GENERIC && argAndNames.getSignature().getLength() >= 2) { - if (classHierarchyR == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - classHierarchyR = insert(ClassHierarchyNodeGen.create(false, true)); - } - RStringVector typeR = classHierarchyR.execute(evaluatedArgs[1]); - if (typeR != null) { - try { - if (functionLookupR == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - functionLookupR = insert(S3FunctionLookupNode.create(false, false)); - } - resultR = functionLookupR.execute(frame, genericName, typeR, dispatch.getGroupGenericName(), frame.materialize(), null); - } catch (NoGenericMethodException e) { - // fall-through - } - } - } - - Result result; - RStringVector dotMethod; - if (resultL == null) { - if (resultR == null) { - result = null; - dotMethod = null; - } else { - result = resultR; - dotMethod = RDataFactory.createStringVector(new String[]{"", result.targetFunctionName}, true); - } - } else { - if (resultR == null) { - result = resultL; - dotMethod = RDataFactory.createStringVector(new String[]{result.targetFunctionName, ""}, true); - } else { - if (mismatchProfile.profile(resultL.function != resultR.function)) { - RError.warning(this, RError.Message.INCOMPATIBLE_METHODS, resultL.targetFunctionName, resultR.targetFunctionName, genericName); - result = null; - dotMethod = null; - } else { - result = resultL; - dotMethod = RDataFactory.createStringVector(new String[]{result.targetFunctionName, result.targetFunctionName}, true); - } - } - } - ArgumentsSignature signature = argAndNames.getSignature(); - S3Args s3Args; - RFunction function; - String functionName; - if (result == null) { - s3Args = null; - function = builtinFunction; - functionName = function.getName(); - } else { - s3Args = new S3Args(genericName, result.clazz, dotMethod, frame.materialize(), null, result.groupMatch ? dispatch.getGroupGenericName() : null); - function = result.function; - functionName = result.targetFunctionName; - } - if (function == null) { - CompilerDirectives.transferToInterpreter(); - throw RError.nyi(this, "missing builtin function '" + genericName + "'"); - } - return callMatcher.execute(frame, signature, evaluatedArgs, function, functionName, s3Args); - } - - @Override - public RSyntaxElement getSyntaxLHS() { - return RSyntaxLookup.createDummyLookup(null, fixedGenericName, true); - } - - @Override - public RSyntaxElement[] getSyntaxArguments() { - return callArgsNode.getSyntaxArguments(); - } - - @Override - public ArgumentsSignature getSyntaxSignature() { - return callArgsNode.getSignature(); - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/MatchedArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/MatchedArguments.java index 9e248913f67f10c404ff3c20c33f9eae0296d190..fc5b9b5e975fc9b99616cf0475af00f804467b2f 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/MatchedArguments.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/MatchedArguments.java @@ -27,7 +27,6 @@ import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; -import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; /** @@ -43,41 +42,10 @@ import com.oracle.truffle.r.runtime.nodes.RNode; */ public final class MatchedArguments extends Arguments<RNode> { - static final class MatchedArgumentsNode extends RBaseNode { - @Children private final RNode[] arguments; - private final ArgumentsSignature signature; - - private MatchedArgumentsNode(RNode[] arguments, ArgumentsSignature signature) { - this.arguments = arguments; - this.signature = signature; - } - - @ExplodeLoop - Object[] executeArray(VirtualFrame frame) { - Object[] result = new Object[arguments.length]; - for (int i = 0; i < arguments.length; i++) { - result[i] = arguments[i].execute(frame); - } - return result; - } - - public ArgumentsSignature getSignature() { - return signature; - } - - public RNode[] getArguments() { - return arguments; - } - } - private MatchedArguments(RNode[] arguments, ArgumentsSignature signature) { super(arguments, signature); } - MatchedArgumentsNode createNode() { - return new MatchedArgumentsNode(getArguments(), getSignature()); - } - /** * @return A fresh {@link MatchedArguments}; arguments may contain <code>null</code> iff there * is neither a supplied argument nor a default argument diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java index d6e92ce33586dd86896418df7f3e82985033c69d..7117b9d93ec754301f8f7e949ca6323419441b4a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java @@ -24,15 +24,18 @@ package com.oracle.truffle.r.nodes.function; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; -import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; 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.RootCallTarget; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.NodeChild; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotTypeException; import com.oracle.truffle.api.frame.MaterializedFrame; @@ -41,26 +44,33 @@ import com.oracle.truffle.api.interop.ForeignAccess; import com.oracle.truffle.api.interop.Message; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.nodes.DirectCallNode; -import com.oracle.truffle.api.nodes.IndirectCallNode; +import com.oracle.truffle.api.nodes.ExplodeLoop; import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.nodes.NodeCloneable; import com.oracle.truffle.api.nodes.NodeCost; import com.oracle.truffle.api.nodes.NodeInfo; import com.oracle.truffle.api.nodes.NodeUtil; import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.nodes.UnexpectedResultException; 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.api.source.SourceSection; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.FrameSlotNode; +import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.RBuiltinRootNode; -import com.oracle.truffle.r.nodes.function.MatchedArguments.MatchedArgumentsNode; +import com.oracle.truffle.r.nodes.function.PromiseHelperNode.PromiseCheckHelperNode; +import com.oracle.truffle.r.nodes.function.RCallNodeGen.FunctionDispatchNodeGen; +import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.NoGenericMethodException; import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result; +import com.oracle.truffle.r.nodes.function.call.PrepareArguments; import com.oracle.truffle.r.nodes.function.signature.RArgumentsNode; +import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode; +import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RArguments; @@ -76,9 +86,13 @@ import com.oracle.truffle.r.runtime.RSerialize; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RBuiltinDescriptor; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.REmpty; import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.RMissing; import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.RPromise.OptType; +import com.oracle.truffle.r.runtime.data.RPromise.PromiseType; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -86,182 +100,108 @@ import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RFastPathNode; import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.nodes.RSourceSectionNode; import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -/** - * This class denotes a call site to a function,e.g.: - * - * <pre> - * f(a, b, c) - * </pre> - * <p> - * To avoid repeated work on each call, {@link CachedCallNode} class together with - * {@link UninitializedCallNode} forms the basis for the polymorphic inline cache (PIC) used to - * cache argument nodes on the call site of a function call. - * </p> - * There are two problems we're facing which are the reason for the caching: - * <ol> - * <li>on some call sites the function may change between executions</li> - * <li>for call sites taking "..." as an argument the actual argument list passed into the function - * may change each call (note that this is totally independent of the problem which function is to - * be called)</li> - * </ol> - * <p> - * Problem 1 can be tackled by a the use of an {@link IndirectCallNode} instead of a - * {@link DirectCallNode} which is not as performant as the latter but has no further disadvantages. - * But as the function changed its formal parameters changed, too, so a re-match has to be done as - * well, which involves the creation of nodes and thus must happen on the {@link TruffleBoundary}. - * <br/> - * Problem 2 is not that easy, too: It is solved by reading the values associated with "..." (which - * are Promises) and wrapping them in newly created {@link RNode}s. These nodes get inserted into - * the arguments list ({@link CallArgumentsNode#executeFlatten(Frame)}) - which needs to be be - * matched against the formal parameters again, as theses arguments may carry names as well which - * may have an impact on argument order. As matching involves node creation, it has to happen on the - * {@link TruffleBoundary}. - * </p> - * To avoid repeated node creations as much as possible by caching two interwoven PICs are - * implemented. The caches are constructed using the following classes: - * - * <pre> - * U = {@link UninitializedCallNode}: Forms the uninitialized end of the function PIC - * D = {@link DispatchedCallNode}: Function fixed, no varargs - * G = {@link GenericCallNode}: Function arbitrary - * - * UV = {@link UninitializedCallNode} with varargs, - * UVC = {@link UninitializedVarArgsCacheCallNode} with varargs, for varargs cache - * DV = {@link DispatchedVarArgsCallNode}: Function fixed, with cached varargs - * DGV = {@link DispatchedGenericVarArgsCallNode}: Function fixed, with arbitrary varargs (generic case) - * - * (RB = {@link RBuiltinNode}: individual functions that are builtins are represented by this node - * which is not aware of caching). Due to {@link CachedCallNode} (see below) this is transparent to - * the cache and just behaves like a D/DGV) - * </pre> - * - * As the property "takes varargs as argument" is static for each call site, we effectively end up - * with two separate cache structures. Some examples of each are depicted below: - * - * <pre> - * non varargs, max depth: - * | - * D-D-D-U - * - * no varargs, generic (if max depth is exceeded): - * | - * D-D-D-D-G - * - * varargs: - * | - * DV-DV-UV <- function call target identity level cache - * | - * DV - * | - * UVC <- varargs signature level cache - * - * varargs, max varargs depth exceeded: - * | - * DV-DV-UV - * | - * DV - * | - * DV - * | - * DV - * | - * DGV - * - * varargs, max function depth exceeded: - * | - * DV-DV-DV-DV-GV - * </pre> - * <p> - * In the diagrams above every horizontal connection "-" is in fact established by a separate node: - * {@link CachedCallNode}, which encapsulates the check for function call target identity. So the 1. - * example in fact looks like this: - * - * <pre> - * | - * C-C-C-U - * | | | - * D D D - * </pre> - * - * This is useful as it avoids repetition and allows child nodes to be more concise. It is also - * needed as there are {@link RCallNode} implementations that are not aware of caching, e.g. - * {@link RBuiltinNode}, which may be part of the cache. Note that varargs cache nodes ( - * {@link DispatchedVarArgsCallNode}, the nodes connected by "|") handle the check for varargs value - * identity by itself. - * </p> - * - * As the two problems of changing arguments and changing functions are totally independent as - * described above, it would be possible to use two totally separate caching infrastructures. The - * reason for the current choice is the expectation that R users will try to call same functions - * with the same arguments, and there will very rarely be the case that the same arguments get - * passed via "..." to the same functions. - * - */ -@NodeInfo(cost = NodeCost.NONE) -public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, RSyntaxCall, RCaller { - - private static final int FUNCTION_INLINE_CACHE_SIZE = 4; - private static final int VARARGS_INLINE_CACHE_SIZE = 4; +class ForcePromiseNode extends RNode { - @Child private RNode functionNode; + @Child private RNode valueNode; @Child private PromiseHelperNode promiseHelper; - @Child private RootCallNode call; - @Child private RootCallNode internalDispatchCall; - @Child private RNode dispatchArgument; - @Child private TemporarySlotNode dispatchTempSlot; - @Child private S3FunctionLookupNode dispatchLookup; - @Child private ClassHierarchyNode classHierarchyNode; - @Child private GroupDispatchNode groupDispatchNode; + private final BranchProfile nonPromiseProfile = BranchProfile.create(); - /** - * The {@link #arguments} field must be cloned by {@link NodeUtil#cloneNode(Node)}. - */ - private static class SyntaxArguments extends NodeCloneable { - private final RSyntaxNode[] v; + ForcePromiseNode(RNode valueNode) { + this.valueNode = valueNode; + } - SyntaxArguments(RSyntaxNode[] arguments) { - this.v = arguments; - } + public RNode getValueNode() { + return valueNode; + } - @Override - protected Object clone() { - SyntaxArguments sa = new SyntaxArguments(new RSyntaxNode[v.length]); - for (int i = 0; i < v.length; i++) { - if (v[i] != null) { - RSyntaxNode viClone = (RSyntaxNode) RASTUtils.cloneNode(v[i].asRNode()); - sa.v[i] = viClone; - } + @Override + public Object execute(VirtualFrame frame) { + Object value = valueNode.execute(frame); + if (value instanceof RPromise) { + if (promiseHelper == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + promiseHelper = insert(new PromiseHelperNode()); } - return sa; + return promiseHelper.evaluate(frame, (RPromise) value); + } else { + nonPromiseProfile.enter(); + return value; } } +} + +interface CallWithCallerFrame extends RCaller { + boolean setNeedsCallerFrame(); +} + +@NodeInfo(cost = NodeCost.NONE) +@NodeChild(value = "function", type = ForcePromiseNode.class) +public abstract class RCallNode extends RNode implements RSyntaxNode, RSyntaxCall, RCaller { + + // currently cannot be RSourceSectionNode because of TruffleDSL restrictions + + @CompilationFinal private SourceSection sourceSectionR; + + @Override + public final void setSourceSection(SourceSection sourceSection) { + assert sourceSection != null; + this.sourceSectionR = sourceSection; + } - private final SyntaxArguments arguments; + @Override + public final SourceSection getSourceSection() { + return sourceSectionR; + } + + public abstract Object execute(VirtualFrame frame, Object function); + + protected abstract ForcePromiseNode getFunction(); + + private final RSyntaxNode[] arguments; + private final int[] varArgIndexes; private final ArgumentsSignature signature; + @Child private ReadVariableNode lookupVarArgs; + protected final LocalReadVariableNode explicitArgs; + + // needed for INTERNAL_GENERIC calls: + @Child private FunctionDispatch internalDispatchCall; + + @CompilationFinal private boolean needsCallerFrame; + + boolean setNeedsCallerFrame() { + try { + return needsCallerFrame; + } finally { + needsCallerFrame = true; + } + } - private final ValueProfile builtinProfile = ValueProfile.createIdentityProfile(); - private final ConditionProfile implicitTypeProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile resultIsBuiltinProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile isPromiseProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile normalDispatchProfile = BranchProfile.create(); - private final BranchProfile errorProfile = BranchProfile.create(); - private final ConditionProfile isRFunctionProfile = ConditionProfile.createBinaryProfile(); + @Override + public RSyntaxNode getSyntaxNode() { + return this; + } - @Child private Node foreignCall; - @CompilationFinal private int foreignCallArgCount; - @Child private CallArgumentsNode foreignCallArguments; + protected RCaller createCaller(VirtualFrame frame, RFunction function) { + if (explicitArgs == null) { + return this; + } else { + return new RCallerHelper.Representation(function, (RArgsValuesAndNames) explicitArgs.execute(frame)); + } + } - private RCallNode(SourceSection sourceSection, RNode function, RSyntaxNode[] arguments, ArgumentsSignature signature) { - super(sourceSection); - this.functionNode = function; - this.arguments = new SyntaxArguments(arguments); + protected RCallNode(SourceSection sourceSection, RSyntaxNode[] arguments, ArgumentsSignature signature) { + assert sourceSection != null; + this.sourceSectionR = sourceSection; + this.arguments = arguments; + this.explicitArgs = null; + this.varArgIndexes = getVarArgIndexes(arguments); + this.lookupVarArgs = varArgIndexes.length == 0 ? null : ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any); for (String name : signature) { if (name != null && name.isEmpty()) { @@ -275,172 +215,357 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, this.signature = signature; } - @Override - public RSyntaxNode getSyntaxNode() { - return this; + protected RCallNode(SourceSection sourceSection, Object explicitArgsIdentifier) { + assert sourceSection != null; + this.sourceSectionR = sourceSection; + this.arguments = null; + this.explicitArgs = LocalReadVariableNode.create(explicitArgsIdentifier, false); + this.varArgIndexes = null; + this.lookupVarArgs = null; + this.signature = null; + } + + public static int[] getVarArgIndexes(RSyntaxNode[] arguments) { + List<Integer> varArgsSymbolIndices = new ArrayList<>(); + for (int i = 0; i < arguments.length; i++) { + RSyntaxNode arg = arguments[i]; + if (arg instanceof RSyntaxLookup) { + RSyntaxLookup lookup = (RSyntaxLookup) arg; + // Check for presence of "..." in the arguments + if (ArgumentsSignature.VARARG_NAME.equals(lookup.getIdentifier())) { + varArgsSymbolIndices.add(i); + } + } + } + // Setup and return + int[] varArgsSymbolIndicesArr = new int[varArgsSymbolIndices.size()]; + for (int i = 0; i < varArgsSymbolIndicesArr.length; i++) { + varArgsSymbolIndicesArr[i] = varArgsSymbolIndices.get(i); + } + return varArgsSymbolIndicesArr; } public Arguments<RSyntaxNode> getArguments() { - return new Arguments<>(arguments.v, signature); + return new Arguments<>(arguments, signature); } - public int getArgumentCount() { - return arguments.v.length; + private RArgsValuesAndNames lookupVarArgs(VirtualFrame frame) { + if (explicitArgs != null) { + return (RArgsValuesAndNames) explicitArgs.execute(frame); + } + RArgsValuesAndNames varArgs; + if (lookupVarArgs == null) { + varArgs = null; + } else { + try { + varArgs = lookupVarArgs.executeRArgsValuesAndNames(frame); + } catch (UnexpectedResultException e) { + throw RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT); + } + } + return varArgs; } - public RSyntaxNode getArgument(int index) { - return arguments.v[index]; + protected FunctionDispatch createUninitializedCall() { + return FunctionDispatchNodeGen.create(this, null, explicitArgs == null ? false : true); } - @Override - public Object execute(VirtualFrame frame) { - return execute(frame, executeFunctionNode(frame)); + protected FunctionDispatch createUninitializedExplicitCall() { + return FunctionDispatchNodeGen.create(this, null, true); } - @TruffleBoundary - private static String getMessage(Throwable e) { - return e.getMessage() != null ? e.getMessage() : e.toString(); + /** + * If there are no parameters, or the target function does not refer to a builtin, or the + * builtin has no special dispatching, then we know that we will just call the function with no + * special dispatch logic. + */ + protected boolean isDefaultDispatch(RFunction function) { + return (signature != null && signature.isEmpty()) || function.getRBuiltin() == null || function.getRBuiltin().getDispatch() == RDispatch.DEFAULT; } - @Override - public Node deepCopy() { - RCallNode copy = (RCallNode) super.deepCopy(); - // execution (frame) specific due to temp identifiers, so reset - copy.internalDispatchCall = null; - return copy; + @Specialization(guards = "isDefaultDispatch(function)") + public Object call(VirtualFrame frame, RFunction function, // + @Cached("createUninitializedCall()") FunctionDispatch call) { + return call.execute(frame, function, lookupVarArgs(frame), null); } - public Object execute(VirtualFrame frame, Object functionObject) { - RFunction function; - if (isRFunctionProfile.profile(functionObject instanceof RFunction)) { - function = (RFunction) functionObject; - // fall through - } else if (functionObject instanceof TruffleObject && !(functionObject instanceof RTypedValue)) { - if (foreignCallArguments == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - foreignCallArguments = insert(createArguments(null, true, true)); + protected RNode createDispatchArgument(int index) { + return new ForcePromiseNode(NodeUtil.cloneNode(arguments[index].asRNode())); + } + + /** + * If the target function refers to a builtin that requires internal generic dispatch and there + * are actual parameters to dispatch on, then we will do an internal generic dispatch on the + * first parameter. + */ + protected boolean isInternalGenericDispatch(RFunction function) { + if (signature != null && signature.isEmpty()) { + return false; + } + RBuiltinDescriptor builtin = function.getRBuiltin(); + return builtin != null && builtin.getDispatch() == RDispatch.INTERNAL_GENERIC; + } + + @Specialization(guards = {"explicitArgs == null", "isInternalGenericDispatch(function)"}) + public Object callInternalGeneric(VirtualFrame frame, RFunction function, // + @Cached("createDispatchArgument(0)") RNode dispatchArgument, // + @Cached("new()") TemporarySlotNode dispatchTempSlot, // + @Cached("create()") ClassHierarchyNode classHierarchyNode, // + @Cached("createWithError()") S3FunctionLookupNode dispatchLookup, // + @Cached("createIdentityProfile()") ValueProfile builtinProfile, // + @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfile, // + @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile) { + RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); + Object dispatchObject = dispatchArgument.execute(frame); + FrameSlot slot = dispatchTempSlot.initialize(frame, dispatchObject, () -> internalDispatchCall = null); + try { + RStringVector type = classHierarchyNode.execute(dispatchObject); + S3Args s3Args; + RFunction resultFunction; + if (implicitTypeProfile.profile(type != null)) { + Result result = dispatchLookup.execute(frame, builtin.getName(), type, null, frame.materialize(), null); + if (resultIsBuiltinProfile.profile(result.function.isBuiltin())) { + s3Args = null; + } else { + s3Args = new S3Args(result.generic, result.clazz, result.targetFunctionName, frame.materialize(), null, null); + } + resultFunction = result.function; + } else { + s3Args = null; + resultFunction = function; } - Object[] argumentsArray = foreignCallArguments.evaluateFlattenObjects(frame); - if (foreignCall == null || foreignCallArgCount != argumentsArray.length) { + if (internalDispatchCall == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - foreignCall = insert(Message.createExecute(argumentsArray.length).createNode()); - foreignCallArgCount = argumentsArray.length; + internalDispatchCall = insert(FunctionDispatchNodeGen.create(this, new Object[]{dispatchTempSlot.getIdentifier()}, false)); } - try { - return ForeignAccess.send(foreignCall, frame, (TruffleObject) functionObject, argumentsArray); - } catch (Throwable e) { - errorProfile.enter(); - throw RError.error(this, RError.Message.GENERIC, "Foreign function failed: " + getMessage(e)); + return internalDispatchCall.execute(frame, resultFunction, lookupVarArgs(frame), s3Args); + } finally { + dispatchTempSlot.cleanup(frame, slot); + } + } + + @Specialization(guards = {"explicitArgs != null", "isInternalGenericDispatch(function)"}) + public Object callInternalGenericExplicit(VirtualFrame frame, RFunction function, // + @Cached("create()") ClassHierarchyNode classHierarchyNode, // + @Cached("createWithError()") S3FunctionLookupNode dispatchLookup, // + @Cached("createIdentityProfile()") ValueProfile builtinProfile, // + @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfile, // + @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile, // + @Cached("createPromiseHelper()") PromiseCheckHelperNode promiseHelperNode, // + @Cached("createUninitializedExplicitCall()") FunctionDispatch call) { + RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); + RArgsValuesAndNames argAndNames = (RArgsValuesAndNames) explicitArgs.execute(frame); + + RStringVector type = argAndNames.isEmpty() ? null : classHierarchyNode.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(0))); + S3Args s3Args; + RFunction resultFunction; + if (implicitTypeProfile.profile(type != null)) { + Result result = dispatchLookup.execute(frame, builtin.getName(), type, null, frame.materialize(), null); + if (resultIsBuiltinProfile.profile(result.function.isBuiltin())) { + s3Args = null; + } else { + s3Args = new S3Args(result.generic, result.clazz, result.targetFunctionName, frame.materialize(), null, null); } + resultFunction = result.function; } else { - errorProfile.enter(); - throw RError.error(RError.SHOW_CALLER, RError.Message.APPLY_NON_FUNCTION); + s3Args = null; + resultFunction = function; } + return call.execute(frame, resultFunction, argAndNames, s3Args); + } - if (!signature.isEmpty() && function.getRBuiltin() != null) { - RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); - RDispatch dispatch = builtin.getDispatch(); - if (dispatch == RDispatch.DEFAULT) { - // fallthrough - } else if (dispatch == RDispatch.INTERNAL_GENERIC) { - if (internalDispatchCall == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - dispatchTempSlot = insert(new TemporarySlotNode()); - dispatchArgument = insert(RASTUtils.cloneNode(arguments.v[0].asRNode())); - dispatchLookup = insert(S3FunctionLookupNode.create(true, false)); - classHierarchyNode = insert(ClassHierarchyNodeGen.create(false, true)); - } - Object dispatchObject = dispatchArgument.execute(frame); - FrameSlot slot = dispatchTempSlot.initialize(frame, dispatchObject, identifier -> internalDispatchCall = insert(new UninitializedCallNode(this, identifier))); + protected CallArgumentsNode createArguments() { + return signature == null ? null : createArguments(null, false, false); + } + + protected ReadVariableNode createVarArgRead(CallArgumentsNode callArguments) { + return callArguments.containsVarArgsSymbol() ? ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any) : null; + } + + protected boolean isGroupGenericDispatch(RFunction function) { + if (signature != null && signature.isEmpty()) { + return false; + } + RBuiltinDescriptor builtin = function.getRBuiltin(); + return builtin != null && builtin.getDispatch().isGroupGeneric(); + } + + protected PromiseCheckHelperNode createPromiseHelper() { + return new PromiseCheckHelperNode(); + } + + @Specialization(guards = "isGroupGenericDispatch(function)") + public Object callGroupGeneric(VirtualFrame frame, RFunction function, // + @Cached("createArguments()") CallArgumentsNode callArguments, // + @Cached("create()") ClassHierarchyNode classHierarchyNodeX, // + @Cached("createWithException()") S3FunctionLookupNode dispatchLookupX, // + @Cached("create()") ClassHierarchyNode classHierarchyNodeY, // + @Cached("createWithException()") S3FunctionLookupNode dispatchLookupY, // + @Cached("createIdentityProfile()") ValueProfile builtinProfile, // + @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfileX, // + @Cached("createBinaryProfile()") ConditionProfile implicitTypeProfileY, // + @Cached("createBinaryProfile()") ConditionProfile mismatchProfile, // + @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile, // + @Cached("createPromiseHelper()") PromiseCheckHelperNode promiseHelperNode, // + @Cached("createUninitializedExplicitCall()") FunctionDispatch call) { + + RArgsValuesAndNames argAndNames = explicitArgs != null ? (RArgsValuesAndNames) explicitArgs.execute(frame) : callArguments.evaluateFlatten(frame, lookupVarArgs(frame)); + + RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin()); + RDispatch dispatch = builtin.getDispatch(); + + RStringVector typeX = classHierarchyNodeX.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(0))); + Result resultX = null; + if (implicitTypeProfileX.profile(typeX != null)) { + try { + resultX = dispatchLookupX.execute(frame, builtin.getName(), typeX, dispatch.getGroupGenericName(), frame.materialize(), null); + } catch (NoGenericMethodException e) { + // fall-through + } + } + Result resultY = null; + if (argAndNames.getLength() > 1 && dispatch == RDispatch.OPS_GROUP_GENERIC) { + RStringVector typeY = classHierarchyNodeY.execute(promiseHelperNode.checkEvaluate(frame, argAndNames.getArgument(1))); + if (implicitTypeProfileY.profile(typeY != null)) { try { - RStringVector type = classHierarchyNode.execute(dispatchObject); - S3Args s3Args; - RFunction resultFunction; - if (implicitTypeProfile.profile(type != null)) { - Result result = dispatchLookup.execute(frame, builtin.getName(), type, null, frame.materialize(), null); - if (resultIsBuiltinProfile.profile(result.function.isBuiltin())) { - s3Args = null; - } else { - s3Args = new S3Args(result.generic, result.clazz, result.targetFunctionName, frame.materialize(), null, null); - } - resultFunction = result.function; - } else { - s3Args = null; - resultFunction = function; - } - return internalDispatchCall.execute(frame, resultFunction, s3Args); - } finally { - dispatchTempSlot.cleanup(frame, slot); + resultY = dispatchLookupY.execute(frame, builtin.getName(), typeY, dispatch.getGroupGenericName(), frame.materialize(), null); + } catch (NoGenericMethodException e) { + // fall-through } + } + } + + Result result; + RStringVector dotMethod; + if (resultX == null) { + if (resultY == null) { + result = null; + dotMethod = null; } else { - assert dispatch.isGroupGeneric(); + result = resultY; + dotMethod = RDataFactory.createStringVector(new String[]{"", result.targetFunctionName}, true); + } + } else { + if (resultY == null) { + result = resultX; + dotMethod = RDataFactory.createStringVector(new String[]{result.targetFunctionName, ""}, true); + } else { + if (mismatchProfile.profile(resultX.function != resultY.function)) { + RError.warning(this, RError.Message.INCOMPATIBLE_METHODS, resultX.targetFunctionName, resultY.targetFunctionName, dispatch.getGroupGenericName()); + result = null; + dotMethod = null; + } else { + result = resultX; + dotMethod = RDataFactory.createStringVector(new String[]{result.targetFunctionName, result.targetFunctionName}, true); + } } } - normalDispatchProfile.enter(); - if (call == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - call = insert(new UninitializedCallNode(this, null)); + S3Args s3Args; + RFunction resultFunction; + if (result == null) { + s3Args = null; + resultFunction = function; + } else { + if (resultIsBuiltinProfile.profile(result.function.isBuiltin())) { + s3Args = null; + } else { + s3Args = new S3Args(builtin.getName(), result.clazz, dotMethod, frame.materialize(), null, result.groupMatch ? dispatch.getGroupGenericName() : null); + } + resultFunction = result.function; } - return call.execute(frame, function, null); + return call.execute(frame, resultFunction, argAndNames, s3Args); } - private Object executeFunctionNode(VirtualFrame frame) { - /** - * Expressions such as "pkg:::f" can result in (delayedAssign) promises that must be - * explicitly resolved. - */ - Object value = functionNode.execute(frame); - if (isPromiseProfile.profile(value instanceof RPromise)) { - if (promiseHelper == null) { + protected class ForeignCall extends Node { + + @Child private CallArgumentsNode arguments; + @Child private Node foreignCall; + @CompilationFinal private int foreignCallArgCount; + + private final BranchProfile errorProfile = BranchProfile.create(); + + public ForeignCall(CallArgumentsNode arguments) { + this.arguments = arguments; + } + + @SuppressWarnings("deprecation") + public Object execute(VirtualFrame frame, TruffleObject function) { + Object[] argumentsArray = explicitArgs != null ? ((RArgsValuesAndNames) explicitArgs.execute(frame)).getArguments() : arguments.evaluateFlattenObjects(frame, lookupVarArgs(frame)); + if (foreignCall == null || foreignCallArgCount != argumentsArray.length) { CompilerDirectives.transferToInterpreterAndInvalidate(); - promiseHelper = insert(new PromiseHelperNode()); + foreignCall = insert(Message.createExecute(argumentsArray.length).createNode()); + foreignCallArgCount = argumentsArray.length; + } + try { + return ForeignAccess.execute(foreignCall, frame, function, argumentsArray); + } catch (Throwable e) { + errorProfile.enter(); + throw RError.error(this, RError.Message.GENERIC, "Foreign function failed: " + e.getMessage() != null ? e.getMessage() : e.toString()); } - value = promiseHelper.evaluate(frame, (RPromise) value); } - return value; + } + + protected ForeignCall createForeignCall() { + return new ForeignCall(createArguments(null, true, true)); + } + + protected static boolean isRTypedValue(Object value) { + return value instanceof RTypedValue; + } + + @Specialization(guards = "!isRTypedValue(function)") + public Object call(VirtualFrame frame, TruffleObject function, // + @Cached("createForeignCall()") ForeignCall foreignCall) { + return foreignCall.execute(frame, function); + } + + @TruffleBoundary + @Fallback + public Object call(@SuppressWarnings("unused") Object function) { + throw RError.error(RError.SHOW_CALLER, RError.Message.APPLY_NON_FUNCTION); } public RNode getFunctionNode() { - if (functionNode != null) { + if (getFunction() != null) { // Only the very 1. RootCallNode on the top level contains the one-and-only function // node - return functionNode; + return getFunction().getValueNode(); } return getParentCallNode().getFunctionNode(); } - public CallArgumentsNode createArguments(Object dispatchTempIdentifier, boolean modeChange, boolean modeChangeAppliesToAll) { - RNode[] args = new RNode[arguments.v.length]; - for (int i = 0; i < arguments.v.length; i++) { - if (i == 0 && dispatchTempIdentifier != null) { - args[0] = new GetTempNode(dispatchTempIdentifier, arguments.v[0]); + public CallArgumentsNode createArguments(Object[] dispatchTempIdentifiers, boolean modeChange, boolean modeChangeAppliesToAll) { + RNode[] args = new RNode[arguments.length]; + for (int i = 0; i < arguments.length; i++) { + if (dispatchTempIdentifiers != null && i < dispatchTempIdentifiers.length) { + args[i] = new GetTempNode(dispatchTempIdentifiers[i], arguments[i]); } else { - args[i] = arguments.v[i] == null ? null : RASTUtils.cloneNode(arguments.v[i].asRNode()); + args[i] = arguments[i] == null ? null : RASTUtils.cloneNode(arguments[i].asRNode()); } } - return CallArgumentsNode.create(modeChange, modeChangeAppliesToAll, args, signature); + return CallArgumentsNode.create(modeChange, modeChangeAppliesToAll, args, signature, varArgIndexes); } @Override public void serializeImpl(RSerialize.State state) { state.setAsLangType(); - state.serializeNodeSetCar(functionNode); - if (isColon(functionNode)) { + state.serializeNodeSetCar(getFunctionNode()); + if (isColon(getFunctionNode())) { // special case, have to translate Strings to Symbols state.openPairList(); - state.setCarAsSymbol(((ReadVariableNode) arguments.v[0]).getIdentifier()); + state.setCarAsSymbol(((ReadVariableNode) arguments[0]).getIdentifier()); state.openPairList(); - state.setCarAsSymbol(((ReadVariableNode) arguments.v[1]).getIdentifier()); + state.setCarAsSymbol(((ReadVariableNode) arguments[1]).getIdentifier()); state.linkPairList(2); state.setCdr(state.closePairList()); } else { - RSyntaxNode f = functionNode.asRSyntaxNode(); + RSyntaxNode f = getFunctionNode().asRSyntaxNode(); boolean infixFieldAccess = false; if (f instanceof RSyntaxLookup) { RSyntaxLookup lookup = (RSyntaxLookup) f; infixFieldAccess = "$".equals(lookup.getIdentifier()) || "@".equals(lookup.getIdentifier()); } - serializeArguments(state, arguments.v, signature, infixFieldAccess); + serializeArguments(state, arguments, signature, infixFieldAccess); } } @@ -490,7 +615,7 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, public RSyntaxNode substituteImpl(REnvironment env) { RNode functionSub = getFunctionNode().substitute(env).asRNode(); - Arguments<RSyntaxNode> argsSub = substituteArguments(env, arguments.v, signature); + Arguments<RSyntaxNode> argsSub = substituteArguments(env, arguments, signature); return RASTUtils.createCall(functionSub, false, argsSub.getSignature(), argsSub.getArguments()); } @@ -521,15 +646,45 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, * Creates a call to a resolved {@link RBuiltinKind#INTERNAL} that will be used to replace the * original call. * - * @param frame The frame to create the inlined builtins in - * @param internalCallArg the {@link UninitializedCallNode} corresponding to the argument to the - * {code .Internal}. + * @param internalCallArg the {@link RCallNode} corresponding to the argument to the {code + * .Internal}. * @param function the resolved {@link RFunction}. - * @param name The name of the function */ - public static LeafCallNode createInternalCall(VirtualFrame frame, RCallNode internalCallArg, RFunction function, String name) { + public static RNode createInternalCall(RCallNode internalCallArg, RFunction function) { CompilerAsserts.neverPartOfCompilation(); - return UninitializedCallNode.createCacheNode(frame, internalCallArg.createArguments(null, false, true), internalCallArg, function); + return new InternalNode(FunctionDispatchNodeGen.create(internalCallArg, null, false), function, internalCallArg.lookupVarArgs != null); + } + + @NodeInfo(cost = NodeCost.NONE) + private static final class InternalNode extends RNode { + @Child private FunctionDispatch rootCallNode; + @Child private ReadVariableNode lookupVarArgs; + private final RFunction function; + + InternalNode(FunctionDispatch rootCallNode, RFunction function, boolean needsVarArgLookup) { + this.rootCallNode = rootCallNode; + this.function = function; + this.lookupVarArgs = needsVarArgLookup ? ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any) : null; + } + + private RArgsValuesAndNames lookupVarArgs(VirtualFrame frame) { + RArgsValuesAndNames varArgs; + if (lookupVarArgs == null) { + varArgs = null; + } else { + try { + varArgs = lookupVarArgs.executeRArgsValuesAndNames(frame); + } catch (UnexpectedResultException e) { + throw RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT); + } + } + return varArgs; + } + + @Override + public Object execute(VirtualFrame frame) { + return rootCallNode.execute(frame, function, lookupVarArgs(frame), null); + } } /** @@ -539,11 +694,11 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, */ @TruffleBoundary public static RCallNode createCloneReplacingArgs(RCallNode call, RSyntaxNode... replacementArgs) { - RSyntaxNode[] args = new RSyntaxNode[call.arguments.v.length]; + RSyntaxNode[] args = new RSyntaxNode[call.arguments.length]; for (int i = 0; i < args.length; i++) { - args[i] = i < replacementArgs.length ? replacementArgs[i] : call.arguments.v[i]; + args[i] = i < replacementArgs.length ? replacementArgs[i] : call.arguments[i]; } - return new RCallNode(call.getSourceSection(), RASTUtils.cloneNode(call.functionNode), args, call.signature); + return RCallNodeGen.create(call.getSourceSection(), args, call.signature, new ForcePromiseNode(RASTUtils.cloneNode(call.getFunction()))); } /** @@ -551,13 +706,17 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, * {@code src == RSyntaxNode.EAGER_DEPARSE} we force a deparse. */ public static RCallNode createCall(SourceSection src, RNode function, ArgumentsSignature signature, RSyntaxNode... arguments) { - RCallNode call = new RCallNode(src, function, arguments, signature); + RCallNode call = RCallNodeGen.create(src, arguments, signature, new ForcePromiseNode(function)); if (src == RSyntaxNode.EAGER_DEPARSE) { RDeparse.ensureSourceSection(call); } return call; } + public static RCallNode createExplicitCall(Object explicitArgsIdentifier) { + return RCallNodeGen.create(RSyntaxNode.INTERNAL, explicitArgsIdentifier, null); + } + static RBuiltinRootNode findBuiltinRootNode(RootCallTarget callTarget) { RootNode root = callTarget.getRootNode(); if (root instanceof RBuiltinRootNode) { @@ -584,12 +743,6 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, return false; } - public abstract static class RootCallNode extends Node { - - public abstract Object execute(VirtualFrame frame, RFunction function, S3Args s3Args); - - } - private static final class GetTempNode extends RNode { @Child private FrameSlotNode slot; @@ -615,138 +768,83 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, } } - /** - * [U]/[UV] Forms the uninitialized end of the function PIC. - * - * @see RCallNode - */ - @NodeInfo(cost = NodeCost.UNINITIALIZED) - private static final class UninitializedCallNode extends RootCallNode { + public abstract static class FunctionDispatch extends Node { - private int depth; - private final RCallNode call; - private final Object dispatchTempIdentifier; + public abstract Object execute(VirtualFrame frame, RFunction function, Object varArgs, Object s3Args); - UninitializedCallNode(RCallNode call, Object dispatchTempIdentifier) { - this.call = call; - this.dispatchTempIdentifier = dispatchTempIdentifier; - this.depth = 0; - } + protected static final int CACHE_SIZE = 4; - @Override - public Object execute(VirtualFrame frame, RFunction function, S3Args s3Args) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - depth++; - RootCallNode next = depth < FUNCTION_INLINE_CACHE_SIZE ? this : new GenericCallNode(call.createArguments(dispatchTempIdentifier, true, true), call); - - RBuiltinDescriptor builtin = function.getRBuiltin(); - boolean modeChange = true; - if (builtin != null) { - modeChange = false; - } + private final RCallNode originalCall; + private final Object[] dispatchTempIdentifiers; + private final boolean explicitArgs; - LeafCallNode current = createCacheNode(frame, call.createArguments(dispatchTempIdentifier, modeChange, true), call, function); - RootCallNode cachedNode = new CachedCallNode(current, next, function); - this.replace(cachedNode); - return cachedNode.execute(frame, function, s3Args); + public FunctionDispatch(RCallNode originalCall, Object[] dispatchTempIdentifiers, boolean explicitArgs) { + this.originalCall = originalCall; + this.dispatchTempIdentifiers = dispatchTempIdentifiers; + this.explicitArgs = explicitArgs; } - private static LeafCallNode createCacheNode(VirtualFrame frame, CallArgumentsNode args, RCallNode creator, RFunction function) { - CompilerDirectives.transferToInterpreter(); - - LeafCallNode callNode = null; - // Check implementation: If written in Java, handle differently! + protected LeafCallNode createCacheNode(RFunction function) { + CompilerAsserts.neverPartOfCompilation(); + FormalArguments formals = ((RRootNode) function.getTarget().getRootNode()).getFormalArguments(); if (function.isBuiltin()) { - RootCallTarget callTarget = function.getTarget(); - RBuiltinRootNode root = findBuiltinRootNode(callTarget); - assert root != null; - - // We inline the given arguments here, as builtins are executed inside the same - // frame as they are called. - RNode[] inlinedArgs = ArgumentMatcher.matchArgumentsInlined(function, args, creator); - callNode = new BuiltinCallNode(root.inline(inlinedArgs), creator); + return new BuiltinCallNode(RBuiltinNode.inline(function.getRBuiltin(), null), function.getRBuiltin(), formals, originalCall); } else { - // Now we need to distinguish: Do supplied arguments vary between calls? - if (args.containsVarArgsSymbol()) { - VarArgsCacheCallNode nextNode = new UninitializedVarArgsCacheCallNode(args, creator); - ArgumentsSignature varArgsSignature = CallArgumentsNode.getVarargsAndNames(frame).getSignature(); - callNode = DispatchedVarArgsCallNode.create(frame, args, nextNode, creator, function, varArgsSignature); - } else { - MatchedArguments matchedArgs = ArgumentMatcher.matchArguments(function, args, creator, false); - callNode = new DispatchedCallNode(function, matchedArgs, creator); - } + return new DispatchedCallNode(function, formals.getSignature(), originalCall); } - - return callNode; } - } - - /** - * [C] Extracts the check for function call target identity away from the individual cache - * nodes. - * - * @see RCallNode - */ - private static final class CachedCallNode extends RootCallNode { - - @Child private RootCallNode nextNode; - @Child private LeafCallNode currentNode; - - private final CallTarget cachedCallTarget; - CachedCallNode(LeafCallNode current, RootCallNode next, RFunction cachedFunction) { - this.currentNode = current; - this.nextNode = next; - this.cachedCallTarget = cachedFunction.getTarget(); + protected PrepareArguments createArguments(RFunction function) { + if (explicitArgs) { + return PrepareArguments.createExplicit(function); + } else { + CallArgumentsNode args = originalCall.createArguments(dispatchTempIdentifiers, !function.isBuiltin(), true); + return PrepareArguments.create(function, args); + } } - @Override - public Object execute(VirtualFrame frame, RFunction f, S3Args s3Args) { - if (cachedCallTarget == f.getTarget()) { - return currentNode.execute(frame, f, s3Args); - } - return nextNode.execute(frame, f, s3Args); + @Specialization(limit = "CACHE_SIZE", guards = "function == cachedFunction") + protected Object dispatch(VirtualFrame frame, @SuppressWarnings("unused") RFunction function, Object varArgs, Object s3Args, // + @Cached("function") RFunction cachedFunction, // + @Cached("createCacheNode(cachedFunction)") LeafCallNode leafCall, // + @Cached("createArguments(cachedFunction)") PrepareArguments prepareArguments) { + Object[] orderedArguments = prepareArguments.execute(frame, (RArgsValuesAndNames) varArgs, originalCall); + return leafCall.execute(frame, cachedFunction, orderedArguments, (S3Args) s3Args); } - } - /** - * [GV] {@link RCallNode} in case there is no fixed {@link RFunction} AND varargs... - * - * @see RCallNode - */ - private static final class GenericCallNode extends RootCallNode { + /* + * Use a TruffleBoundaryNode to be able to switch child nodes without invalidating the whole + * method. + */ + protected final class GenericCall extends TruffleBoundaryNode { - @Child private IndirectCallNode indirectCall = Truffle.getRuntime().createIndirectCallNode(); - @Child private CallArgumentsNode arguments; + private RFunction cachedFunction; + @Child private LeafCallNode leafCall; + @Child private PrepareArguments prepareArguments; - private final RCallNode call; + @TruffleBoundary + public Object execute(MaterializedFrame materializedFrame, RFunction function, Object varArgs, Object s3Args) { + if (cachedFunction != function) { + leafCall = insert(createCacheNode(function)); + prepareArguments = insert(createArguments(function)); + } + VirtualFrame frame = SubstituteVirtualFrame.create(materializedFrame); + Object[] orderedArguments = prepareArguments.execute(frame, (RArgsValuesAndNames) varArgs, originalCall); + return leafCall.execute(frame, cachedFunction, orderedArguments, (S3Args) s3Args); + } + } - GenericCallNode(CallArgumentsNode arguments, RCallNode call) { - // here, it's safe to reuse the arguments - it's the final use - this.arguments = arguments; - this.call = call; + protected GenericCall createGenericCall() { + return new GenericCall(); } - @Override - public Object execute(VirtualFrame frame, RFunction currentFunction, S3Args s3Args) { - CompilerDirectives.transferToInterpreter(); - // Function and arguments may change every call: Flatt'n'Match on SlowPath! :-/ - UnrolledVariadicArguments argsValuesAndNames = arguments.executeFlatten(frame); - MatchedArguments matchedArgs = ArgumentMatcher.matchArguments(currentFunction, argsValuesAndNames, RError.ROOTNODE, true); - - Object[] argsObject = RArguments.create(currentFunction, call, null, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame), matchedArgs.doExecuteArray(frame), - matchedArgs.getSignature(), s3Args); - return indirectCall.call(frame, currentFunction.getTarget(), argsObject); + @Specialization + protected Object dispatchFallback(VirtualFrame frame, RFunction function, Object varArgs, Object s3Args, // + @Cached("createGenericCall()") GenericCall generic) { + return generic.execute(frame.materialize(), function, varArgs, s3Args); } } - /** - * This is the counterpart of {@link RCallNode}: While that is the base class for all top-level - * nodes (C, G, U and GV), this is the base class for all nodes not on the top level of the PIC - * (and thus don't need all information, but can rely on their parents to have them). - * - * @see RCallNode - */ public abstract static class LeafCallNode extends RBaseNode { /** * The original {@link RSyntaxNode} this derives from. @@ -762,297 +860,162 @@ public final class RCallNode extends RSourceSectionNode implements RSyntaxNode, return originalCall; } - public abstract Object execute(VirtualFrame frame, RFunction function, S3Args s3Args); + public abstract Object execute(VirtualFrame frame, RFunction function, Object[] orderedArguments, S3Args s3Args); } @NodeInfo(cost = NodeCost.NONE) private static final class BuiltinCallNode extends LeafCallNode { @Child private RBuiltinNode builtin; + @Child private PromiseCheckHelperNode promiseHelper; + @Children private final CastNode[] casts; - BuiltinCallNode(RBuiltinNode builtin, RCallNode originalCall) { - super(originalCall); - this.builtin = builtin; - } - - @Override - public Object execute(VirtualFrame frame, RFunction currentFunction, S3Args s3Args) { - return builtin.execute(frame); - } - } - - public interface CallWithCallerFrame { - boolean setNeedsCallerFrame(); - } - - /** - * [D] A {@link RCallNode} for calls to fixed {@link RFunction}s with fixed arguments (no - * varargs). - * - * @see RCallNode - */ - private static final class DispatchedCallNode extends LeafCallNode implements CallWithCallerFrame { - - @Child private DirectCallNode call; - @Child private MatchedArgumentsNode matchedArgs; - @Child private RArgumentsNode argsNode = RArgumentsNode.create(); - @Child private RFastPathNode fastPath; - - @CompilationFinal private boolean needsCallerFrame; - private final RootCallTarget callTarget; - @CompilationFinal private boolean needsSplitting; + private final BranchProfile emptyProfile = BranchProfile.create(); + private final BranchProfile varArgsProfile = BranchProfile.create(); + private final ConditionProfile wrapProfile = ConditionProfile.createBinaryProfile(); + private final FormalArguments formals; + private final RBuiltinDescriptor builtinDescriptor; - DispatchedCallNode(RFunction function, MatchedArguments matchedArgs, RCallNode originalCall) { + BuiltinCallNode(RBuiltinNode builtin, RBuiltinDescriptor builtinDescriptor, FormalArguments formalArguments, RCallNode originalCall) { super(originalCall); - this.matchedArgs = matchedArgs.createNode(); - this.needsCallerFrame = function.containsDispatch(); - this.needsSplitting = needsSplitting(function); - this.callTarget = function.getTarget(); + this.builtin = builtin; + this.builtinDescriptor = builtinDescriptor; + this.casts = builtin.getCasts(); + this.formals = formalArguments; + } + + @ExplodeLoop + public Object[] castArguments(VirtualFrame frame, Object[] args) { + int argCount = formals.getLength(); + Object[] result = new Object[argCount]; + for (int i = 0; i < argCount; i++) { + Object arg = args[i]; + if (arg == REmpty.instance) { + emptyProfile.enter(); + arg = formals.getInternalDefaultArgumentAt(i); + } + if (arg instanceof RArgsValuesAndNames) { + varArgsProfile.enter(); + RArgsValuesAndNames varArgs = (RArgsValuesAndNames) arg; + if (builtinDescriptor.evaluatesArg(i)) { + forcePromises(frame, varArgs); + } else { + wrapPromises(varArgs); + } + } else { + if (builtinDescriptor.evaluatesArg(i)) { + if (arg instanceof RPromise) { + if (promiseHelper == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + promiseHelper = insert(new PromiseCheckHelperNode()); + } + arg = promiseHelper.checkEvaluate(frame, arg); - this.fastPath = function.getFastPath() == null ? null : function.getFastPath().create(); - if (fastPath == null) { - this.call = Truffle.getRuntime().createDirectCallNode(function.getTarget()); + } + if (i < casts.length && casts[i] != null) { + assert builtinDescriptor.evaluatesArg(i); + arg = casts[i].execute(arg); + } + } else { + assert casts.length <= i || casts[i] == null : "no casts allowed on non-evaluated arguments"; + if (wrapProfile.profile(!(arg instanceof RPromise || arg instanceof RMissing))) { + arg = createPromise(arg); + } + } + } + result[i] = arg; } + return result; } - @Override - public Object execute(VirtualFrame frame, RFunction currentFunction, S3Args s3Args) { - if (fastPath != null) { - Object[] argValues = matchedArgs.executeArray(frame); - Object result = fastPath.execute(frame, argValues); - if (result != null) { - return result; + private void forcePromises(VirtualFrame frame, RArgsValuesAndNames varArgs) { + Object[] array = varArgs.getArguments(); + for (int i = 0; i < array.length; i++) { + if (promiseHelper == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + promiseHelper = insert(new PromiseCheckHelperNode()); } - CompilerDirectives.transferToInterpreterAndInvalidate(); - fastPath = null; - call = insert(Truffle.getRuntime().createDirectCallNode(callTarget)); - } - - if (needsSplitting) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - needsSplitting = false; - call.cloneCallTarget(); + array[i] = promiseHelper.checkEvaluate(frame, array[i]); } - MaterializedFrame callerFrame = needsCallerFrame ? frame.materialize() : null; - - Object[] argsObject = argsNode.execute(currentFunction, originalCall, callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame), - matchedArgs.executeArray(frame), - matchedArgs.getSignature(), s3Args); - return call.call(frame, argsObject); } - @Override - public boolean setNeedsCallerFrame() { - try { - return needsCallerFrame; - } finally { - needsCallerFrame = true; + @TruffleBoundary + private static void wrapPromises(RArgsValuesAndNames varArgs) { + Object[] array = varArgs.getArguments(); + for (int i = 0; i < array.length; i++) { + Object arg = array[i]; + if (!(arg instanceof RPromise || arg instanceof RMissing)) { + array[i] = createPromise(arg); + } } } - } - - /* - * Varargs cache classes follow - */ - - /** - * Base class for the varargs cache [UVC] and [DV]. - * - * @see RCallNode - */ - private abstract static class VarArgsCacheCallNode extends LeafCallNode { - - @Child private ReadVariableNode lookupVarArgs = ReadVariableNode.createSilent(ArgumentsSignature.VARARG_NAME, RType.Any); - private VarArgsCacheCallNode(RCallNode originalCallNode) { - super(originalCallNode); + @TruffleBoundary + private static Object createPromise(Object arg) { + return RDataFactory.createPromise(PromiseType.NO_ARG, OptType.PROMISED, ConstantNode.create(arg), arg); } @Override - public final Object execute(VirtualFrame frame, RFunction function, S3Args s3Args) { - Object varArgs = lookupVarArgs.execute(frame); - if (varArgs == RNull.instance) { - varArgs = RArgsValuesAndNames.EMPTY; - } - if (varArgs == null || !(varArgs instanceof RArgsValuesAndNames)) { - CompilerDirectives.transferToInterpreter(); - RError.error(RError.SHOW_CALLER, RError.Message.NO_DOT_DOT_DOT); - } - return execute(frame, function, ((RArgsValuesAndNames) varArgs).getSignature(), s3Args); + public Object execute(VirtualFrame frame, RFunction currentFunction, Object[] orderedArguments, S3Args s3Args) { + return builtin.execute(frame, castArguments(frame, orderedArguments)); } - - protected abstract Object execute(VirtualFrame frame, RFunction function, ArgumentsSignature varArgsSignature, S3Args s3Args); } - /** - * [UVC] The uninitialized end of the varargs cache. - * - * @see RCallNode - */ - @NodeInfo(cost = NodeCost.UNINITIALIZED) - private static final class UninitializedVarArgsCacheCallNode extends VarArgsCacheCallNode { - @Child private CallArgumentsNode args; - private int depth = 1; // varargs cached is started with a [DV] DispatchedVarArgsCallNode - - UninitializedVarArgsCacheCallNode(CallArgumentsNode args, RCallNode creator) { - super(creator); - this.args = args; - } - - @Override - public Object execute(VirtualFrame frame, RFunction function, ArgumentsSignature varArgsSignature, S3Args s3Args) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - - // Extend cache - this.depth += 1; - CallArgumentsNode clonedArgs = RASTUtils.cloneNode(args); - VarArgsCacheCallNode next = createNextNode(function); - DispatchedVarArgsCallNode newCallNode = DispatchedVarArgsCallNode.create(frame, clonedArgs, next, this, function, varArgsSignature); - return replace(newCallNode).execute(frame, function, varArgsSignature, s3Args); - } - - private VarArgsCacheCallNode createNextNode(RFunction function) { - if (depth < VARARGS_INLINE_CACHE_SIZE) { - return this; - } else { - CallArgumentsNode clonedArgs = RASTUtils.cloneNode(args); - return new DispatchedGenericVarArgsCallNode(function, clonedArgs, originalCall); - } - } - } + private static final class DispatchedCallNode extends LeafCallNode { - /** - * [DV] A {@link RCallNode} for calls to cached {@link RFunction}s with cached varargs. - * - * @see RCallNode - */ - private static final class DispatchedVarArgsCallNode extends VarArgsCacheCallNode implements CallWithCallerFrame { @Child private DirectCallNode call; - @Child private CallArgumentsNode args; - @Child private VarArgsCacheCallNode next; - @Child private MatchedArgumentsNode matchedArgs; - @Child private RArgumentsNode argsNode = RArgumentsNode.create(); + @Child private RArgumentsNode argsNode; + @Child private RFastPathNode fastPath; - private final ArgumentsSignature cachedSignature; - @CompilationFinal private boolean needsCallerFrame; - @CompilationFinal private boolean needsSplitting; + private final ArgumentsSignature signature; + private final RFunction cachedFunction; - protected DispatchedVarArgsCallNode(CallArgumentsNode args, VarArgsCacheCallNode next, RFunction function, ArgumentsSignature varArgsSignature, MatchedArguments matchedArgs, - RCallNode originalCall) { + DispatchedCallNode(RFunction function, ArgumentsSignature signature, RCallNode originalCall) { super(originalCall); - this.call = Truffle.getRuntime().createDirectCallNode(function.getTarget()); - this.args = args; - this.next = next; - this.cachedSignature = varArgsSignature; - this.matchedArgs = matchedArgs.createNode(); - this.needsCallerFrame = function.containsDispatch(); - /* - * this is a simple heuristic - methods that need a caller frame should have call site - - * specific versions - */ - this.needsSplitting = needsSplitting(function); - } - - protected static DispatchedVarArgsCallNode create(VirtualFrame frame, CallArgumentsNode args, VarArgsCacheCallNode next, RBaseNode creator, RFunction function, - ArgumentsSignature varArgsSignature) { - UnrolledVariadicArguments unrolledArguments = args.executeFlatten(frame); - MatchedArguments matchedArgs = ArgumentMatcher.matchArguments(function, unrolledArguments, creator, false); - RCallNode originalCall; - if (creator instanceof LeafCallNode) { - originalCall = ((LeafCallNode) creator).originalCall; - } else if (creator instanceof RCallNode) { - originalCall = (RCallNode) creator; - } else { - throw RInternalError.shouldNotReachHere(); - } - return new DispatchedVarArgsCallNode(args, next, function, varArgsSignature, matchedArgs, originalCall); + this.cachedFunction = function; + this.signature = signature; + this.fastPath = function.getFastPath() == null ? null : function.getFastPath().create(); + originalCall.needsCallerFrame |= cachedFunction.containsDispatch(); } @Override - public Object execute(VirtualFrame frame, RFunction currentFunction, ArgumentsSignature varArgsSignature, S3Args s3Args) { - // If this is the root of the varargs sub-cache: The signature needs to be created - // once - - // If the signature does not match: delegate to next node! - if (cachedSignature != varArgsSignature) { - return next.execute(frame, currentFunction, varArgsSignature, s3Args); - } - - // Our cached function and matched arguments do match, simply execute! - - if (needsSplitting) { + public Object execute(VirtualFrame frame, RFunction currentFunction, Object[] orderedArguments, S3Args s3Args) { + if (fastPath != null) { + Object result = fastPath.execute(frame, orderedArguments); + if (result != null) { + return result; + } CompilerDirectives.transferToInterpreterAndInvalidate(); - needsSplitting = false; - call.cloneCallTarget(); - } - MaterializedFrame callerFrame = needsCallerFrame ? frame.materialize() : null; - Object[] argsObject = argsNode.execute(currentFunction, originalCall, callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame), - matchedArgs.executeArray(frame), - matchedArgs.getSignature(), s3Args); - return call.call(frame, argsObject); - } - - @Override - public boolean setNeedsCallerFrame() { - try { - return needsCallerFrame; - } finally { - needsCallerFrame = true; + fastPath = null; } - } - } - /** - * [DGV] {@link RCallNode} in case there is a cached {@link RFunction} with cached varargs that - * exceeded the cache size {@link RCallNode#VARARGS_INLINE_CACHE_SIZE} . - * - * @see RCallNode - */ - private static final class DispatchedGenericVarArgsCallNode extends VarArgsCacheCallNode { - - @Child private DirectCallNode call; - @Child private CallArgumentsNode suppliedArgs; - - @CompilationFinal private boolean needsCallerFrame; - - DispatchedGenericVarArgsCallNode(RFunction function, CallArgumentsNode suppliedArgs, RCallNode originalCall) { - super(originalCall); - this.call = Truffle.getRuntime().createDirectCallNode(function.getTarget()); - this.suppliedArgs = suppliedArgs; - } - - @Override - protected Object execute(VirtualFrame frame, RFunction currentFunction, ArgumentsSignature varArgsSignature, S3Args s3Args) { - CompilerDirectives.transferToInterpreter(); - - // Arguments may change every call: Flatt'n'Match on SlowPath! :-/ - UnrolledVariadicArguments argsValuesAndNames = suppliedArgs.executeFlatten(frame); - MatchedArguments matchedArgs = ArgumentMatcher.matchArguments(currentFunction, argsValuesAndNames, this, true); - - if (!needsCallerFrame && currentFunction.containsDispatch()) { + if (argsNode == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - needsCallerFrame = true; + argsNode = insert(RArgumentsNode.create()); + call = insert(Truffle.getRuntime().createDirectCallNode(cachedFunction.getTarget())); + if (needsSplitting(cachedFunction)) { + call.cloneCallTarget(); + } } - MaterializedFrame callerFrame = needsCallerFrame ? frame.materialize() : null; - Object[] argsObject = RArguments.create(currentFunction, originalCall, callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame), - matchedArgs.doExecuteArray(frame), - matchedArgs.getSignature(), s3Args); + MaterializedFrame callerFrame = CompilerDirectives.inInterpreter() || originalCall.needsCallerFrame ? frame.materialize() : null; + Object[] argsObject = argsNode.execute(cachedFunction, originalCall.createCaller(frame, cachedFunction), callerFrame, RArguments.getDepth(frame) + 1, RArguments.getPromiseFrame(frame), + orderedArguments, signature, s3Args); return call.call(frame, argsObject); } } @Override public RSyntaxElement getSyntaxLHS() { - return functionNode.asRSyntaxNode(); + return getFunction() == null ? RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "FUN", true) : getFunctionNode().asRSyntaxNode(); } @Override public ArgumentsSignature getSyntaxSignature() { - return signature; + return signature == null ? ArgumentsSignature.empty(1) : signature; } @Override public RSyntaxElement[] getSyntaxArguments() { - return arguments.v; + return arguments == null ? new RSyntaxElement[]{RSyntaxLookup.createDummyLookup(RSyntaxNode.LAZY_DEPARSE, "...", false)} : arguments; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java index 31af3be0e2ae22903e0b1a0d8b4f162c4e5fdce0..5053315ec963a72c311b422b48fbad04a65bef63 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java @@ -47,10 +47,10 @@ public class RCallerHelper { public static final class Representation implements RCaller { private final Object func; - private final Object[] arguments; + private final RArgsValuesAndNames arguments; private RSyntaxNode syntaxNode = null; - public Representation(Object func, Object[] arguments) { + public Representation(Object func, RArgsValuesAndNames arguments) { this.func = func; this.arguments = arguments; } @@ -58,14 +58,14 @@ public class RCallerHelper { @Override public RSyntaxNode getSyntaxNode() { if (syntaxNode == null) { - RSyntaxNode[] syntaxArguments = new RSyntaxNode[arguments.length]; + RSyntaxNode[] syntaxArguments = new RSyntaxNode[arguments.getLength()]; int index = 0; // arguments are already ordered - once one is missing, all the remaining ones must // be // missing boolean missing = false; - for (int i = 0; i < arguments.length; i++) { - Object arg = arguments[i]; + for (int i = 0; i < arguments.getLength(); i++) { + Object arg = arguments.getArgument(i); if (arg instanceof RPromise) { assert !missing; RPromise p = (RPromise) arg; @@ -103,9 +103,6 @@ public class RCallerHelper { } } - // for some reason GNU R does not use argument names - hence empty signature even - // though - // an actual one is available syntaxNode = RASTUtils.createCall(func, true, ArgumentsSignature.empty(syntaxArguments.length), syntaxArguments); } return syntaxNode; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java index b3e8ffc21b48ecd2dc46afc2169fbc8949448ab8..342c1c1a3d049fbe6c8321862e5b57364d4d36d8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java @@ -80,6 +80,14 @@ public abstract class S3FunctionLookupNode extends RBaseNode { return new UseMethodFunctionLookupUninitializedNode(throwsError, nextMethod); } + public static S3FunctionLookupNode createWithError() { + return new UseMethodFunctionLookupUninitializedNode(true, false); + } + + public static S3FunctionLookupNode createWithException() { + return new UseMethodFunctionLookupUninitializedNode(false, false); + } + @FunctionalInterface private interface LookupOperation { Object read(MaterializedFrame frame, String name, boolean inMethodsTable); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java index 3418749e522c45c5ca692713b441a6a619c5b949..56c0751202f6e38fef94f115bb4dcf895ce01efc 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/TemporarySlotNode.java @@ -22,8 +22,6 @@ */ package com.oracle.truffle.r.nodes.function; -import java.util.function.Consumer; - import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.FrameSlot; import com.oracle.truffle.api.frame.FrameSlotTypeException; @@ -34,16 +32,17 @@ import com.oracle.truffle.r.runtime.RInternalError; public final class TemporarySlotNode extends Node { - private static final Object[] defaultTempIdentifiers = new Object[]{new Object(), new Object(), new Object(), new Object()}; + private static final Object[] defaultTempIdentifiers = new Object[]{new Object(), new Object(), new Object(), new Object(), new Object(), new Object(), new Object(), new Object()}; @Child private FrameSlotNode tempSlot; private int tempIdentifier; + private Object identifier; - public FrameSlot initialize(VirtualFrame frame, Object value, Consumer<Object> initializer) { + public FrameSlot initialize(VirtualFrame frame, Object value, Runnable invalidate) { if (tempSlot == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - tempSlot = insert(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), defaultTempIdentifiers[0], true)); - initializer.accept(defaultTempIdentifiers[0]); + tempSlot = insert(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), identifier = defaultTempIdentifiers[0], true)); + invalidate.run(); } FrameSlot slot = tempSlot.executeFrameSlot(frame); try { @@ -52,9 +51,9 @@ public final class TemporarySlotNode extends Node { // keep the complete loop in the slow path do { tempIdentifier++; - Object identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : new Object(); + identifier = tempIdentifier < defaultTempIdentifiers.length ? defaultTempIdentifiers[tempIdentifier] : new Object(); tempSlot.replace(FrameSlotNode.createInitialized(frame.getFrameDescriptor(), identifier, true)); - initializer.accept(identifier); + invalidate.run(); slot = tempSlot.executeFrameSlot(frame); } while (frame.isObject(slot) && frame.getObject(slot) != null); } @@ -69,4 +68,8 @@ public final class TemporarySlotNode extends Node { public void cleanup(VirtualFrame frame, FrameSlot slot) { frame.setObject(slot, null); } + + public Object getIdentifier() { + return identifier; + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnmatchedArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnmatchedArguments.java index 2258928a55dbd78a81de7667db9c34b96bae5b2e..70829ff60866dce7e8d25982da5008160c738003 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnmatchedArguments.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnmatchedArguments.java @@ -28,7 +28,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; /** * An interface all arguments that are going to be matched need to implement. */ -interface UnmatchedArguments extends ClosureCache { +public interface UnmatchedArguments extends ClosureCache { /** * @return The arguments to be matched. Individual {@link RNode}s may be <code>null</code> to * denote "missingness"! diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnrolledVariadicArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnrolledVariadicArguments.java index d2c1eb5b5ff02cf479765929f7a2f76e0e430eb9..b671bfe682c05ca423bce40b3f645ee5f3e11f76 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnrolledVariadicArguments.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnrolledVariadicArguments.java @@ -24,7 +24,6 @@ package com.oracle.truffle.r.nodes.function; import java.util.IdentityHashMap; -import com.oracle.truffle.api.frame.Frame; import com.oracle.truffle.r.runtime.Arguments; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.data.RPromise.Closure; @@ -32,7 +31,8 @@ import com.oracle.truffle.r.runtime.nodes.RNode; /** * This is a simple container class for arguments whose "..." have been unrolled and inserted into - * the original arguments, as it happens in {@link CallArgumentsNode#executeFlatten(Frame)}. + * the original arguments, as it happens in + * {@link CallArgumentsNode#unrollArguments(ArgumentsSignature)}. */ public final class UnrolledVariadicArguments extends Arguments<RNode> implements UnmatchedArguments { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java index 8990ac616929a540c5838c709b0ab1ece859d6f2..5210945655fb09e4166587e604b7aef188cbf9f4 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/WrapArgumentBaseNode.java @@ -23,7 +23,6 @@ package com.oracle.truffle.r.nodes.function; import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RLanguage; import com.oracle.truffle.r.runtime.data.RS4Object; @@ -73,9 +72,6 @@ public abstract class WrapArgumentBaseNode extends RNode { if (result instanceof RVector) { everSeenVector.enter(); return (RVector) result; - } else if (result instanceof RFactor) { - everSeenFactor.enter(); - return ((RFactor) result).getVector(); } else if (result instanceof RLanguage) { everSeenLanguage.enter(); return (RLanguage) result; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java new file mode 100644 index 0000000000000000000000000000000000000000..2630a51f78a5d5e4a28cf2878fe0a7cdaaa1872c --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/call/PrepareArguments.java @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2016, 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.function.call; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.r.nodes.RRootNode; +import com.oracle.truffle.r.nodes.function.ArgumentMatcher; +import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation; +import com.oracle.truffle.r.nodes.function.CallArgumentsNode; +import com.oracle.truffle.r.nodes.function.FormalArguments; +import com.oracle.truffle.r.nodes.function.RCallNode; +import com.oracle.truffle.r.nodes.function.UnmatchedArguments; +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.RError; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; +import com.oracle.truffle.r.runtime.data.RFunction; +import com.oracle.truffle.r.runtime.nodes.RNode; + +/** + * This class provides the infrastructure to reorder the arguments based on R's argument matching + * rules. It implements two different paths: one for arguments provided as an + * {@link CallArgumentsNode}, i.e., unevaluated arguments, and another path for evaluated arguments. + */ +public abstract class PrepareArguments extends Node { + + private static final int CACHE_SIZE = 4; + + public abstract Object[] execute(VirtualFrame frame, RArgsValuesAndNames varArgs, RCallNode call); + + public static PrepareArguments create(RFunction function, CallArgumentsNode args) { + return new UninitializedPrepareArguments(function, args); + } + + public static PrepareArguments createExplicit(RFunction function) { + return new UninitializedExplicitPrepareArguments(function); + } + + private static final class UninitializedPrepareArguments extends PrepareArguments { + + private final RFunction function; + private final CallArgumentsNode sourceArguments; // not used as a node + private int depth = CACHE_SIZE; + + UninitializedPrepareArguments(RFunction function, CallArgumentsNode sourceArguments) { + this.function = function; + this.sourceArguments = sourceArguments; + } + + @Override + public Object[] execute(VirtualFrame frame, RArgsValuesAndNames varArgs, RCallNode call) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + PrepareArguments next; + if (depth-- > 0) { + next = new CachedPrepareArguments(this, function, call, sourceArguments, varArgs == null ? null : varArgs.getSignature()); + } else { + next = new GenericPrepareArguments(function, sourceArguments); + } + return replace(next).execute(frame, varArgs, call); + } + } + + private static final class CachedPrepareArguments extends PrepareArguments { + + @Child private PrepareArguments next; + @Children private final RNode[] matchedArguments; + private final ArgumentsSignature cachedVarArgSignature; + + CachedPrepareArguments(PrepareArguments next, RFunction function, RCallNode call, CallArgumentsNode args, ArgumentsSignature varArgSignature) { + this.next = next; + cachedVarArgSignature = varArgSignature; + matchedArguments = ArgumentMatcher.matchArguments(function, args.unrollArguments(varArgSignature), call, false); + } + + @Override + @ExplodeLoop + public Object[] execute(VirtualFrame frame, RArgsValuesAndNames varArgs, RCallNode call) { + assert (cachedVarArgSignature != null) == (varArgs != null); + if (cachedVarArgSignature == null || cachedVarArgSignature == varArgs.getSignature()) { + Object[] result = new Object[matchedArguments.length]; + for (int i = 0; i < matchedArguments.length; i++) { + result[i] = matchedArguments[i].execute(frame); + } + return result; + } + return next.execute(frame, varArgs, call); + } + } + + private static final class GenericPrepareArguments extends PrepareArguments { + + private final RFunction function; + private final CallArgumentsNode args; // not used as a node + + GenericPrepareArguments(RFunction function, CallArgumentsNode args) { + this.function = function; + this.args = args; + } + + @Override + public Object[] execute(VirtualFrame frame, RArgsValuesAndNames varArgs, RCallNode call) { + CompilerDirectives.transferToInterpreter(); + ArgumentsSignature varArgSignature = varArgs == null ? null : varArgs.getSignature(); + UnmatchedArguments argsValuesAndNames = args.unrollArguments(varArgSignature); + RNode[] matchedArgs = ArgumentMatcher.matchArguments(function, argsValuesAndNames, RError.ROOTNODE, true); + Object[] result = new Object[matchedArgs.length]; + for (int i = 0; i < matchedArgs.length; i++) { + result[i] = matchedArgs[i].execute(frame); + } + return result; + } + } + + private static final class UninitializedExplicitPrepareArguments extends PrepareArguments { + + private final RFunction function; + private int depth = CACHE_SIZE; + + UninitializedExplicitPrepareArguments(RFunction function) { + this.function = function; + } + + @Override + public Object[] execute(VirtualFrame frame, RArgsValuesAndNames explicitArgs, RCallNode call) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + PrepareArguments next; + if (depth-- > 0) { + next = new CachedExplicitPrepareArguments(this, function, call, explicitArgs == null ? null : explicitArgs.getSignature()); + } else { + next = new GenericExplicitPrepareArguments(function); + } + return replace(next).execute(frame, explicitArgs, call); + } + } + + private static final class CachedExplicitPrepareArguments extends PrepareArguments { + + @Child private PrepareArguments next; + + private final MatchPermutation permutation; + private final ArgumentsSignature cachedExplicitArgSignature; + private final FormalArguments formals; + + CachedExplicitPrepareArguments(PrepareArguments next, RFunction function, RCallNode call, ArgumentsSignature explicitArgSignature) { + this.next = next; + formals = ((RRootNode) function.getTarget().getRootNode()).getFormalArguments(); + permutation = ArgumentMatcher.matchArguments(explicitArgSignature, formals.getSignature(), call, false, function.getRBuiltin()); + cachedExplicitArgSignature = explicitArgSignature; + } + + @Override + public Object[] execute(VirtualFrame frame, RArgsValuesAndNames explicitArgs, RCallNode call) { + if (cachedExplicitArgSignature == explicitArgs.getSignature()) { + return ArgumentMatcher.matchArgumentsEvaluated(permutation, explicitArgs.getArguments(), formals); + } + return next.execute(frame, explicitArgs, call); + } + } + + private static final class GenericExplicitPrepareArguments extends PrepareArguments { + + private final RFunction function; + + GenericExplicitPrepareArguments(RFunction function) { + this.function = function; + } + + @Override + public Object[] execute(VirtualFrame frame, RArgsValuesAndNames explicitArgs, RCallNode call) { + CompilerDirectives.transferToInterpreter(); + // Function and arguments may change every call: Flatt'n'Match on SlowPath! :-/ + return ArgumentMatcher.matchArgumentsEvaluated(function, explicitArgs, RError.ROOTNODE, false).getArguments(); + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java index 0fe79bce163b58fcb88c4b303f7c59f484e94fec..2efb72901f8fec7b31d69558a44c0033c25d3b3a 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/opt/EagerEvalHelper.java @@ -27,13 +27,15 @@ import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; import com.oracle.truffle.r.nodes.function.ArgumentStatePush; import com.oracle.truffle.r.nodes.function.PromiseNode; -import com.oracle.truffle.r.nodes.function.RCallNode; import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.nodes.RNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; +import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; +import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; +import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; +import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; /** * Provides small helper function for eager evaluation of arguments for the use in @@ -81,17 +83,17 @@ public class EagerEvalHelper { if (!optConsts()) { return null; } - if (expr instanceof RCallNode) { - RCallNode call = (RCallNode) expr; - if (call.getFunctionNode() instanceof ReadVariableNode) { - String functionName = ((ReadVariableNode) call.getFunctionNode()).getIdentifier(); + if (expr instanceof RSyntaxCall) { + RSyntaxCall call = (RSyntaxCall) expr; + if (call.getSyntaxLHS() instanceof RSyntaxLookup) { + String functionName = ((RSyntaxLookup) call.getSyntaxLHS()).getIdentifier(); switch (functionName) { case "character": - if (call.getArgumentCount() == 0) { + if (call.getSyntaxArguments().length == 0) { return RDataFactory.createEmptyStringVector(); - } else if (call.getArgumentCount() == 1) { - RSyntaxNode argument = call.getArgument(0); - Integer value = ConstantNode.asIntConstant(argument, true); + } else if (call.getSyntaxArguments().length == 1) { + RSyntaxElement argument = call.getSyntaxArguments()[0]; + Integer value = RSyntaxConstant.asIntConstant(argument, true); if (value != null) { RStringVector vector = RDataFactory.createStringVector(value); ArgumentStatePush.transitionStateSlowPath(vector); @@ -101,8 +103,8 @@ public class EagerEvalHelper { break; } } - } else if (expr instanceof ConstantNode) { - return ((ConstantNode) expr).getValue(); + } else if (expr instanceof RSyntaxConstant) { + return ((RSyntaxConstant) expr).getValue(); } return null; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java new file mode 100644 index 0000000000000000000000000000000000000000..28a8070384beafcb8a5487ed8943365785b5fd0c --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/InheritsCheckNode.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016, 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.helpers; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNode; +import com.oracle.truffle.r.nodes.function.ClassHierarchyNodeGen; +import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.RMissing; +import com.oracle.truffle.r.runtime.data.RStringVector; + +/** + * Checks if given object has given R class. More specifically: whether its attribute class is a + * vector that contains given class name as an element. + */ +public class InheritsCheckNode extends Node { + + @Child private ClassHierarchyNode classHierarchy = ClassHierarchyNodeGen.create(false, false); + private final ConditionProfile nullClassProfile = ConditionProfile.createBinaryProfile(); + @CompilationFinal private ConditionProfile exactMatchProfile; + private final String checkedClazz; + + public InheritsCheckNode(String checkedClazz) { + this.checkedClazz = checkedClazz; + assert RType.fromMode(checkedClazz) == null : "Class '" + checkedClazz + "' cannot be checked by InheritsCheckNode"; + } + + public boolean execute(Object value) { + if (value instanceof RMissing) { + return false; + } + + RStringVector clazz = classHierarchy.execute(value); + if (nullClassProfile.profile(clazz != null)) { + for (int j = 0; j < clazz.getLength(); ++j) { + if (exactMatchProfile == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + exactMatchProfile = ConditionProfile.createBinaryProfile(); + } + if (exactMatchProfile.profile(clazz.getDataAt(j) == checkedClazz) || clazz.getDataAt(j).equals(checkedClazz)) { + return true; + } + } + } + return false; + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java new file mode 100644 index 0000000000000000000000000000000000000000..3573d38864dd81f79000f0226f7e2f13c7de6fc6 --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java @@ -0,0 +1,113 @@ +/* + * 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.helpers; + +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.profiles.BranchProfile; +import com.oracle.truffle.api.profiles.ConditionProfile; +import com.oracle.truffle.r.nodes.attributes.AttributeAccess; +import com.oracle.truffle.r.nodes.unary.CastStringNode; +import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; +import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.RAttributeProfiles; +import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; + +/** + * Contains helper nodes related to factors, special R class of {@link RAbstractIntVector}. Note: + * there is also {@code IsFactorNode}, which implements a built-in, for checking factor class. + */ +public final class RFactorNodes { + + private RFactorNodes() { + } + + /** + * Encapsulates the operation of deciding whether a factor is ordered. + */ + public static class GetOrdered extends Node { + @Child private AttributeAccess isOrderedAccess = AttributeAccess.create(RRuntime.ORDERED_ATTR_KEY); + + public boolean execute(RAbstractIntVector factor) { + Object value = isOrderedAccess.execute(factor.getAttributes()); + if (value instanceof RAbstractLogicalVector) { + RAbstractLogicalVector vec = (RAbstractLogicalVector) value; + return vec.getLength() > 0 && RRuntime.fromLogical(vec.getDataAt(0)); + } + + return false; + } + } + + /** + * Encapsulates the operation of getting the 'levels' of a factor as a string vector. + */ + public static class GetLevels extends Node { + @Child private CastStringNode castString; + @Child private AttributeAccess attrAccess = AttributeAccess.create(RRuntime.LEVELS_ATTR_KEY); + + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + private final BranchProfile notVectorBranch = BranchProfile.create(); + private final ConditionProfile nonScalarLevels = ConditionProfile.createBinaryProfile(); + private final ConditionProfile stringVectorLevels = ConditionProfile.createBinaryProfile(); + + /** + * Returns the levels as a string vector. If the 'levels' attribute is not a string vector a + * cast is done. May return null, if the 'levels' attribute is not present. + */ + public RStringVector execute(RAbstractIntVector factor) { + Object attr = attrAccess.execute(factor.getAttributes()); + + // Convert scalars to vector if necessary + RVector vec; + if (nonScalarLevels.profile(attr instanceof RVector)) { + vec = (RVector) attr; + } else if (attr != null) { + vec = (RVector) RRuntime.asAbstractVector(attr); // scalar to vector + } else { + notVectorBranch.enter(); + // N.B: when a factor is lacking the 'levels' attribute, GNU R uses range 1:14331272 + // as levels, but probably only in 'split'. Following example prints a huge list: + // { f <- factor(1:5); attr(f, 'levels') <- NULL; split(1:2, f) } + return null; + } + + // Convert to string vector if necessary + if (stringVectorLevels.profile(vec instanceof RStringVector)) { + return (RStringVector) vec; + } else { + if (castString == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + castString = insert(CastStringNodeGen.create(false, false, false, false)); + } + RStringVector slevels = (RStringVector) castString.executeString(vec); + return RDataFactory.createStringVector(slevels.getDataWithoutCopying(), RDataFactory.COMPLETE_VECTOR); + } + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java index 9225582669eeeb4ae0686c58c7ac2a14509cd16e..7b15cf7fede1479f5f3718de78a5bbf3983a8978 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastIntegerNode.java @@ -29,22 +29,8 @@ import com.oracle.truffle.api.dsl.Specialization; 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.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.ops.na.NAProfile; public abstract class CastIntegerNode extends CastIntegerBaseNode { @@ -215,11 +201,6 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode { return ret; } - @Specialization - protected RIntVector doFactor(RFactor factor) { - return factor.getVector(); - } - // TODO Should be type-variable and moved to CastNode @Specialization(guards = {"args.getLength() == 1", "isIntVector(args.getArgument(0))"}) protected RIntVector doRArgsValuesAndNames(RArgsValuesAndNames args) { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java index b60cb438a3b5d72dca159bb03cb19dd004c929bd..b41b5aeb679f14847f948eaf926d99c3fdd01aab 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastLogicalNode.java @@ -27,17 +27,9 @@ import java.util.Arrays; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogicalVector; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -79,7 +71,7 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { return operand; } - @Specialization + @Specialization(guards = "!isFactor(operand)") protected RLogicalVector doIntVector(RAbstractIntVector operand) { return createResultVector(operand, index -> naCheck.convertIntToLogical(operand.getDataAt(index))); } @@ -154,8 +146,8 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { return missing; } - @Specialization - protected RLogicalVector asLogical(RFactor factor) { + @Specialization(guards = "isFactor(factor)") + protected RLogicalVector asLogical(RAbstractIntVector factor) { byte[] data = new byte[factor.getLength()]; Arrays.fill(data, RRuntime.LOGICAL_NA); return RDataFactory.createLogicalVector(data, RDataFactory.INCOMPLETE_VECTOR); @@ -170,4 +162,10 @@ public abstract class CastLogicalNode extends CastLogicalBaseNode { public static CastLogicalNode createNonPreserving() { return CastLogicalNodeGen.create(false, false, false); } + + @Child private InheritsCheckNode inheritsFactorCheck = new InheritsCheckNode(RRuntime.CLASS_FACTOR); + + protected boolean isFactor(Object o) { + return inheritsFactorCheck.execute(o); + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java index 260cca0912bf6659377cb15f0778bdabe54a7c11..c1a512ea7c8deab823d2a831203ecbe995e53750 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToContainerNode.java @@ -23,12 +23,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -52,11 +47,6 @@ public abstract class CastToContainerNode extends CastBaseNode { return vector; } - @Specialization - protected RFactor cast(RFactor factor) { - return factor; - } - @Specialization protected RExpression cast(RExpression expression) { return expression; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java index 1734a58f8a5c0474be8b643ebb88c78427cd87c8..8f35c98a981be1d8b8318c449b2684fff67c227e 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/CastToVectorNode.java @@ -24,12 +24,7 @@ package com.oracle.truffle.r.nodes.unary; import com.oracle.truffle.api.dsl.NodeField; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RNull; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @NodeField(name = "nonVectorPreserved", type = boolean.class) @@ -60,11 +55,6 @@ public abstract class CastToVectorNode extends CastNode { return vector; } - @Specialization - protected RAbstractVector cast(RFactor factor) { - return factor.getVector(); - } - @Specialization protected RList cast(RExpression expression) { return expression.getList(); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java index 74f2c2e330bd72da3ce0ff68f3c91c92cd4dad20..bf740255bc676013010b0c5148b838d1212ac733 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/IsFactorNode.java @@ -11,16 +11,19 @@ package com.oracle.truffle.r.nodes.unary; +import static com.oracle.truffle.r.runtime.RRuntime.LOGICAL_FALSE; +import static com.oracle.truffle.r.runtime.RRuntime.LOGICAL_TRUE; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.r.nodes.helpers.InheritsCheckNode; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.RDataFactory; public abstract class IsFactorNode extends UnaryNode { @Child private TypeofNode typeofNode; - @Child private InheritsNode inheritsNode; + @Child private InheritsCheckNode inheritsCheck; public abstract byte executeIsFactor(Object c); @@ -31,12 +34,15 @@ public abstract class IsFactorNode extends UnaryNode { typeofNode = insert(TypeofNodeGen.create()); } if (typeofNode.execute(x) != RType.Integer) { - return RRuntime.LOGICAL_FALSE; + // Note: R does not allow to set class 'factor' to an arbitrary object, unlike with + // data.frame + return LOGICAL_FALSE; } - if (inheritsNode == null) { + if (inheritsCheck == null) { CompilerDirectives.transferToInterpreterAndInvalidate(); - inheritsNode = insert(InheritsNodeGen.create()); + inheritsCheck = insert(new InheritsCheckNode(RRuntime.CLASS_FACTOR)); } - return (byte) inheritsNode.executeObject(x, RDataFactory.createStringVector(RType.Factor.getName()), RRuntime.LOGICAL_FALSE); + + return inheritsCheck.execute(x) ? LOGICAL_TRUE : LOGICAL_FALSE; } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java index 8afec0273e921dbcfce320b4deec79f0241990bc..8c7b2e531442fb5589ed6c5774535a926a3a51a2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/PrecedenceNode.java @@ -26,26 +26,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImportStatic; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLanguage; -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.RPairList; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RS4Object; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RSymbol; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -187,11 +168,6 @@ public abstract class PrecedenceNode extends RBaseNode { return EXPRESSION_PRECEDENCE; } - @Specialization - protected int doFactor(RFactor val, byte recursive) { - return INT_PRECEDENCE; - } - @Specialization protected int doS4Object(RS4Object o, byte recursive) { return LIST_PRECEDENCE; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java index 598e597811d5c1bac3ed67fc399fb53f6702befd..093c75a0a7bb3d22d77c450bedb03e80695fb3d6 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java @@ -80,12 +80,25 @@ public enum FastROptions { public boolean getBooleanValue() { assert isBoolean; - return (Boolean) value; + if (value instanceof Boolean) { + return (Boolean) value; + } else { + System.out.println("boolean option value expected with " + name() + " - forgot +/- ?"); + System.exit(2); + return false; + } + } public String getStringValue() { assert !isBoolean; - return (String) value; + if (value == null || value instanceof String) { + return (String) value; + } else { + System.out.println("string option value expected with " + name()); + System.exit(2); + return ""; + } } private static FastROptions[] VALUES = values(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java index 4c52f4046f06685a7c1b5d115a6edf7722ccc236..c0c031affaa58c088ac0222e2abafa47b7c54c78 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RDeparse.java @@ -23,38 +23,14 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributes; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.REmpty; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RS4Object; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.RTypedValue; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; import com.oracle.truffle.r.runtime.env.REnvironment; import com.oracle.truffle.r.runtime.gnur.SEXPTYPE; -import com.oracle.truffle.r.runtime.nodes.RSyntaxCall; -import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant; -import com.oracle.truffle.r.runtime.nodes.RSyntaxElement; -import com.oracle.truffle.r.runtime.nodes.RSyntaxFunction; -import com.oracle.truffle.r.runtime.nodes.RSyntaxLookup; -import com.oracle.truffle.r.runtime.nodes.RSyntaxNode; -import com.oracle.truffle.r.runtime.nodes.RSyntaxVisitor; +import com.oracle.truffle.r.runtime.nodes.*; /** * Deparsing R objects. @@ -569,9 +545,6 @@ public class RDeparse { protected Void visit(RSyntaxConstant constant) { // coerce scalar values to vectors and unwrap data frames and factors: Object value = RRuntime.asAbstractVector(constant.getValue()); - if (value instanceof RFactor) { - value = ((RFactor) value).getVector(); - } if (value instanceof RExpression) { append("expression(").appendListContents(((RExpression) value).getList()).append(')'); @@ -600,7 +573,7 @@ public class RDeparse { append(')'); } else if (value instanceof RS4Object) { RS4Object s4Obj = (RS4Object) value; - Object clazz = s4Obj.getAttribute("class"); + Object clazz = s4Obj.getAttr("class"); String className = clazz == null ? "S4" : RRuntime.toString(RRuntime.asStringLengthOne(clazz)); append("new(\"").append(className).append('\"'); try (C c = indent()) { @@ -926,8 +899,7 @@ public class RDeparse { } /** - * Handles {@link RList}, (@link RExpression}, and {@link RFactor}. Method name same as - * GnuR. + * Handles {@link RList}, (@link RExpression}. Method name same as GnuR. */ private DeparseVisitor appendListContents(RAbstractListVector v) { int n = v.getLength(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java index bf8611503b131b00dbb305493ec1c6f30d1526a8..9d60e49c9b15a7b223b94bdba45840e14d96a7a0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntime.java @@ -128,7 +128,8 @@ public class RRuntime { public static final String DOT_S3_CLASS = ".S3Class"; public static final String CLASS_DATA_FRAME = "data.frame"; - public static final String CLASS_ORDERED = "ordered"; + public static final String CLASS_FACTOR = "factor"; + public static final String ORDERED_ATTR_KEY = "ordered"; public static final String RS3MethodsTable = ".__S3MethodsTable__."; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index 806c3c6365c687b26bb7776b46dbf8958b56592a..e8ea46f80d38dd1ee8b90445017530ade08304a8 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -11,21 +11,9 @@ */ package com.oracle.truffle.r.runtime; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.PrintStream; +import java.io.*; import java.nio.charset.StandardCharsets; -import java.util.Arrays; -import java.util.Deque; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.Map; +import java.util.*; import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; @@ -34,37 +22,10 @@ import com.oracle.truffle.api.source.Source; import com.oracle.truffle.r.runtime.conn.RConnection; import com.oracle.truffle.r.runtime.context.Engine.ParseException; import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RAttributes; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RAttributes.RAttribute; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.REmpty; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogicalVector; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RPromise.OptType; import com.oracle.truffle.r.runtime.data.RPromise.PromiseType; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RScalar; -import com.oracle.truffle.r.runtime.data.RShareable; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.RTypedValue; -import com.oracle.truffle.r.runtime.data.RUnboundValue; -import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; @@ -1503,10 +1464,6 @@ public class RSerialize { writeItem(RNull.instance); } } - } else if (type == SEXPTYPE.FASTR_FACTOR) { - RFactor factor = (RFactor) obj; - writeItem(factor.getVector()); - return; } else { // flags RAttributes attributes = null; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java index 651c6f100aff2deafd0e947963144913b403fdbc..82816c766520b48e0bcdadc93231b55e693d8147 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RType.java @@ -36,7 +36,6 @@ public enum RType { Closure("closure", -1), Builtin("builtin", -1), Special("special", -1), - Factor("factor", -1), Symbol("symbol", -1), Environment("environment", -1), PairList("pairlist", -1), @@ -143,8 +142,6 @@ public enum RType { return Builtin; case "special": return Special; - case "factor": - return Factor; case "symbol": return Symbol; case "environment": diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java index 9e9a027d826fd7149b75d41d8a76df84b2830d40..388ff08a9c6dd99bf2a3c95e00b11e14c681351a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/Utils.java @@ -412,9 +412,10 @@ public final class Utils { assert call != null; RLanguage rl = RContext.getRRuntimeASTAccess().getSyntaxCaller(call); RSyntaxNode sn = (RSyntaxNode) rl.getRep(); - SourceSection ss = sn.getSourceSection(); + SourceSection ss = sn != null ? sn.getSourceSection() : null; // fabricate a srcref attribute from ss - String path = ss.getSource().getPath(); + Source source = ss != null ? ss.getSource() : null; + String path = source != null ? source.getPath() : null; if (path != null && RInternalSourceDescriptions.isInternal(path)) { path = null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java index 609aef238392dc5b3b57b0678104620c299cdc3a..f5ed54d6b20c16c020e27db5d24cc9c4cdf3e1f3 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributable.java @@ -23,7 +23,6 @@ package com.oracle.truffle.r.runtime.data; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.env.REnvironment; /** @@ -33,6 +32,7 @@ import com.oracle.truffle.r.runtime.env.REnvironment; * {@link RAttributable} is implemented by the {@link RAttributes} class. */ public interface RAttributable extends RTypedValue { + /** * If the attribute set is not initialized, then initialize it. * @@ -49,16 +49,21 @@ public interface RAttributable extends RTypedValue { RAttributes getAttributes(); /** - * Returns the value of the {@code class} attribute. + * Returns the value of the {@code class} attribute or empty {@link RStringVector} if class + * attribute is not set. */ - RStringVector getClassHierarchy(); + default RStringVector getClassHierarchy() { + Object v = getAttr(RRuntime.CLASS_ATTR_KEY); + RStringVector result = v instanceof RStringVector ? (RStringVector) v : getImplicitClass(); + return result != null ? result : RDataFactory.createEmptyStringVector(); + } /** * Returns {@code true} if the {@code class} attribute is set to {@link RStringVector} whose * first element equals to the given className. */ default boolean hasClass(String className) { - RAbstractStringVector v = getClassHierarchy(); + RStringVector v = getClassHierarchy(); for (int i = 0; i < v.getLength(); ++i) { if (v.getDataAt(i).equals(className)) { return true; @@ -81,6 +86,14 @@ public interface RAttributable extends RTypedValue { } } + /** + * Get the value of an attribute. Returns {@code null} if not set. + */ + default Object getAttr(String name) { + RAttributes attr = getAttributes(); + return attr == null ? null : attr.get(name); + } + /** * Set the attribute {@code name} to {@code value}, overwriting any existing value. This is * generic; a class may need to override this to handle certain attributes specially. diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java index c8950954a78e352fca4739d8a680cdf5297ae29a..44cf397f6e5f2c585b25d3eebb4613ded89fba98 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RAttributeStorage.java @@ -22,8 +22,6 @@ */ package com.oracle.truffle.r.runtime.data; -import com.oracle.truffle.r.runtime.RRuntime; - /** * An adaptor class for the several R types that are attributable. Only useful for classes that * don't already inherit from another class, otherwise just cut and paste this code. @@ -50,21 +48,6 @@ public abstract class RAttributeStorage extends RBaseObject implements RAttribut this.attributes = newAttributes; } - public final Object getAttribute(String name) { - RAttributes attr = attributes; - return attr == null ? null : attr.get(name); - } - @Override public abstract RStringVector getImplicitClass(); - - @Override - public final RStringVector getClassHierarchy() { - RStringVector v = (RStringVector) getAttribute(RRuntime.CLASS_ATTR_KEY); - if (v == null) { - return getImplicitClass(); - } else { - return v; - } - } } 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 51bb3a4873c4b5612c37e8fe9ceae54645b3d5c0..8cb3a253031143d295362945b3d4307940c9c566 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 @@ -356,10 +356,6 @@ public final class RDataFactory { return traceDataCreated(new RExpression(list)); } - public static RFactor createFactor(RIntVector vector, boolean ordered) { - return traceDataCreated(new RFactor(vector, ordered)); - } - public static RSymbol createSymbol(String name) { assert name == name.intern(); return traceDataCreated(new RSymbol(name)); 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 812d4f4025a25ae74e30da68b85b1dd153bf2acd..5de2ec03861db52c9595ae8527a25792dce353f3 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 @@ -158,7 +158,7 @@ public class RExpression implements RShareable, RAbstractContainer { @Override public final RStringVector getClassHierarchy() { - RStringVector v = (RStringVector) data.getAttribute(RRuntime.CLASS_ATTR_KEY); + RStringVector v = (RStringVector) data.getAttr(RRuntime.CLASS_ATTR_KEY); if (v == null) { return getImplicitClass(); } else { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java index 9e7f5718c5958f34674848ab0445a545bdc94417..367011fce4b174e190e0e3a7831d051fba891122 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RFactor.java @@ -23,237 +23,32 @@ package com.oracle.truffle.r.runtime.data; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.RType; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -public final class RFactor implements RShareable, RAbstractContainer { +public final class RFactor { - private final RIntVector vector; - - private final boolean ordered; - - public RFactor(RIntVector vector, boolean ordered) { - this.vector = vector; - this.ordered = ordered; - } - - @Override - public int[] getInternalStore() { - return vector.getInternalStore(); - } - - @Override - public RType getRType() { - return RType.Integer; - } - - public RIntVector getVector() { - return vector; - } - - public boolean isOrdered() { - return ordered; - } - - @Override - public boolean isComplete() { - return vector.isComplete(); - } - - @Override - public int getLength() { - return vector.getLength(); - } - - @Override - public RAbstractContainer resize(int size) { - return vector.resize(size); - } - - @Override - public boolean isTemporary() { - return vector.isTemporary(); - } - - @Override - public boolean isShared() { - return vector.isShared(); - } - - @Override - public void incRefCount() { - vector.incRefCount(); - } - - @Override - public void decRefCount() { - vector.decRefCount(); - } - - @Override - public boolean isSharedPermanent() { - return vector.isSharedPermanent(); - } - - @Override - public void makeSharedPermanent() { - vector.makeSharedPermanent(); - } - - @Override - public RShareable getNonShared() { - RIntVector newVector = (RIntVector) vector.getNonShared(); - return newVector == vector ? this : RDataFactory.createFactor(newVector, ordered); - } - - @Override - public RFactor copy() { - return RDataFactory.createFactor((RIntVector) vector.copy(), ordered); - } - - @Override - public RAttributes getAttributes() { - return vector.getAttributes(); - } - - @Override - public boolean hasDimensions() { - return vector.hasDimensions(); - } - - @Override - public int[] getDimensions() { - return vector.getDimensions(); - } - - @Override - public void setDimensions(int[] newDimensions) { - vector.setDimensions(newDimensions); - } - - @Override - public Class<?> getElementClass() { - return RFactor.class; - } - - @Override - public RFactor materializeNonShared() { - RVector v = vector.materializeNonShared(); - return vector != v ? RDataFactory.createFactor((RIntVector) v, ordered) : this; - } - - @Override - public Object getDataAtAsObject(int index) { - return vector.getDataAtAsObject(index); - } - - @Override - public RStringVector getNames(RAttributeProfiles attrProfiles) { - return vector.getNames(attrProfiles); - } - - @Override - public void setNames(RStringVector newNames) { - vector.setNames(newNames); - } - - @Override - public RList getDimNames(RAttributeProfiles attrProfiles) { - return vector.getDimNames(); - } - - @Override - public void setDimNames(RList newDimNames) { - vector.setDimNames(newDimNames); - } - - @Override - public Object getRowNames(RAttributeProfiles attrProfiles) { - return vector.getRowNames(); - } - - @Override - public void setRowNames(RAbstractVector rowNames) { - vector.setRowNames(rowNames); - } - - @Override - public RStringVector getClassHierarchy() { - return vector.getClassHierarchy(); - } - - @Override - public RStringVector getImplicitClass() { - return vector.getImplicitClass(); - } - - @Override - public boolean isObject(RAttributeProfiles attrProfiles) { - return true; - } - - @Override - public RAttributes initAttributes() { - return vector.initAttributes(); - } - - @Override - public void initAttributes(RAttributes newAttributes) { - vector.initAttributes(newAttributes); - } - - @Override - public void setAttr(String name, Object value) { - vector.setAttr(name, value); - } - - @Override - public Object getAttr(RAttributeProfiles attrProfiles, String name) { - return vector.getAttr(attrProfiles, name); - } - - @Override - public RAttributes resetAllAttributes(boolean nullify) { - return vector.resetAllAttributes(nullify); - } - - @Override - public RShareable materializeToShareable() { - return this; - } - - public void setLevels(Object newLevels) { - vector.setAttr(RRuntime.LEVELS_ATTR_KEY, newLevels); - } - - @Override - public RAbstractContainer setClassAttr(RStringVector classAttr, boolean convertToInt) { - return vector.setClassAttr(classAttr, convertToInt); - } - - public RVector getLevels(RAttributeProfiles attrProfiles) { - Object attr = vector.getAttr(attrProfiles, RRuntime.LEVELS_ATTR_KEY); - if (attr instanceof RVector) { - return (RVector) attr; - } else { - // Scalar, must convert - return (RVector) RRuntime.asAbstractVector(attr); - } + private RFactor(RIntVector vector, boolean ordered) { + // only static helpers } - public int getNLevels(RAttributeProfiles attrProfiles) { - RVector levels = getLevels(attrProfiles); - return levels == null ? 0 : levels.getLength(); + /** + * Helper method to get 'levels' of a factor. However, all the invocations of this method should + * be replaced with FactorNodes.GetLevel in the future. + */ + public static RVector getLevels(RAbstractIntVector factor) { + return getLevelsImpl(factor.getAttr(RRuntime.LEVELS_ATTR_KEY)); } - @Override - public int getTypedValueInfo() { - return vector.getTypedValueInfo(); + /** + * Helper method to get 'levels' of a factor with profile. However, all the invocations of this + * method should be replaced with FactorNodes.GetLevel in the future. + */ + public static RVector getLevels(RAttributeProfiles profile, RAbstractIntVector factor) { + return getLevelsImpl(factor.getAttr(profile, RRuntime.LEVELS_ATTR_KEY)); } - @Override - public void setTypedValueInfo(int value) { - vector.setTypedValueInfo(value); + private static RVector getLevelsImpl(Object attr) { + // convert scalar to RVector if necessary + return attr instanceof RVector ? (RVector) attr : (RVector) RRuntime.asAbstractVector(attr); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java index 834aeeeefaa2a5b4c5e73c13dcb19dad41574789..dce983013195da94e1266aa8495c123baa96a6aa 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RPromise.java @@ -484,10 +484,6 @@ public class RPromise implements RTypedValue { public RBaseNode getExpr() { return expr; } - - public Closure deepCopy() { - return new Closure((RBaseNode) expr.deepCopy()); - } } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java index 790f1b2f2351db84be31a0675c2ede6a31201858..2aa99d23f1f6471b547c5c386006bb85cff8f46a 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RTypes.java @@ -51,7 +51,7 @@ import com.oracle.truffle.r.runtime.nodes.RNode; @TypeSystem({boolean.class, byte.class, int.class, double.class, RRaw.class, RComplex.class, String.class, RIntSequence.class, RDoubleSequence.class, RIntVector.class, RDoubleVector.class, RRawVector.class, RComplexVector.class, RStringVector.class, RLogicalVector.class, RFunction.class, RNull.class, RMissing.class, REmpty.class, REnvironment.class, RExpression.class, RConnection.class, MaterializedFrame.class, FrameSlot.class, RAbstractIntVector.class, RAbstractDoubleVector.class, RAbstractLogicalVector.class, RAbstractComplexVector.class, - RAbstractStringVector.class, RAbstractRawVector.class, RList.class, RAbstractVector.class, RFactor.class, RSymbol.class, RPromise.class, RLanguage.class, + RAbstractStringVector.class, RAbstractRawVector.class, RList.class, RAbstractVector.class, RSymbol.class, RPromise.class, RLanguage.class, RPairList.class, RExternalPtr.class, RS4Object.class, RAbstractContainer.class, RAttributable.class, RTypedValue.class, RArgsValuesAndNames.class, RType.class, Object[].class}) public class RTypes { 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 83a7cc0ba4a3e8fd352617af84a3b082261c55e9..a1197ae6546a5f626d0204d437fa15dbbccb7c78 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 @@ -503,40 +503,32 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare // class attribute removed - no longer a data frame or factor (even if it was before) return vector; } else if (classAttr != null && classAttr.getLength() != 0) { - boolean ordered = false; for (int i = 0; i < classAttr.getLength(); i++) { String attr = classAttr.getDataAt(i); - if (RRuntime.CLASS_ORDERED.equals(attr)) { - // "ordered" must be specified before "factor" - hence it's enough to do the - // check only before encountering the "factor" - ordered = true; - } - if (RType.Factor.getName().equals(attr)) { + if (RRuntime.CLASS_FACTOR.equals(attr)) { + // For Factors we only have to check if the data-type is Integer, because + // otherwise we must show error. + // Note: this can only happen if the class is set by hand to some non-integral + // vector, i.e. attr(doubles, 'class') <- 'factor' vector.putAttribute(RRuntime.CLASS_ATTR_KEY, classAttr); - if (enclosingFactor != null) { - // was a factor and still is a factor - return enclosingFactor; - } else { - RIntVector resVector; - if (vector.getElementClass() != RInteger.class) { - if (vector.getElementClass() == RDouble.class && convertToInt) { - RDoubleVector sourceVector = (RDoubleVector) vector; - int[] data = new int[sourceVector.getLength()]; - for (int j = 0; j < data.length; j++) { - data[j] = RRuntime.double2int(sourceVector.getDataAt(j)); - } - resVector = RDataFactory.createIntVector(data, sourceVector.isComplete()); - resVector.copyAttributesFrom(sourceVector); - } else { - // TODO: add invoking node - throw RError.error(RError.SHOW_CALLER2, RError.Message.ADDING_INVALID_CLASS, "factor"); + if (vector.getElementClass() != RInteger.class) { + // TODO: check when this 'convertToInt' is necessary + if (vector.getElementClass() == RDouble.class && convertToInt) { + RDoubleVector sourceVector = (RDoubleVector) vector; + int[] data = new int[sourceVector.getLength()]; + for (int j = 0; j < data.length; j++) { + data[j] = RRuntime.double2int(sourceVector.getDataAt(j)); } + RIntVector resVector = RDataFactory.createIntVector(data, sourceVector.isComplete()); + resVector.copyAttributesFrom(sourceVector); + return resVector; } else { - resVector = (RIntVector) vector; + // TODO: add invoking node + throw RError.error(RError.SHOW_CALLER2, RError.Message.ADDING_INVALID_CLASS, "factor"); } - // it's a factor now - return RDataFactory.createFactor(resVector, ordered); } + + break; // TODO: check if setting connection and then factor shows both errors } else if (RType.Connection.getName().equals(attr)) { // convert to RConnection return ConnectionSupport.fromVector(vector, classAttr); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java index 128abb04ab71e9b131a383763ca70dc776cce073..1907afe018d8f94171746d739935f3fb60c38a7e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RClosures.java @@ -22,22 +22,8 @@ */ package com.oracle.truffle.r.runtime.data.closures; -import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDouble; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RInteger; -import com.oracle.truffle.r.runtime.data.RLogical; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RString; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; public class RClosures { @@ -119,8 +105,11 @@ public class RClosures { // Factor to vector - public static RAbstractVector createFactorToVector(RFactor factor, boolean withNames, RAttributeProfiles attrProfiles) { - RAbstractVector levels = factor.getLevels(attrProfiles); + public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RAttributeProfiles attrProfiles) { + return createFactorToVector(factor, withNames, RFactor.getLevels(attrProfiles, factor)); + } + + public static RAbstractVector createFactorToVector(RAbstractIntVector factor, boolean withNames, RVector levels) { if (levels == null) { return new RFactorToStringVectorClosure(factor, null, withNames); } else { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java index 0ecce378181f1a44c1c00f818265e09824340300..680e2c5aebb22a6a30704d1d8b9349131b7d6187 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToComplexVectorClosure.java @@ -27,10 +27,10 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; /* @@ -41,8 +41,8 @@ final class RFactorToComplexVectorClosure extends RToComplexVectorClosure implem private final RAbstractComplexVector levels; private final boolean withNames; - RFactorToComplexVectorClosure(RFactor factor, RAbstractComplexVector levels, boolean withNames) { - super(factor.getVector()); + RFactorToComplexVectorClosure(RAbstractIntVector vector, RAbstractComplexVector levels, boolean withNames) { + super(vector); assert levels != null; this.levels = levels; this.withNames = withNames; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java index 6fac21bc3c61549c2174db272d847edc5b2e7c6e..45b41c2cfe2dc83860e11c908e1da96a3660f2ee 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToDoubleVectorClosure.java @@ -26,10 +26,10 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; /* @@ -40,8 +40,8 @@ final class RFactorToDoubleVectorClosure extends RToDoubleVectorClosure implemen private final RAbstractDoubleVector levels; private final boolean withNames; - RFactorToDoubleVectorClosure(RFactor factor, RAbstractDoubleVector levels, boolean withNames) { - super(factor.getVector()); + RFactorToDoubleVectorClosure(RAbstractIntVector vector, RAbstractDoubleVector levels, boolean withNames) { + super(vector); assert levels != null; this.levels = levels; this.withNames = withNames; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java index 39bb9913ef5b2cea6d9ac4d65ed5a6500131241e..8e09817efcc8de283347149733a2c36effd09be5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToIntVectorClosure.java @@ -26,7 +26,6 @@ import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -40,8 +39,8 @@ final class RFactorToIntVectorClosure extends RToIntVectorClosure implements RAb private final RAbstractIntVector levels; private final boolean withNames; - RFactorToIntVectorClosure(RFactor factor, RAbstractIntVector levels, boolean withNames) { - super(factor.getVector()); + RFactorToIntVectorClosure(RAbstractIntVector vector, RAbstractIntVector levels, boolean withNames) { + super(vector); assert levels != null; this.levels = levels; this.withNames = withNames; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java index 5581ce61bb2fe5fb469f0e3ba7b140cb4cf35ba6..d6223712ab2613a0364bbab38612b35aced8b340 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RFactorToStringVectorClosure.java @@ -27,9 +27,9 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; -import com.oracle.truffle.r.runtime.data.RFactor; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; @@ -41,8 +41,8 @@ public final class RFactorToStringVectorClosure extends RToStringVectorClosure i private final RAbstractStringVector levels; private final boolean withNames; - RFactorToStringVectorClosure(RFactor factor, RAbstractStringVector levels, boolean withNames) { - super(factor.getVector()); + RFactorToStringVectorClosure(RAbstractIntVector vector, RAbstractStringVector levels, boolean withNames) { + super(vector); this.levels = levels; this.withNames = withNames; if (this.levels == null) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java index 9701130c96eb4f3af92341efb5c37c7f1fc47edf..7dc89eb98a5ebc01e718a2afd693acab71a7bb26 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/gnur/SEXPTYPE.java @@ -17,32 +17,8 @@ import java.util.Map; import com.oracle.truffle.api.source.SourceSection; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.conn.RConnection; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.REmpty; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RExternalPtr; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogicalVector; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RPromise; +import com.oracle.truffle.r.runtime.data.*; import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RS4Object; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.RUnboundValue; import com.oracle.truffle.r.runtime.env.REnvironment; // Transcribed from GnuR src/include/Rinternals.h and src/main/serialize.c @@ -57,8 +33,6 @@ public enum SEXPTYPE { FASTR_INT(301, Integer.class), FASTR_BYTE(302, Byte.class), FASTR_COMPLEX(303, RComplex.class), - // FastR special "vector" types - FASTR_FACTOR(305, RFactor.class), // very special case FASTR_SOURCESECTION(306, SourceSection.class), FASTR_CONNECTION(307, RConnection.class), @@ -196,8 +170,6 @@ public enum SEXPTYPE { return SEXPTYPE.LGLSXP; case FASTR_COMPLEX: return SEXPTYPE.CPLXSXP; - case FASTR_FACTOR: - return SEXPTYPE.VECSXP; case FASTR_CONNECTION: return SEXPTYPE.INTSXP; default: diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java index 06dc66ae1cdda10bee55c1c23cecdbda6d4470db..e4bcc042eaa484f81539bab75c9e38729876ffc7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RNode.java @@ -33,39 +33,8 @@ import com.oracle.truffle.api.nodes.UnexpectedResultException; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.conn.RConnection; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; -import com.oracle.truffle.r.runtime.data.RAttributable; -import com.oracle.truffle.r.runtime.data.RAttributes; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RComplexVector; -import com.oracle.truffle.r.runtime.data.RDoubleSequence; -import com.oracle.truffle.r.runtime.data.RDoubleVector; -import com.oracle.truffle.r.runtime.data.RExpression; -import com.oracle.truffle.r.runtime.data.RFactor; -import com.oracle.truffle.r.runtime.data.RFunction; -import com.oracle.truffle.r.runtime.data.RIntSequence; -import com.oracle.truffle.r.runtime.data.RIntVector; -import com.oracle.truffle.r.runtime.data.RLanguage; -import com.oracle.truffle.r.runtime.data.RList; -import com.oracle.truffle.r.runtime.data.RLogicalVector; -import com.oracle.truffle.r.runtime.data.RMissing; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.RPairList; -import com.oracle.truffle.r.runtime.data.RPromise; -import com.oracle.truffle.r.runtime.data.RRaw; -import com.oracle.truffle.r.runtime.data.RRawVector; -import com.oracle.truffle.r.runtime.data.RStringVector; -import com.oracle.truffle.r.runtime.data.RSymbol; -import com.oracle.truffle.r.runtime.data.RTypes; -import com.oracle.truffle.r.runtime.data.RTypesGen; -import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractRawVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; import com.oracle.truffle.r.runtime.env.REnvironment; @TypeSystemReference(RTypes.class) @@ -193,10 +162,6 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode { return RTypesGen.expectRExpression(execute(frame)); } - public RFactor executeRFactor(VirtualFrame frame) throws UnexpectedResultException { - return RTypesGen.expectRFactor(execute(frame)); - } - public RSymbol executeRSymbol(VirtualFrame frame) throws UnexpectedResultException { return RTypesGen.expectRSymbol(execute(frame)); } @@ -285,10 +250,6 @@ public abstract class RNode extends RBaseNode implements RInstrumentableNode { return value instanceof RList; } - protected static boolean isRFactor(Object value) { - return value instanceof RFactor; - } - protected static boolean isRPromise(Object value) { return value instanceof RPromise; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxConstant.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxConstant.java index 6e8fabfb0db65285a65a4ace262d13d83fc101cb..40a233293549515696f76dcbe0af3ac8c319486c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxConstant.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nodes/RSyntaxConstant.java @@ -53,4 +53,19 @@ public interface RSyntaxConstant extends RSyntaxElement { } }; } + + /** + * Helper function: extract an integer constant from an RSyntaxElement. + */ + static Integer asIntConstant(RSyntaxElement argument, boolean castFromDouble) { + if (argument instanceof RSyntaxConstant) { + Object value = ((RSyntaxConstant) argument).getValue(); + if (value instanceof Integer) { + return (int) value; + } else if (castFromDouble && value instanceof Double) { + return (int) (double) value; + } + } + return null; + } } 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 f69abc670f5a0ebde1f1721f5e483718c466ef67..9804e42bacde3c0ce7462627471866f6b82744e7 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 @@ -23552,6 +23552,15 @@ Error: unexpected symbol in " ', NA), mag = c('Min. :5.000 ', '1st Qu.:5.300 #argv <- list(structure(list(Topic = c('myTst-package', 'foo-class', 'myTst', 'show,foo-method', 'show,foo-method', 'show-methods'), File = c('myTst-package', 'foo-class', 'myTst-package', 'foo-class', 'show-methods', 'show-methods')), .Names = c('Topic', 'File'), row.names = c(3L, 1L, 4L, 2L, 6L, 5L), class = 'data.frame'));is.matrix(argv[[1]]); [1] FALSE +##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA +#is.na(data.frame(col1=1:5, col2=c(NA, 1, NA, 2, NA))) + col1 col2 +[1,] FALSE TRUE +[2,] FALSE FALSE +[3,] FALSE TRUE +[4,] FALSE FALSE +[5,] FALSE TRUE + ##com.oracle.truffle.r.test.builtins.TestBuiltin_isna.testIsNA #is.na(is.na)) Error: unexpected ')' in "is.na(is.na))" @@ -31534,6 +31543,25 @@ NULL [1] "some" [1] "test" +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testDispatchToOpsSpecializations +#data.frame(factor(c(1,2,1))) == data.frame(factor(c(1,2,2))) + factor.c.1..2..1.. +[1,] TRUE +[2,] TRUE +[3,] FALSE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testDispatchToOpsSpecializations +#data.frame(factor(c(1,2,3))) == data.frame(factor(c(1,2,3))) + factor.c.1..2..3.. +[1,] TRUE +[2,] TRUE +[3,] TRUE + +##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testDispatchToOpsSpecializations +#factor(c("a","b","c")) == factor(c(1,2,3)) +Error in Ops.factor(factor(c("a", "b", "c")), factor(c(1, 2, 3))) : + level sets of factors are different + ##com.oracle.truffle.r.test.builtins.TestBuiltin_operators.testIn #{ "hello" %in% c("I", "say", "hello", "world") } [1] TRUE @@ -52945,6 +52973,10 @@ Error in setwd(1) : character argument expected #{ setwd(character()) } Error in setwd(character()) : character argument expected +##com.oracle.truffle.r.test.functions.TestFunctions.testArgEvaluationOrder +#v <- 1; class(v) <- 'foo'; `-.foo` <- function(x,y,...) { cat('[-.foo]'); 1234 }; g <- function(...) { cat('[ing]'); ({cat('[-]'); `-`})(...) }; ({cat('[g]'); g})({cat('[x]'); v},{cat('[y]'); 3},{cat('[z]'); 5}) +[g][ing][-][x][y][z][-.foo][1] 1234 + ##com.oracle.truffle.r.test.functions.TestFunctions.testArgs #{ f<-function(x, row.names = NULL, optional = FALSE, ...) {print(optional); for (i in list(...)) {print(i)} }; f(c(7,42), row.names=NULL, nm="x") } [1] FALSE @@ -53255,6 +53287,10 @@ a ##com.oracle.truffle.r.test.functions.TestFunctions.testDots #f2 <- function(...) { f <- function() cat(...); f() }; f2() +##com.oracle.truffle.r.test.functions.TestFunctions.testDots +#{ `-.foo` <- function(...) 123; v <- 1; class(v) <- 'foo'; sapply(1,`-`,v); sapply(v,`-`,1); sapply(v,`-`,v) } +[1] 123 + ##com.oracle.truffle.r.test.functions.TestFunctions.testDots #{ asdf <- function(x,...) UseMethod("asdf",x); asdf.numeric <- function(x, ...) print(paste("num:", x, ...)); asdf(1) } [1] "num: 1" @@ -106318,6 +106354,110 @@ debug at #4: t exiting from: f(5) [1] 6 +##com.oracle.truffle.r.test.library.utils.TestTrace.testCondTrace +#f <- function(x) {}; (if (exists('.fastr.trace')) .fastr.trace else trace)(f, tracer=quote(if (x == 3 || x == 7) print(x))); g <- function() for (i in 1:10) f(i); g() +[1] "f" +Tracing f(i) on entry +Tracing f(i) on entry +Tracing f(i) on entry +[1] 3 +Tracing f(i) on entry +Tracing f(i) on entry +Tracing f(i) on entry +Tracing f(i) on entry +[1] 7 +Tracing f(i) on entry +Tracing f(i) on entry +Tracing f(i) on entry + +##com.oracle.truffle.r.test.library.utils.TestTrace.testCondTrace +#f <- function(x) {}; trace(f, tracer=quote(if (x == 3 || x == 7) print(x))); g <- function() for (i in 1:10) f(i); g() +[1] "f" +Tracing f(i) on entry +Tracing f(i) on entry +Tracing f(i) on entry +[1] 3 +Tracing f(i) on entry +Tracing f(i) on entry +Tracing f(i) on entry +Tracing f(i) on entry +[1] 7 +Tracing f(i) on entry +Tracing f(i) on entry +Tracing f(i) on entry + +##com.oracle.truffle.r.test.library.utils.TestTrace.testMultiTrace +#f <- function(x) {}; (if (exists('.fastr.trace')) .fastr.trace else trace)(f, tracer=quote(print(x))); g <- function() for (i in 1:10) f(i); g() +[1] "f" +Tracing f(i) on entry +[1] 1 +Tracing f(i) on entry +[1] 2 +Tracing f(i) on entry +[1] 3 +Tracing f(i) on entry +[1] 4 +Tracing f(i) on entry +[1] 5 +Tracing f(i) on entry +[1] 6 +Tracing f(i) on entry +[1] 7 +Tracing f(i) on entry +[1] 8 +Tracing f(i) on entry +[1] 9 +Tracing f(i) on entry +[1] 10 + +##com.oracle.truffle.r.test.library.utils.TestTrace.testMultiTrace +#f <- function(x) {}; trace(f, tracer=quote(print(x))); g <- function() for (i in 1:10) f(i); g() +[1] "f" +Tracing f(i) on entry +[1] 1 +Tracing f(i) on entry +[1] 2 +Tracing f(i) on entry +[1] 3 +Tracing f(i) on entry +[1] 4 +Tracing f(i) on entry +[1] 5 +Tracing f(i) on entry +[1] 6 +Tracing f(i) on entry +[1] 7 +Tracing f(i) on entry +[1] 8 +Tracing f(i) on entry +[1] 9 +Tracing f(i) on entry +[1] 10 + +##com.oracle.truffle.r.test.library.utils.TestTrace.testSimple +#f <- function(x) {}; (if (exists('.fastr.trace')) .fastr.trace else trace)(f); f() +trace: f() +NULL + +##com.oracle.truffle.r.test.library.utils.TestTrace.testSimple +#f <- function(x) {}; trace(f); f() +trace: f() +NULL + +##com.oracle.truffle.r.test.library.utils.TestTrace.testSimpleTrace +#f <- function(x) {}; (if (exists('.fastr.trace')) .fastr.trace else trace)(f, tracer=quote(print(x))); f(100) +[1] "f" +Tracing f(100) on entry +[1] 100 +NULL + +##com.oracle.truffle.r.test.library.utils.TestTrace.testSimpleTrace +#f <- function(x) {}; trace(f, tracer=quote(print(x))); f(100) +[1] "f" +Tracing f(100) on entry +[1] 100 +NULL + ##com.oracle.truffle.r.test.library.utils.TestUtils.testHeadNTail #{head(letters)} [1] "a" "b" "c" "d" "e" "f" diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java index 1d32d7b884107d3adcefbdc4b1df28aa8f96f80e..610e8a0c3c45cf3185af28ae89f100440b8b68bd 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_isna.java @@ -265,5 +265,8 @@ public class TestBuiltin_isna extends TestBase { assertEval("{ is.na(list(1[10],1L[10],list(),integer())) }"); assertEval(Output.ContainsWarning, "is.na(quote(x()))"); assertEval("is.na(is.na))"); + + // Note: is.na.data.frame calls do.call("cbind", lapply(x, "is.na")) - there is the error + assertEval(Ignored.Unimplemented, "is.na(data.frame(col1=1:5, col2=c(NA, 1, NA, 2, NA)))"); } } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java index 147b62182ec86227055a1a6a917e21cc90e868b9..134587376b167655ccbc67329bd787200dec691b 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_operators.java @@ -1921,6 +1921,13 @@ public class TestBuiltin_operators extends TestBase { assertEval("argv <- list(181L, 3.14159265358979);`*`(argv[[1]],argv[[2]]);"); } + @Test + public void testDispatchToOpsSpecializations() { + assertEval(Output.ContainsError, "factor(c(\"a\",\"b\",\"c\")) == factor(c(1,2,3))"); + assertEval("data.frame(factor(c(1,2,3))) == data.frame(factor(c(1,2,3)))"); + assertEval("data.frame(factor(c(1,2,1))) == data.frame(factor(c(1,2,2)))"); + } + @Test public void testOperators() { assertEval("{ `+`(1,2) }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java index f5e7184962b27130766598232c77023bef39f779..5d0a4c7bf52c1e6c7748fb3f5a8a7ad7d5b0d177 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/functions/TestFunctions.java @@ -217,6 +217,11 @@ public class TestFunctions extends TestBase { "e2 <- new.env(); e2n <- new.env(); assign(\"b\", \"isb\", e2n); assign(\"ex\", e2n, e2); ex1 <- c(\"a\"); ex2 <- c(\"b\"); f(e1, ex1); f(e2, ex2) == \"isb\""); } + @Test + public void testArgEvaluationOrder() { + assertEval("v <- 1; class(v) <- 'foo'; `-.foo` <- function(x,y,...) { cat('[-.foo]'); 1234 }; g <- function(...) { cat('[ing]'); ({cat('[-]'); `-`})(...) }; ({cat('[g]'); g})({cat('[x]'); v},{cat('[y]'); 3},{cat('[z]'); 5})"); + } + @Test public void testMatching() { assertEval("{ x<-function(foo,bar){foo*bar} ; x(f=10,2) }"); @@ -311,7 +316,7 @@ public class TestFunctions extends TestBase { assertEval("f2 <- function(...) { f <- function() cat(...); f() }; f2()"); assertEval("f2 <- function(...) { f <- function() cat(...); environment(f) <- globalenv(); f() }; f2()"); assertEval("f2 <- function(...) { f <- function() cat(...); f() }; f2(\"a\")"); - assertEval("f2 <- function(...) { f <- function() cat(...); assign(\"...\", NULL); f() }; f2(\"a\")"); + assertEval(Ignored.ImplementationError, "f2 <- function(...) { f <- function() cat(...); assign(\"...\", NULL); f() }; f2(\"a\")"); assertEval("f2 <- function(...) { f <- function() cat(...); assign(\"...\", \"asdf\"); f() }; f2(\"a\")"); assertEval("{ g <- function(a,b,x) { a + b * x } ; f <- function(...) { g(x=4, ..., 10) } ; f(b=1,a=2) }"); @@ -319,6 +324,8 @@ public class TestFunctions extends TestBase { assertEval("{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, ..., xxx=2) } ; g(1) }"); assertEval("{ f <- function(a, barg, bextra, dummy) { a + barg } ; g <- function(...) { f(a=1, xxx=2, ...) } ; g(1) }"); + assertEval("{ `-.foo` <- function(...) 123; v <- 1; class(v) <- 'foo'; sapply(1,`-`,v); sapply(v,`-`,1); sapply(v,`-`,v) }"); + assertEval(Ignored.Unknown, "{ f <- function(...) { substitute(..1) } ; f(x+y) }"); assertEval(Ignored.Unknown, Output.ContainsError, "{ lapply(1:3, \"dummy\") }"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTrace.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTrace.java new file mode 100644 index 0000000000000000000000000000000000000000..5a09217420b34d17cd213b0a9538913e0936e053 --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/library/utils/TestTrace.java @@ -0,0 +1,54 @@ +/* + * 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.test.library.utils; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestTrace extends TestBase { + private static final String FASTR_TRACE = "(if (exists('.fastr.trace')) .fastr.trace else trace)"; + private static final String PLAIN_TRACE = "trace"; + private static final String[] TRACE_VARIANTS = new String[]{PLAIN_TRACE, FASTR_TRACE}; + + @Test + public void testSimple() { + assertEval(template("f <- function(x) {}; %0(f); f()", TRACE_VARIANTS)); + } + + @Test + public void testSimpleTrace() { + assertEval(template("f <- function(x) {}; %0(f, tracer=quote(print(x))); f(100)", TRACE_VARIANTS)); + } + + @Test + public void testMultiTrace() { + assertEval(template("f <- function(x) {}; %0(f, tracer=quote(print(x))); g <- function() for (i in 1:10) f(i); g()", TRACE_VARIANTS)); + } + + @Test + public void testCondTrace() { + assertEval(template("f <- function(x) {}; %0(f, tracer=quote(if (x == 3 || x == 7) print(x))); g <- function() for (i in 1:10) f(i); g()", TRACE_VARIANTS)); + } + +} diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index db81248acc0e31a90b87084e44548dadc924e74a..39bdc1aaa7c197218691ebd726a6882c5860232d 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -171,7 +171,6 @@ com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessSlotNode. com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/UpdateSlotNode.java,gnu_r_gentleman_ihaka.copyright com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/binary/CastTypeNode.java,purdue.copyright com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java,purdue.copyright -com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java,purdue.copyright com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java,purdue.copyright com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodInternalNode.java,purdue.copyright com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/objects/AsS4.java,gnu_r_gentleman_ihaka.copyright