From af0c3cea7f1dac413fe358a8ffd5090b8ca41fa2 Mon Sep 17 00:00:00 2001 From: stepan <stepan.sindelar@oracle.com> Date: Wed, 2 Nov 2016 14:50:12 +0100 Subject: [PATCH] Varargs related methods moved from ArgumentsSignature to new class VarArgsHelper --- .../builtin/base/S3DispatchFunctions.java | 4 + .../r/nodes/function/CallMatcherNode.java | 16 +- .../r/nodes/function/RCallerHelper.java | 7 +- .../signature/CombineSignaturesNode.java | 11 +- .../function/signature/VarArgsHelper.java | 161 ++++++++++++++++++ .../truffle/r/runtime/ArgumentsSignature.java | 133 --------------- 6 files changed, 182 insertions(+), 150 deletions(-) create mode 100644 com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/VarArgsHelper.java diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java index 94669aeca1..21f5256c1b 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/S3DispatchFunctions.java @@ -53,6 +53,7 @@ import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RPromise; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; +import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; public abstract class S3DispatchFunctions extends RBuiltinNode { @@ -219,6 +220,9 @@ public abstract class S3DispatchFunctions extends RBuiltinNode { } protected static boolean isNotString(Object obj) { + // Note: if RAbstractStringVector becomes expected, then it must have length == 1, GnuR + // ignores character vectors longer than 1 as the "generic" argument of NextMethod + assert !(obj instanceof RAbstractStringVector) || ((RAbstractStringVector) obj).getLength() != 1 : "unexpected RAbstractStringVector with length != 1"; return !(obj instanceof String); } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java index 6e4b72a729..06d899fec8 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/CallMatcherNode.java @@ -27,10 +27,10 @@ import com.oracle.truffle.r.nodes.function.ArgumentMatcher.MatchPermutation; import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNode; import com.oracle.truffle.r.nodes.function.call.CallRFunctionCachedNodeGen; import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode; +import com.oracle.truffle.r.nodes.function.signature.VarArgsHelper; import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode; import com.oracle.truffle.r.nodes.unary.CastNode; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.ArgumentsSignature.VarArgsInfo; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RArguments.DispatchArgs; import com.oracle.truffle.r.runtime.RCaller; @@ -85,15 +85,15 @@ public abstract class CallMatcherNode extends RBaseNode { int argCount = suppliedArguments.length; // extract vararg signatures from the arguments - VarArgsInfo varArgsInfo = suppliedSignature.getVarArgsInfo(suppliedArguments); + VarArgsHelper varArgsInfo = VarArgsHelper.create(suppliedSignature, suppliedArguments); int argListSize = varArgsInfo.getArgListSize(); // see flattenIndexes for the interpretation of the values long[] preparePermutation; ArgumentsSignature resultSignature; if (varArgsInfo.hasVarArgs()) { - resultSignature = suppliedSignature.flattenNames(varArgsInfo); - preparePermutation = suppliedSignature.flattenIndexes(varArgsInfo); + resultSignature = varArgsInfo.flattenNames(suppliedSignature); + preparePermutation = varArgsInfo.flattenIndexes(suppliedSignature); } else { preparePermutation = new long[argListSize]; String[] newSuppliedSignature = new String[argListSize]; @@ -193,7 +193,7 @@ public abstract class CallMatcherNode extends RBaseNode { private final ArgumentsSignature[] cachedVarArgSignatures; private final RFunction cachedFunction; /** - * {@link ArgumentsSignature#flattenNames(VarArgsInfo)} for the interpretation of the + * {@link VarArgsHelper#flattenNames(ArgumentsSignature)} for the interpretation of the * values. */ @CompilationFinal private final long[] preparePermutation; @@ -300,9 +300,9 @@ public abstract class CallMatcherNode extends RBaseNode { Object[] values = new Object[preparePermutation.length]; for (int i = 0; i < values.length; i++) { long source = preparePermutation[i]; - if (ArgumentsSignature.isVarArgsIndex(source)) { - int varArgsIdx = ArgumentsSignature.extractVarArgsIndex(source); - int argsIdx = ArgumentsSignature.extractVarArgsArgumentIndex(source); + if (VarArgsHelper.isVarArgsIndex(source)) { + int varArgsIdx = VarArgsHelper.extractVarArgsIndex(source); + int argsIdx = VarArgsHelper.extractVarArgsArgumentIndex(source); RArgsValuesAndNames varargs = (RArgsValuesAndNames) arguments[varArgsIdx]; values[i] = varargs.getArguments()[argsIdx]; } else { diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java index af7f0639df..d16b817a36 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallerHelper.java @@ -27,6 +27,7 @@ import java.util.function.Supplier; import com.oracle.truffle.r.nodes.RASTUtils; import com.oracle.truffle.r.nodes.access.ConstantNode; import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode; +import com.oracle.truffle.r.nodes.function.signature.VarArgsHelper; import com.oracle.truffle.r.runtime.ArgumentsSignature; import com.oracle.truffle.r.runtime.RCaller; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; @@ -133,12 +134,12 @@ public final class RCallerHelper { String[] names = new String[preparePermutation.length]; for (int i = 0; i < values.length; i++) { long source = preparePermutation[i]; - if (!ArgumentsSignature.isVarArgsIndex(source)) { + if (!VarArgsHelper.isVarArgsIndex(source)) { values[i] = suppliedArguments[(int) source]; names[i] = suppliedSignature.getName((int) source); } else { - int varArgsIdx = ArgumentsSignature.extractVarArgsIndex(source); - int argsIdx = ArgumentsSignature.extractVarArgsArgumentIndex(source); + int varArgsIdx = VarArgsHelper.extractVarArgsIndex(source); + int argsIdx = VarArgsHelper.extractVarArgsArgumentIndex(source); RArgsValuesAndNames varargs = (RArgsValuesAndNames) suppliedArguments[varArgsIdx]; values[i] = varargs.getArguments()[argsIdx]; names[i] = varargs.getSignature().getName(argsIdx); diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java index 2c604132b4..b360a6e5aa 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/CombineSignaturesNode.java @@ -31,7 +31,6 @@ import com.oracle.truffle.api.dsl.TypeSystemReference; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.EmptyTypeSystemFlatLayout; import com.oracle.truffle.r.runtime.ArgumentsSignature; -import com.oracle.truffle.r.runtime.ArgumentsSignature.VarArgsInfo; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.nodes.RBaseNode; @@ -76,7 +75,7 @@ public abstract class CombineSignaturesNode extends RBaseNode { @Cached("createBinaryProfile()") ConditionProfile noVarArgsProfile) { Object[] flatLeftValues = leftValues; if (noVarArgsProfile.profile(resultCached.varArgsInfo.hasVarArgs())) { - flatLeftValues = left.flattenValues(leftValues, resultCached.varArgsInfo); + flatLeftValues = resultCached.varArgsInfo.flattenValues(left, leftValues); } return new RArgsValuesAndNames(resultCached.getValues(flatLeftValues, rightValues, shufflingProfile), resultCached.signature); } @@ -84,10 +83,10 @@ public abstract class CombineSignaturesNode extends RBaseNode { @TruffleBoundary protected CombineResult combine(ArgumentsSignature leftOriginal, Object[] leftValues, ArgumentsSignature right) { // flatten any varargs, note there should not be any in right - VarArgsInfo varArgsInfo = leftOriginal.getVarArgsInfo(leftValues); + VarArgsHelper varArgsInfo = VarArgsHelper.create(leftOriginal, leftValues); ArgumentsSignature left = leftOriginal; if (varArgsInfo.hasVarArgs()) { - left = leftOriginal.flattenNames(varArgsInfo); + left = varArgsInfo.flattenNames(leftOriginal); } // calculate the size of the resulting signature - some values in left are overridden by the @@ -157,9 +156,9 @@ public abstract class CombineSignaturesNode extends RBaseNode { */ private final int[] valuesIndexes; - private final VarArgsInfo varArgsInfo; + private final VarArgsHelper varArgsInfo; - CombineResult(ArgumentsSignature signature, int[] valuesIndexes, VarArgsInfo varArgsInfo) { + CombineResult(ArgumentsSignature signature, int[] valuesIndexes, VarArgsHelper varArgsInfo) { this.varArgsInfo = varArgsInfo; assert valuesIndexes == null || signature.getLength() == valuesIndexes.length; this.signature = signature; diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/VarArgsHelper.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/VarArgsHelper.java new file mode 100644 index 0000000000..b0b110efec --- /dev/null +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/signature/VarArgsHelper.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.truffle.r.nodes.function.signature; + +import com.oracle.truffle.r.runtime.ArgumentsSignature; +import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; + +/** + * Represents the information about varargs contained in {@link ArgumentsSignature} and its argument + * values and provides helper functions related to flattening the varargs. + */ +public final class VarArgsHelper { + + /** + * Array of the same size as the original signature with {@code null} in places where there are + * regular arguments and with {@link ArgumentsSignature} instances under the same indexes of + * their corresponding {@link RArgsValuesAndNames}. + */ + private final ArgumentsSignature[] varArgs; + + /** + * The total number of arguments including those in varargs, and excluding unmatched ones. + */ + private final int argListSize; + + private VarArgsHelper(ArgumentsSignature[] varArgs, int argListSize) { + this.varArgs = varArgs; + this.argListSize = argListSize; + } + + public static VarArgsHelper create(ArgumentsSignature signature, Object[] suppliedArguments) { + assert signature.getLength() == suppliedArguments.length; + ArgumentsSignature[] varArgs = null; + int argListSize = signature.getLength(); + for (int i = 0; i < suppliedArguments.length; i++) { + Object arg = suppliedArguments[i]; + if (arg instanceof RArgsValuesAndNames) { + if (varArgs == null) { + varArgs = new ArgumentsSignature[suppliedArguments.length]; + } + varArgs[i] = ((RArgsValuesAndNames) arg).getSignature(); + argListSize += ((RArgsValuesAndNames) arg).getLength() - 1; + } else if (signature.isUnmatched(i)) { + argListSize--; + } + } + return new VarArgsHelper(varArgs, argListSize); + } + + public boolean hasVarArgs() { + return varArgs != null; + } + + public ArgumentsSignature[] getVarArgsSignatures() { + return varArgs; + } + + public int getArgListSize() { + return argListSize; + } + + /** + * Returns an array where each index is either index into the variables array (positive number) + * or it is a packed representation of two indices: one into the variables array pointing to + * varargs instance and the other is index into this varargs' arguments array. Use static + * methods {@link #isVarArgsIndex(long)}, {@link #extractVarArgsArgumentIndex(long)} and + * {@link #extractVarArgsArgumentIndex(long)} to access the data packed in the {@code long} + * value. This method also removes arguments that are marked as 'unmatched' in the signature. + * + * Note: where {@link #hasVarArgs()} returns {@code false}, then the flattening may not be + * necessary. This optimization is left to the caller. + */ + public long[] flattenIndexes(ArgumentsSignature signature) { + long[] preparePermutation = new long[argListSize]; + int index = 0; + for (int i = 0; i < varArgs.length; i++) { + ArgumentsSignature varArgSignature = varArgs[i]; + if (varArgSignature != null) { + for (int j = 0; j < varArgSignature.getLength(); j++) { + preparePermutation[index++] = -((((long) i) << 32) + j) - 1; + } + } else if (!signature.isUnmatched(i)) { + preparePermutation[index++] = i; + } + } + return preparePermutation; + } + + /** @see #flattenIndexes(ArgumentsSignature) */ + public Object[] flattenValues(ArgumentsSignature signature, Object[] values) { + Object[] result = new Object[argListSize]; + int resultIdx = 0; + for (int valuesIdx = 0; valuesIdx < values.length; valuesIdx++) { + if (varArgs[valuesIdx] != null) { + assert values[valuesIdx] instanceof RArgsValuesAndNames; + assert ((RArgsValuesAndNames) values[valuesIdx]).getSignature() == varArgs[valuesIdx]; + RArgsValuesAndNames varArgs = (RArgsValuesAndNames) values[valuesIdx]; + for (int i = 0; i < varArgs.getLength(); i++) { + result[resultIdx++] = varArgs.getArgument(i); + } + } else if (!signature.isUnmatched(valuesIdx)) { + result[resultIdx++] = values[valuesIdx]; + } + } + return result; + } + + /** @see #flattenIndexes(ArgumentsSignature) */ + public ArgumentsSignature flattenNames(ArgumentsSignature signature) { + String[] argNames = new String[argListSize]; + int index = 0; + for (int i = 0; i < varArgs.length; i++) { + ArgumentsSignature varArgSignature = varArgs[i]; + if (varArgSignature != null) { + for (int j = 0; j < varArgSignature.getLength(); j++) { + argNames[index++] = varArgSignature.getName(j); + } + } else if (!signature.isUnmatched(i)) { + argNames[index++] = signature.getName(i); + } + } + return ArgumentsSignature.get(argNames); + } + + /* + * Utility functions for interpreting the result of flattenIndexes. + */ + + public static boolean isVarArgsIndex(long idx) { + return idx < 0; + } + + public static int extractVarArgsIndex(long idx) { + return (int) ((-idx - 1) >> 32); + } + + public static int extractVarArgsArgumentIndex(long idx) { + return (int) (-idx - 1); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java index 1edbe70707..20acad69f0 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ArgumentsSignature.java @@ -30,7 +30,6 @@ import com.oracle.truffle.api.CompilerAsserts; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; public final class ArgumentsSignature implements Iterable<String> { @@ -193,136 +192,4 @@ public final class ArgumentsSignature implements Iterable<String> { public String toString() { return "Signature " + Arrays.toString(names); } - - /* - * Utility functions - */ - - public static boolean isVarArgsIndex(long idx) { - return idx < 0; - } - - public static int extractVarArgsIndex(long idx) { - return (int) ((-idx - 1) >> 32); - } - - public static int extractVarArgsArgumentIndex(long idx) { - return (int) (-idx - 1); - } - - /** - * Creates instance of {@link VarArgsInfo} for this signature and supplied arguments values. - * This object is required by other utility methods handling varargs. - */ - public VarArgsInfo getVarArgsInfo(Object[] suppliedArguments) { - ArgumentsSignature[] varArgs = null; - int argListSize = getLength(); - for (int i = 0; i < suppliedArguments.length; i++) { - Object arg = suppliedArguments[i]; - if (arg instanceof RArgsValuesAndNames) { - if (varArgs == null) { - varArgs = new ArgumentsSignature[suppliedArguments.length]; - } - varArgs[i] = ((RArgsValuesAndNames) arg).getSignature(); - argListSize += ((RArgsValuesAndNames) arg).getLength() - 1; - } else if (isUnmatched(i)) { - argListSize--; - } - } - return new VarArgsInfo(varArgs, argListSize); - } - - /** - * Returns an array where each index is either index into the variables array (positive number) - * or it is a packed representation of two indices: one into the variables array pointing to - * varargs instance and the other is index into this varargs' arguments array. Use static - * methods {@link #isVarArgsIndex(long)}, {@link #extractVarArgsArgumentIndex(long)} and - * {@link #extractVarArgsArgumentIndex(long)} to access the data packed in the {@code long} - * value. This method also removes arguments that are marked as 'unmatched' in the signature. - * - * Note: where {@link VarArgsInfo#hasVarArgs()} returns {@code false}, then the flattening may - * not be necessary. This optimization is left to the caller. - */ - public long[] flattenIndexes(VarArgsInfo varArgsInfo) { - long[] preparePermutation = new long[varArgsInfo.argListSize]; - int index = 0; - for (int i = 0; i < varArgsInfo.varArgs.length; i++) { - ArgumentsSignature varArgSignature = varArgsInfo.varArgs[i]; - if (varArgSignature != null) { - for (int j = 0; j < varArgSignature.getLength(); j++) { - preparePermutation[index++] = -((((long) i) << 32) + j) - 1; - } - } else if (!isUnmatched(i)) { - preparePermutation[index++] = i; - } - } - return preparePermutation; - } - - /** @see #flattenIndexes(VarArgsInfo varArgsInfo) */ - public Object[] flattenValues(Object[] values, VarArgsInfo varArgsInfo) { - Object[] result = new Object[varArgsInfo.argListSize]; - int resultIdx = 0; - for (int valuesIdx = 0; valuesIdx < values.length; valuesIdx++) { - if (varArgsInfo.varArgs[valuesIdx] != null) { - assert values[valuesIdx] instanceof RArgsValuesAndNames; - assert ((RArgsValuesAndNames) values[valuesIdx]).getSignature() == varArgsInfo.varArgs[valuesIdx]; - RArgsValuesAndNames varArgs = (RArgsValuesAndNames) values[valuesIdx]; - for (int i = 0; i < varArgs.getLength(); i++) { - result[resultIdx++] = varArgs.getArgument(i); - } - } else if (!isUnmatched(valuesIdx)) { - result[resultIdx++] = values[valuesIdx]; - } - } - return result; - } - - /** @see #flattenIndexes(VarArgsInfo varArgsInfo) */ - public ArgumentsSignature flattenNames(VarArgsInfo varArgsInfo) { - String[] argNames = new String[varArgsInfo.argListSize]; - int index = 0; - for (int i = 0; i < varArgsInfo.varArgs.length; i++) { - ArgumentsSignature varArgSignature = varArgsInfo.varArgs[i]; - if (varArgSignature != null) { - for (int j = 0; j < varArgSignature.getLength(); j++) { - argNames[index++] = varArgSignature.getName(j); - } - } else if (!isUnmatched(i)) { - argNames[index++] = getName(i); - } - } - return ArgumentsSignature.get(argNames); - } - - public static final class VarArgsInfo { - /** - * Array of the same size as the original signature with {@code null} in places where there - * are regular arguments and with {@link ArgumentsSignature} instances under the same - * indexes of their corresponding {@link RArgsValuesAndNames}. - */ - private final ArgumentsSignature[] varArgs; - - /** - * The total number of arguments including those in varargs, and excluding unmatched ones. - */ - private final int argListSize; - - private VarArgsInfo(ArgumentsSignature[] varArgs, int argListSize) { - this.varArgs = varArgs; - this.argListSize = argListSize; - } - - public boolean hasVarArgs() { - return varArgs != null; - } - - public ArgumentsSignature[] getVarArgsSignatures() { - return varArgs; - } - - public int getArgListSize() { - return argListSize; - } - } } -- GitLab