From bd3fc8c77938bb358f3acfbd16ce98c0dccc4d66 Mon Sep 17 00:00:00 2001 From: Lukas Stadler <lukas.stadler@oracle.com> Date: Mon, 30 Mar 2015 13:51:59 +0200 Subject: [PATCH] simplify and unify group generics implementation --- .../com/oracle/truffle/r/nodes/RASTUtils.java | 18 +- .../truffle/r/nodes/RTruffleVisitor.java | 7 +- .../r/nodes/access/AccessArgumentNode.java | 2 + .../array/write/UpdateArrayHelperNode.java | 2 - .../r/nodes/function/ArgumentsNode.java | 1 + .../function/BinaryOpsGroupDispatchNode.java | 136 ------ .../r/nodes/function/DispatchNode.java | 43 -- .../r/nodes/function/DispatchedCallNode.java | 210 --------- .../nodes/function/GroupDispatchCallNode.java | 417 ------------------ .../r/nodes/function/GroupDispatchNode.java | 184 ++++++++ .../function/NextMethodDispatchNode.java | 225 ---------- .../r/nodes/function/S3DispatchNode.java | 348 --------------- .../function/UnaryOpsGroupDispatchNode.java | 59 --- .../nodes/function/UseMethodDispatchNode.java | 355 --------------- .../truffle/r/nodes/runtime/RASTDeparse.java | 4 +- .../r/nodes/runtime/RASTHelperImpl.java | 4 +- .../oracle/truffle/r/runtime/RArguments.java | 1 + .../com/oracle/truffle/r/runtime/RError.java | 1 + .../truffle/r/runtime/RGroupGenerics.java | 191 ++++---- 19 files changed, 285 insertions(+), 1923 deletions(-) delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/BinaryOpsGroupDispatchNode.java delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchNode.java delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchedCallNode.java delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchCallNode.java create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/NextMethodDispatchNode.java delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3DispatchNode.java delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnaryOpsGroupDispatchNode.java delete mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java 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 8f4f5953ce..c0b9b05c59 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 @@ -191,9 +191,9 @@ public class RASTUtils { return RCallNode.createCall(null, RASTUtils.createReadVariableNode(((String) fn)), callArgsNode, null); } else if (fn instanceof ReadVariableNode) { return RCallNode.createCall(null, (ReadVariableNode) fn, callArgsNode, null); - } else if (fn instanceof GroupDispatchCallNode) { - GroupDispatchCallNode gdcn = (GroupDispatchCallNode) fn; - return GroupDispatchCallNode.create(gdcn.getGenericName(), gdcn.getGroupName(), callArgsNode, gdcn.getCallSrc()); + } else if (fn instanceof GroupDispatchNode) { + GroupDispatchNode gdcn = (GroupDispatchNode) fn; + return GroupDispatchNode.create(gdcn.getGenericName(), gdcn.getGroup(), callArgsNode, gdcn.getCallSrc()); } else { RFunction rfn = (RFunction) fn; return RCallNode.createCall(null, ConstantNode.create(rfn), callArgsNode, null); @@ -201,7 +201,7 @@ public class RASTUtils { } /** - * Really should not be necessary, but things like '+' ({@link DispatchedCallNode}) have a + * Really should not be necessary, but things like '+' ({@link GroupDispatchNode}) have a * different AST structure from normal calls. */ private static class CallArgsNodeFinder implements NodeVisitor { @@ -234,7 +234,7 @@ public class RASTUtils { /** * Returns the name (as an {@link RSymbol} or the function associated with an {@link RCallNode} - * or {@link DispatchedCallNode}. + * or {@link GroupDispatchNode}. * * @param escape Add escape characters to non-standard names */ @@ -248,8 +248,8 @@ public class RASTUtils { name = escapeName(name); } return RDataFactory.createSymbol(name); - } else if (child instanceof GroupDispatchCallNode) { - GroupDispatchCallNode groupDispatchNode = (GroupDispatchCallNode) child; + } else if (child instanceof GroupDispatchNode) { + GroupDispatchNode groupDispatchNode = (GroupDispatchNode) child; String gname = groupDispatchNode.getGenericName(); if (escape) { gname = escapeName(gname); @@ -274,12 +274,12 @@ public class RASTUtils { /** * Returns the {@link ReadVariableNode} associated with a {@link RCallNode} or the - * {@link GroupDispatchCallNode} . + * {@link GroupDispatchNode} . */ public static RNode findFunctionNode(Node node) { if (node instanceof RCallNode) { return ((RCallNode) node).getFunctionNode(); - } else if (node instanceof GroupDispatchCallNode) { + } else if (node instanceof GroupDispatchNode) { return (RNode) node; } assert false; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java index fd77df9068..7b0b3614e3 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/RTruffleVisitor.java @@ -118,7 +118,7 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> { if (callName != null) { String functionName = callName; if (!FastROptions.DisableGroupGenerics.getValue() && RGroupGenerics.isGroupGeneric(functionName)) { - return GroupDispatchCallNode.create(functionName, RGroupGenerics.getGroup(functionName), aCallArgNode, callSource); + return GroupDispatchNode.create(functionName, RGroupGenerics.getGroup(functionName), aCallArgNode, callSource); } return RCallNode.createCall(callSource, ReadVariableNode.createForced(functionName, RType.Function), aCallArgNode, callParam); } else { @@ -212,7 +212,8 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> { String functionName = op.getOperator().getName(); CallArgumentsNode aCallArgNode = CallArgumentsNode.createUnnamed(false, true, operand); if (!FastROptions.DisableGroupGenerics.getValue() && RGroupGenerics.isGroupGeneric(functionName)) { - return GroupDispatchCallNode.create(functionName, RGroupGenerics.GROUP_OPS, aCallArgNode, op.getSource()); + assert RGroupGenerics.getGroup(functionName) == RGroupGenerics.Ops; + return GroupDispatchNode.create(functionName, RGroupGenerics.Ops, aCallArgNode, op.getSource()); } return RCallNode.createStaticCall(op.getSource(), functionName, aCallArgNode, op); } @@ -227,7 +228,7 @@ public final class RTruffleVisitor extends BasicVisitor<RNode> { String functionName = op.getOperator().getName(); CallArgumentsNode aCallArgNode = CallArgumentsNode.createUnnamed(false, true, left, right); if (!FastROptions.DisableGroupGenerics.getValue() && RGroupGenerics.isGroupGeneric(functionName)) { - return GroupDispatchCallNode.create(functionName, RGroupGenerics.getGroup(functionName), aCallArgNode, op.getSource()); + return GroupDispatchNode.create(functionName, RGroupGenerics.getGroup(functionName), aCallArgNode, op.getSource()); } return RCallNode.createStaticCall(op.getSource(), functionName, aCallArgNode, op); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java index 033997b1fc..daf546e131 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/AccessArgumentNode.java @@ -31,6 +31,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.r.nodes.*; import com.oracle.truffle.r.nodes.access.variables.*; +import com.oracle.truffle.r.nodes.builtin.*; import com.oracle.truffle.r.nodes.function.*; import com.oracle.truffle.r.nodes.function.opt.*; import com.oracle.truffle.r.runtime.*; @@ -93,6 +94,7 @@ public abstract class AccessArgumentNode extends RNode { @Specialization(guards = {"hasDefaultArg()"}) protected Object doArgumentDefaultArg(VirtualFrame frame, @SuppressWarnings("unused") RMissing argMissing) { + assert !(getRootNode() instanceof RBuiltinRootNode) : getRootNode(); Object result; if (canBeOptimized()) { // Insert default value diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java index 4d294f138a..7bb262c5da 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/access/array/write/UpdateArrayHelperNode.java @@ -29,7 +29,6 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.*; import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.Node.*; import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.utilities.*; import com.oracle.truffle.r.nodes.*; @@ -38,7 +37,6 @@ import com.oracle.truffle.r.nodes.access.array.ArrayPositionCast.OperatorConvert import com.oracle.truffle.r.nodes.access.array.ArrayPositionCastNodeGen.OperatorConverterNodeGen; import com.oracle.truffle.r.nodes.access.array.read.*; import com.oracle.truffle.r.nodes.function.*; -import com.oracle.truffle.r.nodes.function.DispatchedCallNode.*; import com.oracle.truffle.r.nodes.unary.*; import com.oracle.truffle.r.runtime.*; import com.oracle.truffle.r.runtime.RDeparse.State; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentsNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentsNode.java index b7ff42f2f0..1079a1da36 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentsNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/ArgumentsNode.java @@ -47,6 +47,7 @@ public abstract class ArgumentsNode extends RNode implements ArgumentsTrait { assert signature != null && signature.getLength() == arguments.length : Arrays.toString(arguments) + " " + signature; this.arguments = arguments; this.signature = signature; + assert signature != null; } @CreateWrapper diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/BinaryOpsGroupDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/BinaryOpsGroupDispatchNode.java deleted file mode 100644 index 4e7782eca3..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/BinaryOpsGroupDispatchNode.java +++ /dev/null @@ -1,136 +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-2015, Purdue University - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.nodes.function; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; - -public class BinaryOpsGroupDispatchNode extends GroupDispatchNode { - - private String targetFunctionNameR; - protected RFunction targetFunctionR; - private RStringVector klassR; - private RStringVector typeL; - private RStringVector typeR; - private boolean writeGroupR; - protected boolean isBuiltinCalled; - - public BinaryOpsGroupDispatchNode(final String aGenericName, boolean hasVararg, SourceSection callSrc, SourceSection argSrc) { - super(aGenericName, RGroupGenerics.GROUP_OPS, hasVararg, callSrc, argSrc); - } - - private void initDispatchTypes(final Object[] evaluatedArgs) { - // This is kind of tricky. We want to evaluate args before we know the function for which - // arguments should be matched. But as OpsGroupDispatchNode is for BinaryOperators, we can - // assume that arguments are in correct order! - this.typeL = getArgClass(evaluatedArgs[0]); - this.typeR = getArgClass(evaluatedArgs[1]); - } - - @Override - public Object execute(VirtualFrame frame, final RArgsValuesAndNames argAndNames) { - Object[] evaluatedArgs = argAndNames.getValues(); - ArgumentsSignature signature = argAndNames.getSignature(); - if (!isExecuted) { - isExecuted = true; - executeNoCache(frame, evaluatedArgs); - } - if (isBuiltinCalled || (targetFunctionR == null && targetFunction == null)) { - return callBuiltin(frame, evaluatedArgs, signature); - } - return executeHelper(frame, evaluatedArgs, signature); - } - - @Override - public boolean isSameType(Object[] args) { - return !isExecuted || isEqualType(getArgClass(args[0]), this.typeL) && isEqualType(getArgClass(args[1]), this.typeR); - } - - protected void executeNoCache(VirtualFrame frame, Object[] evaluatedArgs) { - initDispatchTypes(evaluatedArgs); - if (this.typeR != null) { - this.type = this.typeR; - findTargetFunction(frame); - targetFunctionNameR = targetFunctionName; - targetFunctionR = targetFunction; - klassR = klass; - writeGroupR = writeGroup; - } else { - targetFunctionR = null; - } - if (this.typeL != null) { - this.type = this.typeL; - findTargetFunction(frame); - } else { - targetFunction = null; - } - if (targetFunctionR == null && targetFunction == null) { - isBuiltinCalled = true; - return; - } - if (targetFunctionR != targetFunction) { - if (targetFunctionR != null && targetFunction != null) { - if (targetFunctionName.equals("Ops.difftime") && targetFunctionNameR.equals("+.POSIXt") && targetFunctionNameR.equals("+.Date")) { - targetFunction = null; - } else if (!(targetFunctionNameR.equals("Ops.difftime") && targetFunctionName.equals("+.POSIXt") && targetFunctionName.equals("-.POSIXt") && targetFunctionNameR.equals("+.Date") && targetFunctionNameR.equals("-.Date"))) { - /* - * TODO: throw warning - * "Incompatible methods (\"%s\", \"%s\") for \"%s\""),lname,rname, generic - */ - isBuiltinCalled = true; - return; - } - } - if (targetFunction == null) { - targetFunction = targetFunctionR; - targetFunctionName = targetFunctionNameR; - klass = klassR; - writeGroup = writeGroupR; - this.type = this.typeR; - } - } - String[] methods = new String[evaluatedArgs.length]; - for (int i = 0; i < methods.length; ++i) { - methods[i] = ""; - RStringVector classHr = getArgClass(evaluatedArgs[i]); - if (classHr == null) { - continue; - } - for (int j = 0; j < classHr.getLength(); ++j) { - if (classHr.getDataAt(j).equals(klass.getDataAt(0))) { - methods[i] = targetFunctionName; - break; - } - } - } - dotMethod = RDataFactory.createStringVector(methods, true); - } -} - -class GenericBinarysOpsGroupDispatchNode extends BinaryOpsGroupDispatchNode { - - public GenericBinarysOpsGroupDispatchNode(String aGenericName, boolean hasVararg, SourceSection callSrc, SourceSection argSrc) { - super(aGenericName, hasVararg, callSrc, argSrc); - } - - @Override - public Object execute(VirtualFrame frame, final RArgsValuesAndNames argAndNames) { - Object[] evaluatedArgs = argAndNames.getValues(); - executeNoCache(frame, evaluatedArgs); - if (isBuiltinCalled || (targetFunctionR == null && targetFunction == null)) { - return callBuiltin(frame, evaluatedArgs, argAndNames.getSignature()); - } - return executeHelper(frame, evaluatedArgs, argAndNames.getSignature()); - } - -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchNode.java deleted file mode 100644 index 49a5359890..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchNode.java +++ /dev/null @@ -1,43 +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) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ - -package com.oracle.truffle.r.nodes.function; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.function.DispatchedCallNode.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; - -public abstract class DispatchNode extends RNode { - - protected final String genericName; - - protected DispatchNode(String genericName) { - this.genericName = genericName; - } - - public abstract Object executeGeneric(VirtualFrame frame, RStringVector aType); - - @SuppressWarnings("unused") - public Object executeInternalGeneric(VirtualFrame frame, RStringVector aType, Object[] args) throws NoGenericMethodException { - throw RInternalError.shouldNotReachHere(); - } - - @SuppressWarnings("unused") - public Object executeInternal(VirtualFrame frame, Object[] args) throws NoGenericMethodException { - throw RInternalError.shouldNotReachHere(); - } - - public String getGenericName() { - return genericName; - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchedCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchedCallNode.java deleted file mode 100644 index 6a83bc2121..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/DispatchedCallNode.java +++ /dev/null @@ -1,210 +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) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ - -package com.oracle.truffle.r.nodes.function; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.utilities.*; -import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; - -public abstract class DispatchedCallNode extends RNode { - - public static final class NoGenericMethodException extends ControlFlowException { - private static final long serialVersionUID = 344198853147758435L; - } - - public static enum DispatchType { - UseMethod, - NextMethod - } - - private static final int INLINE_CACHE_SIZE = 4; - - public static DispatchedCallNode create(String genericName, DispatchType dispatchType, ArgumentsSignature signature) { - return new UninitializedDispatchedCallNode(genericName, dispatchType, signature); - } - - public static DispatchedCallNode create(String genericName, String enclosingName, DispatchType dispatchType, Object[] args, ArgumentsSignature signature) { - return new UninitializedDispatchedCallNode(genericName, enclosingName, dispatchType, args, signature); - } - - @Override - public Object execute(VirtualFrame frame) { - throw RInternalError.shouldNotReachHere(); - } - - public abstract Object execute(VirtualFrame frame, RStringVector type); - - public abstract Object executeInternal(VirtualFrame frame, RStringVector type, Object[] args) throws NoGenericMethodException; - - @Override - public boolean isSyntax() { - return true; - } - - @NodeInfo(cost = NodeCost.UNINITIALIZED) - private static final class UninitializedDispatchedCallNode extends DispatchedCallNode { - private final int depth; - private final String genericName; - private final String enclosingName; - private final DispatchType dispatchType; - @CompilationFinal private final Object[] args; - private final ArgumentsSignature signature; - - private UninitializedDispatchedCallNode(String genericName, String enclosingName, DispatchType dispatchType, Object[] args, ArgumentsSignature signature) { - this.genericName = genericName; - this.enclosingName = enclosingName; - this.signature = signature; - this.depth = 0; - this.dispatchType = dispatchType; - this.args = args; - } - - public UninitializedDispatchedCallNode(String genericName, DispatchType dispatchType, ArgumentsSignature signature) { - this(genericName, null, dispatchType, null, signature); - } - - private UninitializedDispatchedCallNode(UninitializedDispatchedCallNode copy, int depth) { - this.depth = depth; - this.genericName = copy.genericName; - this.enclosingName = copy.enclosingName; - this.dispatchType = copy.dispatchType; - this.signature = copy.signature; - this.args = null; - } - - @Override - public Object execute(VirtualFrame frame, RStringVector type) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - return specialize(type).execute(frame, type); - } - - @Override - public Object executeInternal(VirtualFrame frame, RStringVector type, @SuppressWarnings("hiding") Object[] args) throws NoGenericMethodException { - CompilerDirectives.transferToInterpreterAndInvalidate(); - return specialize(type).executeInternal(frame, type, args); - } - - private DispatchedCallNode specialize(RStringVector type) { - CompilerAsserts.neverPartOfCompilation(); - if (depth < INLINE_CACHE_SIZE) { - DispatchNode current = createCurrentNode(type, true); - return replace(new CachedNode(current, new UninitializedDispatchedCallNode(this, depth + 1), type)); - } - RError.performanceWarning("S3 method dispatch fallback to generic"); - return this.replace(new GenericDispatchNode(createCurrentNode(type, false))); - } - - private DispatchNode createCurrentNode(RStringVector type, boolean cached) { - switch (dispatchType) { - case NextMethod: - return new NextMethodDispatchNode(genericName, type, args, signature, enclosingName); - case UseMethod: - return cached ? UseMethodDispatchNode.createCached(genericName, type, signature) : UseMethodDispatchNode.createGeneric(genericName, signature); - default: - throw RInternalError.shouldNotReachHere(); - } - } - } - - private static final class GenericDispatchNode extends DispatchedCallNode { - - @Child private DispatchNode dcn; - - public GenericDispatchNode(DispatchNode dcn) { - this.dcn = dcn; - } - - @Override - public Object execute(VirtualFrame frame, RStringVector type) { - return dcn.executeGeneric(frame, type); - } - - @Override - public Object executeInternal(VirtualFrame frame, RStringVector type, Object[] args) throws NoGenericMethodException { - return dcn.executeInternalGeneric(frame, type, args); - } - } - - private static final class CachedNode extends DispatchedCallNode { - - private final ConditionProfile sameIdentityProfile = ConditionProfile.createBinaryProfile(); - private final BranchProfile nullTypeProfile = BranchProfile.create(); - private final BranchProfile lengthMismatch = BranchProfile.create(); - private final BranchProfile notIdentityEqualElements = BranchProfile.create(); - - @Child private DispatchedCallNode nextNode; - @Child private DispatchNode currentNode; - private final RStringVector cachedType; - @CompilationFinal private final String[] cachedTypeElements; - - CachedNode(DispatchNode currentNode, DispatchedCallNode nextNode, RStringVector type) { - this.nextNode = nextNode; - this.currentNode = currentNode; - this.cachedType = type; - this.cachedTypeElements = type.getDataCopy(); - } - - private boolean isEqualType(RStringVector type) { - if (sameIdentityProfile.profile(type == cachedType)) { - return true; - } - if (cachedType == null) { - return false; - } - if (type == null) { - nullTypeProfile.enter(); - return false; - } - if (type.getLength() != cachedTypeElements.length) { - lengthMismatch.enter(); - return false; - } - return compareLoop(type); - } - - @ExplodeLoop - private boolean compareLoop(RStringVector type) { - for (int i = 0; i < cachedTypeElements.length; i++) { - String elementOne = cachedTypeElements[i]; - String elementTwo = type.getDataAt(i); - if (elementOne != elementTwo) { - notIdentityEqualElements.enter(); - if (!elementOne.equals(elementTwo)) { - return false; - } - } - } - return true; - } - - @Override - public Object execute(VirtualFrame frame, RStringVector type) { - if (isEqualType(type)) { - return currentNode.execute(frame); - } - return nextNode.execute(frame, type); - } - - @Override - public Object executeInternal(VirtualFrame frame, RStringVector type, Object[] args) throws NoGenericMethodException { - if (isEqualType(type)) { - return currentNode.executeInternal(frame, args); - } - return nextNode.executeInternal(frame, type, args); - } - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchCallNode.java deleted file mode 100644 index fe54c0e22c..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchCallNode.java +++ /dev/null @@ -1,417 +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, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.nodes.function; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.access.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.runtime.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.RArguments.S3Args; -import com.oracle.truffle.r.runtime.RDeparse.State; -import com.oracle.truffle.r.runtime.data.*; -import com.oracle.truffle.r.runtime.data.model.*; -import com.oracle.truffle.r.runtime.env.*; - -import edu.umd.cs.findbugs.annotations.*; - -public abstract class GroupDispatchCallNode extends RNode { - - private static final int INLINE_CACHE_SIZE = 4; - @Child protected CallArgumentsNode callArgsNode; - - public static GroupDispatchCallNode create(String aGenericName, String groupName, CallArgumentsNode callArgNode, SourceSection callSrc) { - GroupDispatchCallNode gdcn = new UninitializedGroupDispatchCallNode(aGenericName, groupName, callArgNode); - gdcn.assignSourceSection(callSrc); - return gdcn; - } - - @Override - public Object execute(VirtualFrame frame) { - throw new UnsupportedOperationException(); - } - - public abstract Object execute(VirtualFrame frame, RArgsValuesAndNames argAndNames); - - public abstract String getGenericName(); - - public abstract String getGroupName(); - - public abstract SourceSection getCallSrc(); - - protected RArgsValuesAndNames evalArgs(VirtualFrame frame) { - UnrolledVariadicArguments unrolledArgs = callArgsNode.executeFlatten(frame); - RNode[] unevaledArgs = unrolledArgs.getArguments(); - Object[] evaledArgs = new Object[unevaledArgs.length]; - for (int i = 0; i < unevaledArgs.length; ++i) { - if (unevaledArgs[i] != null) { - evaledArgs[i] = unevaledArgs[i].execute(frame); - } else { - evaledArgs[i] = RMissing.instance; - } - } - // Delay assignment to allow recursion - RArgsValuesAndNames argAndNames = new RArgsValuesAndNames(evaledArgs, unrolledArgs.getSignature()); - return argAndNames; - } - - @Override - public boolean isSyntax() { - return true; - } - - @Override - public void deparse(State state) { - String name = getGenericName(); - RDeparse.Func func = RDeparse.getFunc(name); - if (func != null) { - // infix operator - RASTDeparse.deparseInfixOperator(state, this, func); - } else { - state.append(name); - this.callArgsNode.deparse(state); - } - } - - @Override - public RNode substitute(REnvironment env) { - // TODO substitute aDispatchNode - return RASTUtils.createCall(this, (CallArgumentsNode) callArgsNode.substitute(env)); - } - - private static class UninitializedGroupDispatchCallNode extends GroupDispatchCallNode { - - private final String groupName; - @CompilationFinal private final String genericName; - private final int depth; - - public UninitializedGroupDispatchCallNode(String aGenericName, String groupName, CallArgumentsNode callArgNode) { - this.genericName = aGenericName; - this.groupName = groupName; - this.callArgsNode = callArgNode; - this.depth = 0; - } - - private UninitializedGroupDispatchCallNode(UninitializedGroupDispatchCallNode copy, int depth) { - this.genericName = copy.genericName; - this.groupName = copy.groupName; - this.callArgsNode = copy.callArgsNode; - this.depth = depth; - this.assignSourceSection(copy.getSourceSection()); - } - - @Override - public Object execute(VirtualFrame frame) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - RArgsValuesAndNames argAndNames = evalArgs(frame); - return specialize(argAndNames).execute(frame, argAndNames); - } - - @Override - public Object execute(VirtualFrame frame, RArgsValuesAndNames argAndNames) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - return specialize(argAndNames).execute(frame, argAndNames); - } - - private GroupDispatchCallNode specialize(RArgsValuesAndNames argAndNames) { - CompilerAsserts.neverPartOfCompilation(); - if (depth < INLINE_CACHE_SIZE) { - final GroupDispatchNode current = createCurrentNode(argAndNames.getValues()); - final GroupDispatchCallNode cachedNode = new CachedNode(current, new UninitializedGroupDispatchCallNode(this, this.depth + 1), this.callArgsNode); - this.replace(cachedNode); - return cachedNode; - } - return this.replace(new GenericDispatchNode(createGenericNode(argAndNames.getValues()))); - } - - private GroupDispatchNode createGenericNode(Object[] evaluatedArgs) { - if (this.groupName == RGroupGenerics.GROUP_OPS) { - if (evaluatedArgs.length == 1) { - return new GenericUnaryOpsGroupDispatchNode(this.genericName, this.callArgsNode.containsVarArgsSymbol(), this.getSourceSection(), this.callArgsNode.getEncapsulatingSourceSection()); - } - if (evaluatedArgs.length >= 2) { - return new GenericBinarysOpsGroupDispatchNode(this.genericName, this.callArgsNode.containsVarArgsSymbol(), this.getSourceSection(), - this.callArgsNode.getEncapsulatingSourceSection()); - } - } - if (evaluatedArgs.length == 0 /* - * TODO add condition for when all the arguments are - * constant - */) { - return new GroupDispatchNode(this.genericName, this.groupName, this.callArgsNode.containsVarArgsSymbol(), this.getSourceSection(), this.callArgsNode.getEncapsulatingSourceSection()); - } - return new GenericGroupDispatchNode(this.genericName, this.groupName, this.callArgsNode.containsVarArgsSymbol(), this.getSourceSection(), this.callArgsNode.getEncapsulatingSourceSection()); - } - - @SuppressFBWarnings(value = "ES_COMPARING_STRINGS_WITH_EQ", justification = "GROUP_OPS is intended to be used as an identity") - protected GroupDispatchNode createCurrentNode(Object[] evaluatedArgs) { - if (this.groupName == RGroupGenerics.GROUP_OPS) { - if (evaluatedArgs.length == 1) { - return new UnaryOpsGroupDispatchNode(this.genericName, this.callArgsNode.containsVarArgsSymbol(), this.getSourceSection(), this.callArgsNode.getEncapsulatingSourceSection()); - } - if (evaluatedArgs.length >= 2) { - return new BinaryOpsGroupDispatchNode(this.genericName, this.callArgsNode.containsVarArgsSymbol(), this.getSourceSection(), this.callArgsNode.getEncapsulatingSourceSection()); - } - } - return new GroupDispatchNode(this.genericName, this.groupName, this.callArgsNode.containsVarArgsSymbol(), this.getSourceSection(), this.callArgsNode.getEncapsulatingSourceSection()); - } - - @Override - public String getGenericName() { - return this.genericName; - } - - @Override - public String getGroupName() { - return this.groupName; - } - - @Override - public SourceSection getCallSrc() { - return this.getSourceSection(); - } - } - - private static final class CachedNode extends GroupDispatchCallNode { - - @Child private GroupDispatchCallNode nextNode; - @Child private GroupDispatchNode currentNode; - - CachedNode(final GroupDispatchNode currentNode, GroupDispatchCallNode nextNode, CallArgumentsNode callArgsNode) { - this.nextNode = nextNode; - this.currentNode = currentNode; - this.callArgsNode = callArgsNode; - } - - @Override - public Object execute(VirtualFrame frame) { - RArgsValuesAndNames argsAndNames = evalArgs(frame); - if (currentNode.isSameType(argsAndNames.getValues())) { - return currentNode.execute(frame, argsAndNames); - } - return nextNode.execute(frame, argsAndNames); - } - - @Override - public Object execute(VirtualFrame frame, RArgsValuesAndNames argAndNames) { - if (currentNode.isSameType(argAndNames.getValues())) { - return currentNode.execute(frame, argAndNames); - } - return nextNode.execute(frame, argAndNames); - } - - @Override - public String getGenericName() { - return currentNode.genericName; - } - - @Override - public String getGroupName() { - return currentNode.groupName; - } - - @Override - public SourceSection getCallSrc() { - return currentNode.callSrc; - } - } - - private static final class GenericDispatchNode extends GroupDispatchCallNode { - - @Child private GroupDispatchNode gdn; - - public GenericDispatchNode(GroupDispatchNode gdn) { - this.gdn = gdn; - } - - @Override - public Object execute(VirtualFrame frame, RArgsValuesAndNames argAndNames) { - return gdn.execute(frame, argAndNames); - } - - @Override - public String getGenericName() { - return gdn.genericName; - } - - @Override - public String getGroupName() { - return gdn.groupName; - } - - @Override - public SourceSection getCallSrc() { - return gdn.callSrc; - } - } -} - -class GroupDispatchNode extends S3DispatchLegacyNode { - - @CompilationFinal protected boolean isExecuted = false; - @CompilationFinal protected final String groupName; - @Child protected ReadVariableNode builtInNode; - @Child private WriteVariableNode wvnGroup; - protected RFunction builtinFunc; - protected boolean writeGroup; - protected RStringVector dotMethod; - protected boolean hasVararg; - protected final SourceSection callSrc; - protected final SourceSection argSrc; - - private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); - - @Override - public Object executeGeneric(VirtualFrame frame, RStringVector aType) { - throw new AssertionError(); - } - - protected GroupDispatchNode(String genericName, String groupName, boolean hasVarArg, SourceSection callSrc, SourceSection argSrc) { - super(genericName, null); - this.groupName = groupName; - this.hasVararg = hasVarArg; - this.callSrc = callSrc; - this.argSrc = argSrc; - } - - public boolean isSameType(Object[] args) { - return !isExecuted || isEqualType(getArgClass(args[0]), this.type); - } - - protected void initBuiltin(VirtualFrame frame) { - // assuming builtin functions don't get redefined. - if (builtInNode == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - builtInNode = insert(ReadVariableNode.createFunctionLookup(genericName, true)); - try { - builtinFunc = builtInNode.executeFunction(frame); - } catch (UnexpectedResultException e) { - throw new RuntimeException("Builtin " + this.genericName + " not found"); - } - } - } - - protected void findTargetFunction(VirtualFrame frame) { - String[] prefix = {genericName, groupName}; - for (int i = 0; i < this.type.getLength(); ++i) { - for (int j = 0; j < prefix.length; ++j) { - findFunction(prefix[j], this.type.getDataAt(i), frame); - if (targetFunction != null) { - RStringVector classVec = null; - if (i > 0) { - isFirst = false; - classVec = RDataFactory.createStringVector(Arrays.copyOfRange(this.type.getDataWithoutCopying(), i, this.type.getLength()), true); - } else { - isFirst = true; - classVec = this.type.copyResized(this.type.getLength(), false); - } - klass = classVec; - if (j == 1) { - writeGroup = true; - } else { - writeGroup = false; - } - return; - } - } - } - } - - public Object execute(VirtualFrame frame, RArgsValuesAndNames argAndNames) { - Object[] evaluatedArgs = argAndNames.getValues(); - ArgumentsSignature signature = argAndNames.getSignature(); - if (!isExecuted) { - isExecuted = true; - this.type = evaluatedArgs.length > 0 ? getArgClass(evaluatedArgs[0]) : null; - if (this.type == null) { - return callBuiltin(frame, evaluatedArgs, signature); - } - findTargetFunction(frame); - if (targetFunction != null) { - dotMethod = RDataFactory.createStringVector(new String[]{targetFunctionName, ""}, true); - } - } - if (targetFunction == null) { - return callBuiltin(frame, evaluatedArgs, signature); - } - return executeHelper(frame, evaluatedArgs, signature); - } - - protected Object callBuiltin(VirtualFrame frame, Object[] evaluatedArgs, ArgumentsSignature argumentsSignature) { - initBuiltin(frame); - EvaluatedArguments reorderedArgs = reorderArgs(frame, builtinFunc, evaluatedArgs, argumentsSignature, this.hasVararg, this.callSrc); - Object[] argObject = RArguments.create(builtinFunc, this.callSrc, null, RArguments.getDepth(frame), reorderedArgs.getEvaluatedArgs(), reorderedArgs.getSignature()); - indirectCallNode.assignSourceSection(this.callSrc); - return indirectCallNode.call(frame, builtinFunc.getTarget(), argObject); - } - - protected Object executeHelper(VirtualFrame frame, Object[] evaluatedArgs, ArgumentsSignature argumentsSignature) { - EvaluatedArguments reorderedArgs = reorderArgs(frame, targetFunction, evaluatedArgs, argumentsSignature, this.hasVararg, this.callSrc); - Object[] argObject = RArguments.create(targetFunction, this.callSrc, null, RArguments.getDepth(frame) + 1, reorderedArgs.getEvaluatedArgs(), reorderedArgs.getSignature()); - genCallEnv = frame.materialize(); - RArguments.setS3Args(argObject, new S3Args(genericName, klass, dotMethod, genCallEnv, genDefEnv, writeGroup ? groupName : null)); - indirectCallNode.assignSourceSection(this.callSrc); - /* - * Create a new frame s3VarDefFrame and define s3 generic variables such as .Generic, - * .Method etc. in it and set this frame as the enclosing frame of the target function - * ensuring that these generic variables are available to the called function. The real - * enclosing frame of the target function become enclosing frame of the new frame - * s3VarDefFrame. After the function returns reset the enclosing frame of the target - * function. - */ - Object result = indirectCallNode.call(frame, targetFunction.getTarget(), argObject); - return result; - } - - protected RStringVector getArgClass(Object arg) { - if (arg instanceof RAbstractContainer && ((RAbstractContainer) arg).isObject(attrProfiles)) { - return ((RAbstractContainer) arg).getClassHierarchy(); - } - return null; - } - - @Override - public Object execute(VirtualFrame frame) { - throw new AssertionError(); - } -} - -class GenericGroupDispatchNode extends GroupDispatchNode { - - protected GenericGroupDispatchNode(String aGenericName, String groupName, boolean hasVarArg, SourceSection callSrc, SourceSection argSrc) { - super(aGenericName, groupName, hasVarArg, callSrc, argSrc); - } - - @Override - public Object execute(VirtualFrame frame, RArgsValuesAndNames argAndNames) { - Object[] evaluatedArgs = argAndNames.getValues(); - ArgumentsSignature signature = argAndNames.getSignature(); - this.type = getArgClass(evaluatedArgs[0]); - if (this.type == null) { - return callBuiltin(frame, evaluatedArgs, signature); - } - findTargetFunction(frame); - if (targetFunction != null) { - dotMethod = RDataFactory.createStringVector(new String[]{targetFunctionName, ""}, true); - } - if (targetFunction == null) { - callBuiltin(frame, evaluatedArgs, signature); - } - return executeHelper(frame, evaluatedArgs, signature); - } -} 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 new file mode 100644 index 0000000000..28b1c7ad4c --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/GroupDispatchNode.java @@ -0,0 +1,184 @@ +/* + * 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, Oracle and/or its affiliates + * + * All rights reserved. + */ +package com.oracle.truffle.r.nodes.function; + +import com.oracle.truffle.api.*; +import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.source.*; +import com.oracle.truffle.api.utilities.*; +import com.oracle.truffle.r.nodes.*; +import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.NoGenericMethodException; +import com.oracle.truffle.r.nodes.function.S3FunctionLookupNode.Result; +import com.oracle.truffle.r.nodes.runtime.*; +import com.oracle.truffle.r.runtime.*; +import com.oracle.truffle.r.runtime.RArguments.S3Args; +import com.oracle.truffle.r.runtime.RDeparse.State; +import com.oracle.truffle.r.runtime.data.*; +import com.oracle.truffle.r.runtime.data.model.*; +import com.oracle.truffle.r.runtime.env.*; + +public final class GroupDispatchNode extends RNode { + + @Child private CallArgumentsNode callArgsNode; + @Child private S3FunctionLookupNode functionLookupL; + @Child private S3FunctionLookupNode functionLookupR; + @Child private CallMatcherNode callMatcher = CallMatcherNode.create(false, true); + + private final String genericName; + private final RGroupGenerics group; + private final RFunction builtinFunc; + private final boolean binaryLookup; + + private final RAttributeProfiles attrProfiles = RAttributeProfiles.create(); + private final ConditionProfile mismatchProfile = ConditionProfile.createBinaryProfile(); + + public GroupDispatchNode(String genericName, RGroupGenerics group, CallArgumentsNode callArgNode) { + this.genericName = genericName.intern(); + this.group = group; + this.callArgsNode = callArgNode; + this.binaryLookup = group == RGroupGenerics.Ops && callArgsNode.getSignature().getLength() >= 2; + + this.builtinFunc = RContext.getEngine().lookupBuiltin(genericName); + } + + public static GroupDispatchNode create(String aGenericName, RGroupGenerics group, CallArgumentsNode callArgNode, SourceSection callSrc) { + GroupDispatchNode gdcn = new GroupDispatchNode(aGenericName, group, callArgNode); + gdcn.assignSourceSection(callSrc); + return gdcn; + } + + public String getGenericName() { + return genericName; + } + + public RGroupGenerics getGroup() { + return group; + } + + public SourceSection getCallSrc() { + return getSourceSection(); + } + + protected RArgsValuesAndNames evalArgs(VirtualFrame frame) { + UnrolledVariadicArguments unrolledArgs = callArgsNode.executeFlatten(frame); + RNode[] unevaledArgs = unrolledArgs.getArguments(); + Object[] evaledArgs = new Object[unevaledArgs.length]; + for (int i = 0; i < unevaledArgs.length; ++i) { + if (unevaledArgs[i] != null) { + evaledArgs[i] = unevaledArgs[i].execute(frame); + } else { + evaledArgs[i] = RMissing.instance; + } + } + // Delay assignment to allow recursion + return new RArgsValuesAndNames(evaledArgs, unrolledArgs.getSignature()); + } + + @Override + public boolean isSyntax() { + return true; + } + + @Override + public void deparse(State state) { + String name = getGenericName(); + RDeparse.Func func = RDeparse.getFunc(name); + if (func != null) { + // infix operator + RASTDeparse.deparseInfixOperator(state, this, func); + } else { + state.append(name); + callArgsNode.deparse(state); + } + } + + @Override + public RNode substitute(REnvironment env) { + // TODO substitute aDispatchNode + return RASTUtils.createCall(this, (CallArgumentsNode) callArgsNode.substitute(env)); + } + + protected RStringVector getArgClass(Object arg) { + if (arg instanceof RAbstractContainer && ((RAbstractContainer) arg).isObject(attrProfiles)) { + return ((RAbstractContainer) arg).getClassHierarchy(); + } + return null; + } + + @Override + public Object execute(VirtualFrame frame) { + RArgsValuesAndNames argAndNames = evalArgs(frame); + Object[] evaluatedArgs = argAndNames.getValues(); + + RStringVector typeL = evaluatedArgs.length == 0 ? null : getArgClass(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, group.getName(), frame.materialize(), null); + } catch (NoGenericMethodException e) { + // fall-through + } + } + Result resultR = null; + if (binaryLookup) { + RStringVector typeR = getArgClass(evaluatedArgs[1]); + if (typeR != null) { + try { + if (functionLookupR == null) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + functionLookupR = insert(S3FunctionLookupNode.create(false, false)); + } + resultR = functionLookupR.execute(frame, genericName, typeR, group.getName(), 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(getSourceSection(), 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(); + if (result == null) { + return callMatcher.execute(frame, signature, evaluatedArgs, builtinFunc, null); + } else { + S3Args s3Args = new S3Args(genericName, result.clazz, dotMethod, frame.materialize(), null, result.groupMatch ? group.getName() : null); + return callMatcher.execute(frame, signature, evaluatedArgs, result.function, s3Args); + } + } +} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/NextMethodDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/NextMethodDispatchNode.java deleted file mode 100644 index 49025ecfb2..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/NextMethodDispatchNode.java +++ /dev/null @@ -1,225 +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) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ - -package com.oracle.truffle.r.nodes.function; - -import java.util.*; - -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.r.nodes.access.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode.ReadKind; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.RArguments.S3Args; -import com.oracle.truffle.r.runtime.data.*; - -public final class NextMethodDispatchNode extends S3DispatchLegacyNode { - - @Child private ReadVariableNode rvnDefEnv = ReadVariableNode.create(RRuntime.RDotGenericDefEnv, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode rvnCallEnv = ReadVariableNode.create(RRuntime.RDotGenericCallEnv, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode rvnGroup = ReadVariableNode.create(RRuntime.RDotGroup, RType.Any, ReadKind.SilentLocal); - @Child private ReadVariableNode rvnMethod = ReadVariableNode.create(RRuntime.RDotMethod, RType.Any, ReadKind.SilentLocal); - @Child private WriteVariableNode wvnGroup; - private String group; - private String lastGroup; - private String storedFunctionName; - private String lastStoredFunctionName; - private String baseName; - private String[] prefix; - private boolean hasGroup; - private boolean lastHasGroup; - @CompilationFinal private final Object[] args; - - NextMethodDispatchNode(String genericName, RStringVector type, Object[] args, ArgumentsSignature suppliedSignature, String storedFunctionName) { - super(genericName, suppliedSignature); - this.type = type; - this.args = args; - this.storedFunctionName = storedFunctionName; - } - - @Override - public Object execute(VirtualFrame frame) { - readGenericVars(frame); - if (!isSame() || !isFirst) { - findTargetFunction(frame); - storeValues(); - } - return executeHelper(frame); - } - - @Override - public Object executeGeneric(VirtualFrame frame, RStringVector aType) { - readGenericVars(frame); - findTargetFunction(frame); - storeValues(); - return executeHelper(frame); - } - - private EvaluatedArguments processArgs(VirtualFrame frame) { - int argsLength = args == null ? 0 : args.length; - // Extract arguments from current frame... - ArgumentsSignature signature = RArguments.getSignature(frame); - Object[] funArgValues = new Object[signature.getLength() + argsLength]; - String[] funArgNames = new String[signature.getLength() + argsLength]; - int index = 0; - for (int fi = 0; fi < signature.getLength(); fi++) { - Object argVal = RArguments.getArgument(frame, fi); - if (argVal instanceof RArgsValuesAndNames) { - RArgsValuesAndNames varArgs = (RArgsValuesAndNames) argVal; - int varArgsLength = varArgs.length(); - if (varArgsLength != 1) { - funArgValues = Utils.resizeArray(funArgValues, funArgValues.length + varArgsLength - 1); - } - System.arraycopy(varArgs.getValues(), 0, funArgValues, index, varArgsLength); - if (varArgsLength != 1) { - funArgNames = Utils.resizeArray(funArgNames, funArgNames.length + varArgsLength - 1); - } - for (int i = 0; i < varArgsLength; i++) { - funArgNames[index++] = varArgs.getSignature().getName(i); - } - } else { - funArgValues[index] = argVal; - funArgNames[index] = signature.getName(fi); - index++; - } - } - if (argsLength > 0) { - for (int i = 0; i < argsLength; i++) { - funArgValues[index] = args[i]; - if (suppliedSignature != null) { - funArgNames[index] = suppliedSignature.getName(i); - } - index++; - } - } - - ArgumentsSignature evaluatedSignature = ArgumentsSignature.get(funArgNames); - - EvaluatedArguments evaledArgs = EvaluatedArguments.create(funArgValues, evaluatedSignature); - // ...to match them against the chosen function's formal arguments - EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(targetFunction, evaledArgs, getSourceSection(), true); - if (targetFunction.isBuiltin()) { - ArgumentMatcher.evaluatePromises(frame, promiseHelper, reorderedArgs.getEvaluatedArgs()); - } - return reorderedArgs; - } - - private Object executeHelper(VirtualFrame frame) { - EvaluatedArguments evaledArgs = processArgs(frame); - Object[] argObject = RArguments.create(targetFunction, getSourceSection(), null, RArguments.getDepth(frame) + 1, evaledArgs.getEvaluatedArgs(), evaledArgs.getSignature()); - RArguments.setS3Args(argObject, new S3Args(genericName, klass, storedFunctionName != null ? storedFunctionName : targetFunctionName, genCallEnv, genDefEnv, group)); - return indirectCallNode.call(frame, targetFunction.getTarget(), argObject); - } - - private boolean isSame() { - return lastHasGroup == hasGroup && isEqual(lastGroup, group) && isEqual(lastStoredFunctionName, storedFunctionName); - } - - private static boolean isEqual(String a, String b) { - if (a == null || b == null) { - return a == null && b == null; - } - return a.equals(b); - } - - private void findTargetFunction(VirtualFrame frame) { - int nextClassIndex = 0; - String currentFunctionName = storedFunctionName == null ? RArguments.getFunction(frame).getName() : storedFunctionName; - for (int i = 0; i < type.getLength(); ++i) { - if (RRuntime.toString(new StringBuffer(baseName).append(RRuntime.RDOT).append(type.getDataAt(i))).equals(currentFunctionName)) { - nextClassIndex = i + 1; - break; - } - } - final int firstClassIndex = nextClassIndex; - int index = 0; - // First try generic.class then group.class. - for (; nextClassIndex < type.getLength() && targetFunction == null; ++nextClassIndex) { - for (; index < prefix.length && targetFunction == null; findFunction(prefix[index++], type.getDataAt(nextClassIndex), genCallEnv)) { - } - } - if (firstClassIndex == nextClassIndex && index == 1) { - isFirst = true; - } else { - isFirst = false; - } - if (targetFunction == null) { - findFunction(this.genericName, RRuntime.DEFAULT, genCallEnv); - } - if (targetFunction == null) { - findFunction(this.genericName, frame); - if (targetFunction == null || !targetFunction.isBuiltin()) { - throw RError.error(getEncapsulatingSourceSection(), RError.Message.NO_METHOD_FOUND); - } - } - RStringVector classVec = null; - if (nextClassIndex == type.getLength()) { - classVec = RDataFactory.createStringVector(""); - } else { - classVec = RDataFactory.createStringVector(Arrays.copyOfRange(type.getDataWithoutCopying(), nextClassIndex, type.getLength()), true); - } - classVec.setAttr(RRuntime.PREVIOUS_ATTR_KEY, type.copyResized(type.getLength(), false)); - klass = classVec; - } - - private void storeValues() { - lastHasGroup = hasGroup; - lastGroup = group; - lastStoredFunctionName = storedFunctionName; - } - - private void readGenericVars(VirtualFrame frame) { - S3Args s3Args = RArguments.getS3Args(frame); - genDefEnv = s3Args == null ? null : s3Args.defEnv; - if (genDefEnv == null) { - genDefEnv = RArguments.getEnclosingFrame(frame); - } - genCallEnv = s3Args == null ? null : s3Args.callEnv; - if (genCallEnv == null) { - genCallEnv = frame.materialize(); - } - group = s3Args == null ? null : s3Args.group; - if (group == null || group.isEmpty()) { - handleMissingGroup(); - } else { - handlePresentGroup(); - } - - Object method = s3Args == null ? null : s3Args.method; - String functionName; - if (method == null) { - functionName = null; - } else if (method instanceof String) { - functionName = (String) method; - } else { - functionName = ((RStringVector) method).getDataAt(0); - } - if (functionName != null) { - storedFunctionName = functionName; - } - } - - private void handleMissingGroup() { - baseName = genericName; - prefix = new String[1]; - prefix[0] = genericName; - hasGroup = false; - } - - private void handlePresentGroup() { - baseName = group; - prefix = new String[2]; - prefix[0] = genericName; - prefix[1] = group; - hasGroup = true; - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3DispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3DispatchNode.java deleted file mode 100644 index 4427f3fb1c..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3DispatchNode.java +++ /dev/null @@ -1,348 +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) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ - -package com.oracle.truffle.r.nodes.function; - -import java.util.*; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.api.utilities.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.RArguments.S3Args; -import com.oracle.truffle.r.runtime.data.*; - -public abstract class S3DispatchNode extends DispatchNode { - - @Child protected PromiseHelperNode promiseHelper = new PromiseHelperNode(); - - protected final BranchProfile errorProfile = BranchProfile.create(); - private final ConditionProfile topLevelFrameProfile = ConditionProfile.createBinaryProfile(); - private final ConditionProfile callerFrameSlotPath = ConditionProfile.createBinaryProfile(); - private final ConditionProfile hasVarArgsProfile = ConditionProfile.createBinaryProfile(); - private final ValueProfile argumentCountProfile = ValueProfile.createPrimitiveProfile(); - - protected final ArgumentsSignature suppliedSignature; - - public S3DispatchNode(String genericName, ArgumentsSignature suppliedSignature) { - super(genericName); - this.suppliedSignature = suppliedSignature; - } - - protected MaterializedFrame getCallerFrame(VirtualFrame frame) { - MaterializedFrame funFrame = RArguments.getCallerFrame(frame); - if (callerFrameSlotPath.profile(funFrame == null)) { - funFrame = Utils.getCallerFrame(frame, FrameAccess.MATERIALIZE).materialize(); - RError.performanceWarning("slow caller frame access in UseMethod dispatch"); - } - // S3 method can be dispatched from top-level where there is no caller frame - return topLevelFrameProfile.profile(funFrame == null) ? frame.materialize() : funFrame; - } - - protected Object[] extractArguments(VirtualFrame frame, boolean fixedLength) { - int argCount = argumentCountProfile.profile(RArguments.getArgumentsLength(frame)); - Object[] argValues = new Object[argCount]; - if (fixedLength) { - extractArgumentsLoopFixedLength(frame, argCount, argValues); - } else { - extractArgumentsLoop(frame, argCount, argValues); - } - return argValues; - } - - private static void extractArgumentsLoop(VirtualFrame frame, int argCount, Object[] argValues) { - for (int i = 0; i < argCount; i++) { - argValues[i] = RArguments.getArgument(frame, i); - } - } - - @ExplodeLoop - private static void extractArgumentsLoopFixedLength(VirtualFrame frame, int argCount, Object[] argValues) { - for (int i = 0; i < argCount; i++) { - argValues[i] = RArguments.getArgument(frame, i); - } - } - - protected EvaluatedArguments reorderArguments(Object[] args, RFunction function, ArgumentsSignature paramSignature, SourceSection errorSourceSection) { - assert paramSignature.getLength() == args.length; - - int argCount = args.length; - int argListSize = argCount; - - boolean hasVarArgs = false; - for (int fi = 0; fi < argCount; ++fi) { - Object arg = args[fi]; - if (hasVarArgsProfile.profile(arg instanceof RArgsValuesAndNames)) { - hasVarArgs = true; - argListSize += ((RArgsValuesAndNames) arg).length() - 1; - } - } - Object[] argValues; - ArgumentsSignature signature; - if (hasVarArgs) { - argValues = new Object[argListSize]; - String[] argNames = new String[argListSize]; - int index = 0; - for (int fi = 0; fi < argCount; ++fi) { - Object arg = args[fi]; - if (arg instanceof RArgsValuesAndNames) { - RArgsValuesAndNames varArgs = (RArgsValuesAndNames) arg; - Object[] varArgValues = varArgs.getValues(); - ArgumentsSignature varArgSignature = varArgs.getSignature(); - for (int i = 0; i < varArgs.length(); i++) { - argNames[index] = varArgSignature.getName(i); - argValues[index++] = checkMissing(varArgValues[i]); - } - } else { - argNames[index] = paramSignature.getName(fi); - argValues[index++] = checkMissing(arg); - } - } - signature = ArgumentsSignature.get(argNames); - } else { - argValues = new Object[argCount]; - for (int i = 0; i < argCount; i++) { - argValues[i] = checkMissing(args[i]); - } - signature = paramSignature; - } - - // ...and use them as 'supplied' arguments... - EvaluatedArguments evaledArgs = EvaluatedArguments.create(argValues, signature); - - // ...to match them against the chosen function's formal arguments - EvaluatedArguments evaluated = ArgumentMatcher.matchArgumentsEvaluated(function, evaledArgs, errorSourceSection, false); - return evaluated; - } - - private final ValueProfile callerFrameProfile = ValueProfile.createClassProfile(); - - protected final Object[] prepareArguments(MaterializedFrame callerFrame, MaterializedFrame genericDefFrame, Object[] evaluatedArguments, ArgumentsSignature evaluatedSignature, RFunction function, - RStringVector clazz, String functionName) { - CompilerAsserts.partialEvaluationConstant(evaluatedArguments.length); - - MaterializedFrame profiledCallerFrame = callerFrameProfile.profile(callerFrame); - Object[] argObject = RArguments.create(function, getSourceSection(), null, RArguments.getDepth(profiledCallerFrame) + 1, evaluatedArguments, evaluatedSignature); - RArguments.setS3Args(argObject, new S3Args(genericName, clazz, functionName, profiledCallerFrame.materialize(), genericDefFrame, null)); - return argObject; - } - - protected static Object checkMissing(Object value) { - return RMissingHelper.isMissing(value) || (value instanceof RPromise && RMissingHelper.isMissingName((RPromise) value)) ? null : value; - } - - @TruffleBoundary - protected static String functionName(String generic, String className) { - return new StringBuilder(generic).append(RRuntime.RDOT).append(className).toString(); - } - - protected static final class TargetLookupResult { - public final ReadVariableNode[] unsuccessfulReads; - public final ReadVariableNode successfulRead; - public final RFunction targetFunction; - public final String targetFunctionName; - public final RStringVector clazz; - - public TargetLookupResult(ReadVariableNode[] unsuccessfulReads, ReadVariableNode successfulRead, RFunction targetFunction, String targetFunctionName, RStringVector clazz) { - this.unsuccessfulReads = unsuccessfulReads; - this.successfulRead = successfulRead; - this.targetFunction = targetFunction; - this.targetFunctionName = targetFunctionName; - this.clazz = clazz; - } - } - - protected static TargetLookupResult findTargetFunctionLookup(Frame lookupFrame, RStringVector type, String genericName, boolean createReadVariableNodes) { - CompilerAsserts.neverPartOfCompilation(); - RFunction targetFunction = null; - String targetFunctionName = null; - RStringVector clazz = null; - ArrayList<ReadVariableNode> unsuccessfulReads = createReadVariableNodes ? new ArrayList<>() : null; - - for (int i = 0; i <= type.getLength(); i++) { - String clazzName = i == type.getLength() ? RRuntime.DEFAULT : type.getDataAt(i); - String functionName = genericName + RRuntime.RDOT + clazzName; - ReadVariableNode rvn; - Object func; - if (createReadVariableNodes) { - rvn = ReadVariableNode.createFunctionLookup(functionName, false); - func = rvn.execute(null, lookupFrame); - } else { - rvn = null; - func = ReadVariableNode.lookupFunction(functionName, lookupFrame); - } - if (func != null) { - assert func instanceof RFunction; - targetFunctionName = functionName; - targetFunction = (RFunction) func; - - if (i == 0) { - clazz = type.copyResized(type.getLength(), false); - } else if (i == type.getLength()) { - clazz = null; - } else { - clazz = RDataFactory.createStringVector(Arrays.copyOfRange(type.getDataWithoutCopying(), i, type.getLength()), true); - clazz.setAttr(RRuntime.PREVIOUS_ATTR_KEY, type.copyResized(type.getLength(), false)); - } - ReadVariableNode[] array = createReadVariableNodes ? unsuccessfulReads.toArray(new ReadVariableNode[unsuccessfulReads.size()]) : null; - return new TargetLookupResult(array, rvn, targetFunction, targetFunctionName, clazz); - } else { - if (createReadVariableNodes) { - unsuccessfulReads.add(rvn); - } - } - } - if (createReadVariableNodes) { - return new TargetLookupResult(unsuccessfulReads.toArray(new ReadVariableNode[unsuccessfulReads.size()]), null, null, null, null); - } else { - return null; - } - } -} - -abstract class S3DispatchLegacyNode extends S3DispatchNode { - - protected RStringVector type; - - @Child protected IndirectCallNode indirectCallNode = Truffle.getRuntime().createIndirectCallNode(); - protected RStringVector klass; - protected MaterializedFrame genCallEnv; - protected MaterializedFrame genDefEnv; - protected boolean isFirst; - - @CompilationFinal private String lastFun; - @Child private ReadVariableNode lookup; - protected String targetFunctionName; - protected RFunction targetFunction; - - public S3DispatchLegacyNode(String genericName, ArgumentsSignature suppliedSignature) { - super(genericName, suppliedSignature); - } - - protected void findFunction(String functionName, Frame frame) { - if (lookup == null || !functionName.equals(lastFun)) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - lastFun = functionName; - ReadVariableNode rvn = ReadVariableNode.createFunctionLookup(functionName, false); - lookup = lookup == null ? insert(rvn) : lookup.replace(rvn); - } - targetFunction = null; - targetFunctionName = null; - Object func; - if (frame instanceof VirtualFrame) { - func = lookup.execute((VirtualFrame) frame); - } else { - func = lookup.execute(null, frame); - } - if (func != null) { - assert func instanceof RFunction; - targetFunctionName = functionName; - targetFunction = (RFunction) func; - } - } - - protected void findFunction(String generic, String className, Frame frame) { - checkLength(className, generic); - findFunction(functionName(generic, className), frame); - } - - private void checkLength(String className, String generic) { - // The magic number two taken from src/main/objects.c - if (className.length() + generic.length() + 2 > RRuntime.LEN_METHOD_NAME) { - throw RError.error(getEncapsulatingSourceSection(), RError.Message.TOO_LONG_CLASS_NAME, generic); - } - } - - protected EvaluatedArguments reorderArgs(VirtualFrame frame, RFunction func, Object[] evaluatedArgs, ArgumentsSignature signature, boolean hasVarArgs, SourceSection callSrc) { - Object[] evaluatedArgsValues = evaluatedArgs; - ArgumentsSignature evaluatedSignature; - int argCount = evaluatedArgs.length; - if (hasVarArgs) { - evaluatedSignature = signature; - } else { - String[] evaluatedArgNames = null; - evaluatedArgNames = new String[signature.getLength()]; - int fi = 0; - int index = 0; - int argListSize = evaluatedArgsValues.length; - for (; fi < argCount; ++fi) { - Object arg = evaluatedArgs[fi]; - if (arg instanceof RArgsValuesAndNames) { - RArgsValuesAndNames varArgsContainer = (RArgsValuesAndNames) arg; - argListSize += varArgsContainer.length() - 1; - evaluatedArgsValues = Utils.resizeArray(evaluatedArgsValues, argListSize); - // argNames can be null if no names for arguments have been specified - evaluatedArgNames = evaluatedArgNames == null ? new String[argListSize] : Utils.resizeArray(evaluatedArgNames, argListSize); - Object[] varArgsValues = varArgsContainer.getValues(); - for (int i = 0; i < varArgsContainer.length(); i++) { - evaluatedArgsValues[index] = checkMissing(varArgsValues[i]); - String name = varArgsContainer.getSignature().getName(i); - evaluatedArgNames[index] = name; - index++; - } - } else { - evaluatedArgsValues[index] = checkMissing(arg); - evaluatedArgNames[index] = signature.getName(fi); - index++; - } - } - evaluatedSignature = ArgumentsSignature.get(evaluatedArgNames); - } - EvaluatedArguments evaledArgs = EvaluatedArguments.create(evaluatedArgsValues, evaluatedSignature); - // ...to match them against the chosen function's formal arguments - EvaluatedArguments reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(func, evaledArgs, callSrc, false); - if (func.isBuiltin()) { - ArgumentMatcher.evaluatePromises(frame, promiseHelper, reorderedArgs.getEvaluatedArgs()); - } - return reorderedArgs; - } - - public static boolean isEqualType(RStringVector one, RStringVector two) { - if (one == null && two == null) { - return true; - } - if (one == null || two == null) { - return false; - } - - if (one.getLength() != two.getLength()) { - return false; - } - for (int i = 0; i < one.getLength(); i++) { - if (!one.getDataAt(i).equals(two.getDataAt(i))) { - return false; - } - } - return true; - } -} - -abstract class S3DispatchCachedNode extends S3DispatchNode { - protected final RStringVector type; - - public S3DispatchCachedNode(String genericName, RStringVector type, ArgumentsSignature suppliedSignature) { - super(genericName, suppliedSignature); - this.type = type; - } -} - -abstract class S3DispatchGenericNode extends S3DispatchNode { - - public S3DispatchGenericNode(String genericName, ArgumentsSignature suppliedSignature) { - super(genericName, suppliedSignature); - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnaryOpsGroupDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnaryOpsGroupDispatchNode.java deleted file mode 100644 index d95ca5c21e..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UnaryOpsGroupDispatchNode.java +++ /dev/null @@ -1,59 +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-2015, Purdue University - * Copyright (c) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.nodes.function; - -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; - -/* - * Handles unary +, - and ! operators. - */ -public class UnaryOpsGroupDispatchNode extends GroupDispatchNode { - - public UnaryOpsGroupDispatchNode(String genericName, boolean hasVararg, SourceSection callSrc, SourceSection argSrc) { - super(genericName, RGroupGenerics.GROUP_OPS, hasVararg, callSrc, argSrc); - } - - @Override - protected Object callBuiltin(VirtualFrame frame, Object[] evaluatedArgs, ArgumentsSignature signature) { - initBuiltin(frame); - Object[] args = ((HasSignature) builtinFunc.getRootNode()).getSignature().getLength() == 1 ? new Object[]{evaluatedArgs[0]} : new Object[]{evaluatedArgs[0], RMissing.instance}; - Object[] argObject = RArguments.create(builtinFunc, callSrc, null, RArguments.getDepth(frame) + 1, args); - return indirectCallNode.call(frame, builtinFunc.getTarget(), argObject); - } -} - -class GenericUnaryOpsGroupDispatchNode extends UnaryOpsGroupDispatchNode { - - public GenericUnaryOpsGroupDispatchNode(String genericName, boolean hasVararg, SourceSection callSrc, SourceSection argSrc) { - super(genericName, hasVararg, callSrc, argSrc); - } - - @Override - public Object execute(VirtualFrame frame, final RArgsValuesAndNames argAndNames) { - Object[] evaluatedArgs = argAndNames.getValues(); - ArgumentsSignature signature = argAndNames.getSignature(); - this.type = getArgClass(evaluatedArgs[0]); - if (this.type == null) { - return callBuiltin(frame, evaluatedArgs, signature); - } - findTargetFunction(frame); - if (targetFunction != null) { - dotMethod = RDataFactory.createStringVector(new String[]{targetFunctionName, ""}, true); - } - if (targetFunction == null) { - callBuiltin(frame, evaluatedArgs, signature); - } - return executeHelper(frame, evaluatedArgs, signature); - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java deleted file mode 100644 index a188769bea..0000000000 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/UseMethodDispatchNode.java +++ /dev/null @@ -1,355 +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) 2014, 2015, Oracle and/or its affiliates - * - * All rights reserved. - */ - -package com.oracle.truffle.r.nodes.function; - -import com.oracle.truffle.api.*; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.frame.*; -import com.oracle.truffle.api.nodes.*; -import com.oracle.truffle.api.source.*; -import com.oracle.truffle.r.nodes.*; -import com.oracle.truffle.r.nodes.access.variables.*; -import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation; -import com.oracle.truffle.r.nodes.function.DispatchedCallNode.NoGenericMethodException; -import com.oracle.truffle.r.runtime.*; -import com.oracle.truffle.r.runtime.data.*; - -/** - * {@code UseMethod} is typically called like this: - * - * <pre> - * f <- function(x, ...) UseMethod("f") - * </pre> - * - * Locating the correct call depends on the class of {@code x}, and the search starts in the - * enclosing (parent) environment of {@code f}, which, for packages, which is where most of these - * definitions occur, will be the package {@code namepace} enviromnent. - */ -public abstract class UseMethodDispatchNode { - - public static DispatchNode createCached(String genericName, RStringVector type, ArgumentsSignature suppliedSignature) { - return new UseMethodDispatchCachedNode(genericName, type, suppliedSignature); - } - - public static DispatchNode createGeneric(String genericName, ArgumentsSignature suppliedSignature) { - return new UseMethodDispatchGenericNode(genericName, suppliedSignature); - } -} - -final class UseMethodDispatchCachedNode extends S3DispatchCachedNode { - - @NodeInfo(cost = NodeCost.NONE) - private static final class CheckReadsNode extends Node { - @Children private final ReadVariableNode[] unsuccessfulReadsCallerFrame; - @Children private final ReadVariableNode[] unsuccessfulReadsDefFrame; - // if readsDefFrame != null, then this read will go to the def frame - @Child private ReadVariableNode successfulRead; - - private final ArgumentsSignature signature; - @CompilationFinal private final ArgumentsSignature[] varArgSignature; - - public final RFunction function; - public final RStringVector clazz; - public final String functionName; - @CompilationFinal public long[] preparePermutation; - public final MatchPermutation permutation; - - public CheckReadsNode(ReadVariableNode[] unsuccessfulReadsCallerFrame, ReadVariableNode[] unsuccessfulReadsDefFrame, ReadVariableNode successfulRead, RFunction function, RStringVector clazz, - String functionName, ArgumentsSignature signature, ArgumentsSignature[] varArgSignature, long[] preparePermutation, MatchPermutation permutation) { - this.unsuccessfulReadsCallerFrame = unsuccessfulReadsCallerFrame; - this.unsuccessfulReadsDefFrame = unsuccessfulReadsDefFrame; - this.successfulRead = successfulRead; - this.function = function; - this.clazz = clazz; - this.functionName = functionName; - this.signature = signature; - this.varArgSignature = varArgSignature; - this.preparePermutation = preparePermutation; - this.permutation = permutation; - } - - public boolean executeReads(Frame callerFrame, MaterializedFrame defFrame, ArgumentsSignature actualSignature, Object[] actualArguments) { - if (actualSignature != signature) { - return false; - } - if (!checkLastArgSignature(actualArguments)) { - return false; - } - if (!executeReads(unsuccessfulReadsCallerFrame, callerFrame)) { - return false; - } - Object actualFunction; - if (unsuccessfulReadsDefFrame != null) { - if (!executeReads(unsuccessfulReadsDefFrame, defFrame)) { - return false; - } - actualFunction = successfulRead.execute(null, defFrame); - } else { - actualFunction = successfulRead.execute(null, callerFrame); - } - return actualFunction == function; - } - - @ExplodeLoop - private static boolean executeReads(ReadVariableNode[] reads, Frame callerFrame) { - for (ReadVariableNode read : reads) { - if (read.execute(null, callerFrame) != null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - return false; - } - } - return true; - } - - @ExplodeLoop - private boolean checkLastArgSignature(Object[] arguments) { - for (int i = 0; i < arguments.length; i++) { - Object arg = arguments[i]; - if (arg instanceof RArgsValuesAndNames) { - if (varArgSignature == null || varArgSignature[i] != ((RArgsValuesAndNames) arg).getSignature()) { - return false; - } - } else { - if (varArgSignature != null && varArgSignature[i] != null) { - return false; - } - } - } - return true; - } - } - - @Child private CheckReadsNode cached; - @Child private DirectCallNode call; - - public UseMethodDispatchCachedNode(String genericName, RStringVector type, ArgumentsSignature suppliedSignature) { - super(genericName, type, suppliedSignature); - } - - @Override - public Object execute(VirtualFrame frame) { - Object[] arguments = extractArguments(frame, true); - ArgumentsSignature signature = RArguments.getSignature(frame); - MaterializedFrame genericDefFrame = RArguments.getEnclosingFrame(frame); - MaterializedFrame callerFrame = getCallerFrame(frame); - - if (cached == null || !cached.executeReads(callerFrame, genericDefFrame, signature, arguments)) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - specialize(frame, callerFrame, signature, arguments, true); - } - - Object[] preparedArguments = prepareSuppliedArgument(cached.preparePermutation, arguments); - - RRootNode rootNode = (RRootNode) cached.function.getTarget().getRootNode(); - FormalArguments formals = rootNode.getFormalArguments(); - ArgumentsSignature formalSignature = formals.getSignature(); - - Object[] reorderedArgs = ArgumentMatcher.matchArgumentsEvaluated(cached.permutation, preparedArguments, formals); - - CompilerAsserts.partialEvaluationConstant(reorderedArgs.length); - - if (cached.function.isBuiltin()) { - ArgumentMatcher.evaluatePromises(frame, promiseHelper, reorderedArgs); - } - - Object[] argObject = prepareArguments(callerFrame, genericDefFrame, reorderedArgs, formalSignature, cached.function, cached.clazz, cached.functionName); - - return call.call(frame, argObject); - } - - @ExplodeLoop - private static Object[] prepareSuppliedArgument(long[] preparePermutation, Object[] arguments) { - Object[] result = new Object[preparePermutation.length]; - for (int i = 0; i < result.length; i++) { - long source = preparePermutation[i]; - if (source >= 0) { - result[i] = arguments[(int) source]; - } else { - source = -source; - result[i] = ((RArgsValuesAndNames) arguments[(int) (source >> 32)]).getValues()[(int) source]; - } - } - return result; - } - - private void specialize(Frame callerFrame, MaterializedFrame genericDefFrame, ArgumentsSignature signature, Object[] arguments, boolean throwsRError) { - CompilerAsserts.neverPartOfCompilation(); - // look for a match in the caller frame hierarchy - TargetLookupResult result = findTargetFunctionLookup(callerFrame, type, genericName, true); - ReadVariableNode[] unsuccessfulReadsCaller = result.unsuccessfulReads; - ReadVariableNode[] unsuccessfulReadsDef = null; - if (result.successfulRead == null) { - if (genericDefFrame != null) { - // look for a match in the generic def frame hierarchy - result = findTargetFunctionLookup(genericDefFrame, type, genericName, true); - unsuccessfulReadsDef = result.unsuccessfulReads; - } - if (result.successfulRead == null) { - if (throwsRError) { - throw RError.error(getEncapsulatingSourceSection(), RError.Message.UNKNOWN_FUNCTION_USE_METHOD, genericName, type); - } else { - throw new NoGenericMethodException(); - } - } - } - - int argCount = arguments.length; - int argListSize = argCount; - - // extract vararg signatures from the arguments - ArgumentsSignature[] varArgSignatures = null; - for (int i = 0; i < arguments.length; i++) { - Object arg = arguments[i]; - if (arg instanceof RArgsValuesAndNames) { - if (varArgSignatures == null) { - varArgSignatures = new ArgumentsSignature[arguments.length]; - } - varArgSignatures[i] = ((RArgsValuesAndNames) arg).getSignature(); - argListSize += ((RArgsValuesAndNames) arg).length() - 1; - } - } - - long[] preparePermutation; - ArgumentsSignature resultSignature; - if (varArgSignatures != null) { - resultSignature = ArgumentsSignature.flattenNames(signature, varArgSignatures, argListSize); - preparePermutation = ArgumentsSignature.flattenIndexes(varArgSignatures, argListSize); - } else { - preparePermutation = new long[argCount]; - for (int i = 0; i < argCount; i++) { - preparePermutation[i] = i; - } - resultSignature = signature; - } - - assert resultSignature != null; - ArgumentsSignature formalSignature = ArgumentMatcher.getFunctionSignature(result.targetFunction); - MatchPermutation permutation = ArgumentMatcher.matchArguments(resultSignature, formalSignature, getEncapsulatingSourceSection(), false); - - CheckReadsNode newCheckedReads = new CheckReadsNode(unsuccessfulReadsCaller, unsuccessfulReadsDef, result.successfulRead, result.targetFunction, result.clazz, result.targetFunctionName, - signature, varArgSignatures, preparePermutation, permutation); - DirectCallNode newCall = Truffle.getRuntime().createDirectCallNode(result.targetFunction.getTarget()); - if (call == null) { - cached = insert(newCheckedReads); - call = insert(newCall); - } else { - RError.performanceWarning("re-specializing UseMethodDispatchCachedNode"); - cached.replace(newCheckedReads); - call.replace(newCall); - } - } - - @Override - public Object executeGeneric(VirtualFrame frame, RStringVector aType) { - throw RInternalError.shouldNotReachHere(); - } - - @Override - public Object executeInternal(VirtualFrame frame, Object[] arguments) throws NoGenericMethodException { - ArgumentsSignature signature = suppliedSignature; - if (cached == null || !cached.executeReads(frame, null, signature, arguments)) { - CompilerDirectives.transferToInterpreterAndInvalidate(); - specialize(frame, null, signature, arguments, false); - } - EvaluatedArguments reorderedArgs = reorderArguments(arguments, cached.function, suppliedSignature, getEncapsulatingSourceSection()); - if (cached.function.isBuiltin()) { - ArgumentMatcher.evaluatePromises(frame, promiseHelper, reorderedArgs.getEvaluatedArgs()); - } - Object[] argObject = prepareArguments(frame.materialize(), null, reorderedArgs.arguments, reorderedArgs.signature, cached.function, cached.clazz, cached.functionName); - return call.call(frame, argObject); - } - - @Override - public Object executeInternalGeneric(VirtualFrame frame, RStringVector aType, Object[] args) throws NoGenericMethodException { - throw RInternalError.shouldNotReachHere(); - } - -} - -final class UseMethodDispatchGenericNode extends S3DispatchGenericNode { - - @Child protected IndirectCallNode indirectCallNode = Truffle.getRuntime().createIndirectCallNode(); - - public UseMethodDispatchGenericNode(String genericName, ArgumentsSignature suppliedSignature) { - super(genericName, suppliedSignature); - } - - @Override - public Object execute(VirtualFrame frame) { - throw RInternalError.shouldNotReachHere(); - } - - @Override - public Object executeGeneric(VirtualFrame frame, RStringVector type) { - Object[] arguments = extractArguments(frame, false); - ArgumentsSignature signature = RArguments.getSignature(frame); - MaterializedFrame genericDefFrame = RArguments.getEnclosingFrame(frame); - MaterializedFrame callerFrame = getCallerFrame(frame); - - TargetLookupResult lookupResult = findTargetFunction(callerFrame, genericDefFrame, type, true); - Object[] callArguments = executeHelper(frame, callerFrame, genericDefFrame, lookupResult, arguments, signature, getSourceSection()); - return indirectCallNode.call(frame, lookupResult.targetFunction.getTarget(), callArguments); - } - - @Override - public Object executeInternal(VirtualFrame frame, Object[] args) { - throw RInternalError.shouldNotReachHere(); - } - - @Override - public Object executeInternalGeneric(VirtualFrame frame, RStringVector type, Object[] arguments) { - MaterializedFrame genericDefFrame = RArguments.getEnclosingFrame(frame); - MaterializedFrame callerFrame = getCallerFrame(frame); - - TargetLookupResult lookupResult = findTargetFunction(callerFrame, genericDefFrame, type, true); - Object[] callArguments = executeHelper(frame, callerFrame, genericDefFrame, lookupResult, arguments, suppliedSignature, getEncapsulatingSourceSection()); - return indirectCallNode.call(frame, lookupResult.targetFunction.getTarget(), callArguments); - } - - private Object[] executeHelper(VirtualFrame frame, MaterializedFrame callerFrame, MaterializedFrame genericDefFrame, TargetLookupResult lookupResult, Object[] args, - ArgumentsSignature paramSignature, SourceSection errorSourceSection) { - RFunction function = lookupResult.targetFunction; - EvaluatedArguments reorderedArgs = reorderArguments(args, function, paramSignature, errorSourceSection); - if (function.isBuiltin()) { - ArgumentMatcher.evaluatePromises(frame, promiseHelper, reorderedArgs.getEvaluatedArgs()); - } - return prepareArguments(callerFrame, genericDefFrame, lookupResult, function, reorderedArgs); - } - - @Override - @TruffleBoundary - protected EvaluatedArguments reorderArguments(Object[] args, RFunction function, ArgumentsSignature paramSignature, SourceSection errorSourceSection) { - return super.reorderArguments(args, function, paramSignature, errorSourceSection); - } - - @TruffleBoundary - private Object[] prepareArguments(MaterializedFrame callerFrame, MaterializedFrame genericDefFrame, TargetLookupResult lookupResult, RFunction function, EvaluatedArguments reorderedArgs) { - return super.prepareArguments(callerFrame, genericDefFrame, reorderedArgs.arguments, reorderedArgs.signature, function, lookupResult.clazz, lookupResult.targetFunctionName); - } - - @TruffleBoundary - private TargetLookupResult findTargetFunction(MaterializedFrame callerFrame, MaterializedFrame genericDefFrame, RStringVector type, boolean throwsRError) { - TargetLookupResult lookupResult = findTargetFunctionLookup(callerFrame, type, genericName, false); - if (lookupResult == null) { - lookupResult = findTargetFunctionLookup(genericDefFrame, type, genericName, false); - if (lookupResult == null) { - if (throwsRError) { - throw RError.error(getEncapsulatingSourceSection(), RError.Message.UNKNOWN_FUNCTION_USE_METHOD, genericName, RRuntime.toString(type)); - } else { - throw new NoGenericMethodException(); - } - } - } - return lookupResult; - } -} diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTDeparse.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTDeparse.java index 4caaaec408..9f20193bcb 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTDeparse.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTDeparse.java @@ -5,7 +5,7 @@ * * Copyright (c) 1995-2012, The R Core Team * Copyright (c) 2003, The R Foundation - * Copyright (c) 2013, 2014, Oracle and/or its affiliates + * Copyright (c) 2013, 2015, Oracle and/or its affiliates * * All rights reserved. */ @@ -52,7 +52,7 @@ public class RASTDeparse { } private static Func isInfixOperatorNode(Node node) { - if (node instanceof RCallNode || node instanceof GroupDispatchCallNode) { + if (node instanceof RCallNode || node instanceof GroupDispatchNode) { Object fname = RASTUtils.findFunctionName(node, false); return isInfixOperator(fname); } else { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java index 05b653c514..e99cad9a26 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/runtime/RASTHelperImpl.java @@ -87,7 +87,7 @@ public class RASTHelperImpl implements RASTHelper { @TruffleBoundary private static int computeLength(Node node) { int result = 1; - if (node instanceof RCallNode || node instanceof DispatchedCallNode || node instanceof GroupDispatchCallNode) { + if (node instanceof RCallNode || node instanceof GroupDispatchNode) { // 1 + number of args CallArgumentsNode args = RASTUtils.findCallArgumentsNode(node); result += args.getArguments().length; @@ -137,7 +137,7 @@ public class RASTHelperImpl implements RASTHelper { // index has already been range checked based on computeLength Node node = RASTUtils.unwrap(rl.getRep()); int index = indexArg; - if (node instanceof RCallNode || node instanceof DispatchedCallNode || node instanceof GroupDispatchCallNode) { + if (node instanceof RCallNode || node instanceof GroupDispatchNode) { if (index == 0) { return RASTUtils.findFunctionName(node, true); } else { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java index 4e5168730d..4a1749be22 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RArguments.java @@ -94,6 +94,7 @@ public final class RArguments { public S3Args(String generic, Object clazz, Object method, MaterializedFrame callEnv, MaterializedFrame defEnv, String group) { assert generic != null && callEnv != null : generic + " " + callEnv; + assert generic.intern() == generic; this.generic = generic; this.clazz = clazz; this.method = method; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java index 30c1a5fd6a..e948eab02e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RError.java @@ -449,6 +449,7 @@ public final class RError extends RuntimeException { INVALID_TYPE_LENGTH("invalid type/length (%s/%d) in vector allocation"), SUBASSIGN_TYPE_FIX("incompatible types (from %s to %s) in subassignment type fix"), SUBSCRIPT_TYPES("incompatible types (from %s to %s) in [[ assignment"), + INCOMPATIBLE_METHODS("incompatible methods (\"%s\", \"%s\") for \"%s\""), RECURSIVE_INDEXING_FAILED("recursive indexing failed at level %d"), ARGUMENTS_PASSED("%d arguments passed to '%s' which requires %d"), ARGUMENTS_PASSED_0_1("0 arguments passed to '%s' which requires 1"), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RGroupGenerics.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RGroupGenerics.java index cb31c420d5..95e86e618b 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RGroupGenerics.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RGroupGenerics.java @@ -10,121 +10,88 @@ */ package com.oracle.truffle.r.runtime; -import java.util.*; - -public class RGroupGenerics { - - public static final String GROUP_MATH = "Math"; - - public static final String GROUP_OPS = "Ops"; - - public static final String GROUP_SUMMARY = "Summary"; - - public static final String GROUP_COMPLEX = "Complex"; - - private static Map<String, String> methodToGroup; - - static { - initializeMethodToGroup(); - } - - /* - * Returns the group to which a given S-3 group generic method belongs to. - */ - public static String getGroup(final String methodName) { - return methodToGroup.get(methodName); +public enum RGroupGenerics { + Math, + Ops, + Summary, + Complex; + + public String getName() { + return name(); } - /* - * Returns true if the method is group generic. - */ - public static boolean isGroupGeneric(final String methodName) { - return methodToGroup.containsKey(methodName); + public static RGroupGenerics getGroup(String methodName) { + switch (methodName) { + case "abs": + case "sign": + case "sqrt": + case "floor": + case "ceiling": + case "trunc": + case "round": + case "signif": + case "exp": + case "log": + case "expm1": + case "log1p": + case "cos": + case "sin": + case "tan": + case "acos": + case "asin": + case "atan": + case "cosh": + case "sinh": + case "tanh": + case "acosh": + case "asinh": + case "atanh": + case "lgamma": + case "gamma": + case "digamma": + case "trigamma": + case "cumsum": + case "cumprod": + case "cummax": + case "cummin": + return Math; + case "+": + case "-": + case "*": + case "/": + case "^": + case "%%": + case "%/%": + case "&": + case "|": + case "!": + case "==": + case "!=": + case "<": + case "<=": + case ">=": + case ">": + return Ops; + case "max": + case "min": + case "prod": + case "sum": + case "all": + case "any": + case "range": + return Summary; + case "Arg": + case "Conj": + case "Im": + case "Mod": + case "Re": + return Complex; + default: + return null; + } } - /* - * S3 methods can be written for four groups:"Math", "Ops", "Summary" and "Complex". The - * following method maps each method to its associated group. - */ - private static void initializeMethodToGroup() { - assert (methodToGroup == null); - methodToGroup = new HashMap<>(); - addGroupMath(); - addGroupOps(); - addGroupSummary(); - addGroupComplex(); + public static boolean isGroupGeneric(String methodName) { + return getGroup(methodName) != null; } - - private static void addGroupMath() { - methodToGroup.put("abs", GROUP_MATH); - methodToGroup.put("sign", GROUP_MATH); - methodToGroup.put("sqrt", GROUP_MATH); - methodToGroup.put("floor", GROUP_MATH); - methodToGroup.put("ceiling", GROUP_MATH); - methodToGroup.put("trunc", GROUP_MATH); - methodToGroup.put("round", GROUP_MATH); - methodToGroup.put("signif", GROUP_MATH); - methodToGroup.put("exp", GROUP_MATH); - methodToGroup.put("log", GROUP_MATH); - methodToGroup.put("expm1", GROUP_MATH); - methodToGroup.put("log1p", GROUP_MATH); - methodToGroup.put("cos", GROUP_MATH); - methodToGroup.put("sin", GROUP_MATH); - methodToGroup.put("tan", GROUP_MATH); - methodToGroup.put("acos", GROUP_MATH); - methodToGroup.put("asin", GROUP_MATH); - methodToGroup.put("atan", GROUP_MATH); - methodToGroup.put("cosh", GROUP_MATH); - methodToGroup.put("sinh", GROUP_MATH); - methodToGroup.put("tanh", GROUP_MATH); - methodToGroup.put("acosh", GROUP_MATH); - methodToGroup.put("asinh", GROUP_MATH); - methodToGroup.put("atanh", GROUP_MATH); - methodToGroup.put("lgamma", GROUP_MATH); - methodToGroup.put("gamma", GROUP_MATH); - methodToGroup.put("digamma", GROUP_MATH); - methodToGroup.put("trigamma", GROUP_MATH); - methodToGroup.put("cumsum", GROUP_MATH); - methodToGroup.put("cumprod", GROUP_MATH); - methodToGroup.put("cummax", GROUP_MATH); - methodToGroup.put("cummin", GROUP_MATH); - } - - private static void addGroupOps() { - methodToGroup.put("+", GROUP_OPS); - methodToGroup.put("-", GROUP_OPS); - methodToGroup.put("*", GROUP_OPS); - methodToGroup.put("/", GROUP_OPS); - methodToGroup.put("^", GROUP_OPS); - methodToGroup.put("%%", GROUP_OPS); - methodToGroup.put("%/%", GROUP_OPS); - methodToGroup.put("&", GROUP_OPS); - methodToGroup.put("|", GROUP_OPS); - methodToGroup.put("!", GROUP_OPS); - methodToGroup.put("==", GROUP_OPS); - methodToGroup.put("!=", GROUP_OPS); - methodToGroup.put("<", GROUP_OPS); - methodToGroup.put("<=", GROUP_OPS); - methodToGroup.put(">=", GROUP_OPS); - methodToGroup.put(">", GROUP_OPS); - } - - private static void addGroupSummary() { - methodToGroup.put("max", GROUP_SUMMARY); - methodToGroup.put("min", GROUP_SUMMARY); - methodToGroup.put("prod", GROUP_SUMMARY); - methodToGroup.put("sum", GROUP_SUMMARY); - methodToGroup.put("all", GROUP_SUMMARY); - methodToGroup.put("any", GROUP_SUMMARY); - methodToGroup.put("range", GROUP_SUMMARY); - } - - private static void addGroupComplex() { - methodToGroup.put("Arg", GROUP_COMPLEX); - methodToGroup.put("Conj", GROUP_COMPLEX); - methodToGroup.put("Im", GROUP_COMPLEX); - methodToGroup.put("Mod", GROUP_COMPLEX); - methodToGroup.put("Re", GROUP_COMPLEX); - } - } -- GitLab