Skip to content
Snippets Groups Projects
Commit 2374f615 authored by Lukas Stadler's avatar Lukas Stadler
Browse files

[GR-2737] [GR-2738] [GR-4790] Various performance and bug fixes.

parents 26a95a7d 5839d0ea
No related branches found
No related tags found
No related merge requests found
Showing
with 1205 additions and 987 deletions
......@@ -185,7 +185,7 @@ builds = [
${gateTestNoSpecialsLinux} {capabilities : [linux, amd64, fast], targets : [gate], name: "gate-test-linux-amd64-nospecials"}
${gateTestDarwin} {capabilities : [darwin, amd64], targets : [gate], name: "gate-test-darwin-amd64"}
${gateStyle} {capabilities : [linux, amd64], targets : [gate], name: "gate-style-linux-amd64"}
${rbcheck} {capabilities : [linux, amd64], targets : [gate], name: "gate-rbcheck-linux-amd64"}
# ${rbcheck} {capabilities : [linux, amd64], targets : [gate], name: "gate-rbcheck-linux-amd64"}
${internalPkgtest} {capabilities : [linux, amd64], targets : [gate], name: "gate-internal-pkgtest-linux-amd64"}
${gateTestManagedLinux} {capabilities : [linux, amd64, fast], targets : [gate], name: "gate-test-managed-linux-amd64"}
${gateTestJava9Linux} {capabilities : [linux, amd64, fast], targets : [gate], name: "gate-test-java9-linux-amd64"}
......
......@@ -43,6 +43,8 @@ import com.oracle.truffle.r.nodes.builtin.base.fastpaths.IntersectFastPathNodeGe
import com.oracle.truffle.r.nodes.builtin.base.fastpaths.IsElementFastPathNodeGen;
import com.oracle.truffle.r.nodes.builtin.base.fastpaths.MatrixFastPathNodeGen;
import com.oracle.truffle.r.nodes.builtin.base.fastpaths.SetDiffFastPathNodeGen;
import com.oracle.truffle.r.nodes.builtin.base.fastpaths.SubscriptDataFrameFastPathNodeGen;
import com.oracle.truffle.r.nodes.builtin.base.fastpaths.SubsetDataFrameFastPathNodeGen;
import com.oracle.truffle.r.nodes.builtin.base.fastpaths.VectorFastPathsFactory.DoubleFastPathNodeGen;
import com.oracle.truffle.r.nodes.builtin.base.fastpaths.VectorFastPathsFactory.IntegerFastPathNodeGen;
import com.oracle.truffle.r.nodes.builtin.base.foreign.CallAndExternalFunctions;
......@@ -790,6 +792,8 @@ public class BasePackage extends RBuiltinPackage {
@Override
public void loadOverrides(MaterializedFrame baseFrame) {
super.loadOverrides(baseFrame);
addFastPath(baseFrame, "[[.data.frame", SubscriptDataFrameFastPathNodeGen::create, RVisibility.ON);
addFastPath(baseFrame, "[.data.frame", SubsetDataFrameFastPathNodeGen::create, RVisibility.ON);
addFastPath(baseFrame, "matrix", MatrixFastPathNodeGen::create, Matrix.class);
addFastPath(baseFrame, "setdiff", SetDiffFastPathNodeGen::create, RVisibility.ON);
addFastPath(baseFrame, "get", GetFastPathNodeGen::create, RVisibility.ON);
......
......@@ -28,10 +28,13 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX;
import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL;
import com.oracle.truffle.api.CompilerAsserts;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.ExplodeLoop;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.profiles.BranchProfile;
import com.oracle.truffle.r.nodes.access.WriteVariableNode;
import com.oracle.truffle.r.nodes.access.WriteVariableNode.Mode;
import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
......@@ -117,7 +120,10 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
}
}
@Child private GetNamesAttributeNode getNames = GetNamesAttributeNode.create();
@Child private GetNamesAttributeNode getNamesDots = GetNamesAttributeNode.create();
@Child private GetNamesAttributeNode getNamesMoreArgs = GetNamesAttributeNode.create();
private final BranchProfile nonPerfectMatch = BranchProfile.create();
public abstract Object[] execute(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector additionalArguments);
......@@ -125,18 +131,46 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
return extractNode.apply(frame, dots.getDataAt(listIndex), new Object[]{i % lengths[listIndex] + 1}, RLogical.TRUE, RLogical.TRUE);
}
@SuppressWarnings("unused")
@Specialization(limit = "5", guards = {"dots.getLength() == cachedDots.getLength()",
"moreArgs.getLength() == cachedMoreArgs.getLength()", "sameNames(dots, cachedDots)",
"sameNames(moreArgs, cachedMoreArgs)"})
@Specialization(limit = "5", guards = {"dots.getLength() == dotsLength", "moreArgs.getLength() == moreArgsLength",
"sameNames(dots, cachedDotsNames)", "sameNames(moreArgs, cachedMoreArgsNames)"})
protected Object[] cachedMApply(VirtualFrame frame, RAbstractListVector dots, RFunction function, RAbstractListVector moreArgs,
@Cached("dots") RAbstractListVector cachedDots,
@Cached("moreArgs") RAbstractListVector cachedMoreArgs,
@Cached("createElementNodeArray(cachedDots, cachedMoreArgs)") ElementNode[] cachedElementNodeArray,
@Cached("dots.getLength()") int dotsLength,
@Cached("moreArgs.getLength()") int moreArgsLength,
@SuppressWarnings("unused") @Cached(value = "extractNames(dots)", dimensions = 1) String[] cachedDotsNames,
@SuppressWarnings("unused") @Cached(value = "extractNames(moreArgs)", dimensions = 1) String[] cachedMoreArgsNames,
@Cached("createElementNodeArray(dotsLength, moreArgsLength, cachedDotsNames, cachedMoreArgsNames)") ElementNode[] cachedElementNodeArray,
@Cached("createCallNode(cachedElementNodeArray)") RCallNode callNode) {
int dotsLength = dots.getLength();
int moreArgsLength = moreArgs.getLength();
int[] lengths = new int[dotsLength];
int maxLength = getDotsLengths(frame, dots, dotsLength, cachedElementNodeArray, lengths);
storeAdditionalArguments(frame, moreArgs, dotsLength, moreArgsLength, cachedElementNodeArray);
Object[] result = new Object[maxLength];
for (int i = 0; i < maxLength; i++) {
/* Evaluate and store the arguments */
prepareElements(frame, dots, dotsLength, cachedElementNodeArray, lengths, i);
/* Now call the function */
result[i] = callNode.execute(frame, function);
}
return result;
}
@ExplodeLoop
private static void prepareElements(VirtualFrame frame, RAbstractListVector dots, int dotsLength, ElementNode[] cachedElementNodeArray, int[] lengths, int i) {
for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, cachedElementNodeArray[listIndex].extractNode);
cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, vecElement);
}
}
@ExplodeLoop
private static void storeAdditionalArguments(VirtualFrame frame, RAbstractListVector moreArgs, int dotsLength, int moreArgsLength, ElementNode[] cachedElementNodeArray) {
for (int listIndex = dotsLength; listIndex < dotsLength + moreArgsLength; listIndex++) {
// store additional arguments
cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, moreArgs.getDataAt(listIndex - dotsLength));
}
}
@ExplodeLoop
private static int getDotsLengths(VirtualFrame frame, RAbstractListVector dots, int dotsLength, ElementNode[] cachedElementNodeArray, int[] lengths) {
int maxLength = -1;
for (int i = 0; i < dotsLength; i++) {
int length = cachedElementNodeArray[i].lengthNode.executeInt(frame, dots.getDataAt(i));
......@@ -145,22 +179,13 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
}
lengths[i] = length;
}
for (int listIndex = dotsLength; listIndex < dotsLength + moreArgsLength; listIndex++) {
// store additional arguments
cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame,
moreArgs.getDataAt(listIndex - dotsLength));
}
Object[] result = new Object[maxLength];
for (int i = 0; i < maxLength; i++) {
/* Evaluate and store the arguments */
for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
Object vecElement = getVecElement(frame, dots, i, listIndex, lengths, cachedElementNodeArray[listIndex].extractNode);
cachedElementNodeArray[listIndex].writeVectorElementNode.execute(frame, vecElement);
}
/* Now call the function */
result[i] = callNode.execute(frame, function);
}
return result;
return maxLength;
}
protected static String[] extractNames(RAbstractListVector list) {
CompilerAsserts.neverPartOfCompilation();
RStringVector names = list.getNames();
return names == null ? null : names.getDataCopy();
}
@Specialization(replaces = "cachedMApply")
......@@ -181,13 +206,13 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
}
Object[] values = new Object[dotsLength + moreArgsLength];
String[] names = new String[dotsLength + moreArgsLength];
RStringVector dotsNames = getNames.getNames(dots);
RStringVector dotsNames = getNamesDots.getNames(dots);
if (dotsNames != null) {
for (int listIndex = 0; listIndex < dotsLength; listIndex++) {
names[listIndex] = dotsNames.getDataAt(listIndex).isEmpty() ? null : dotsNames.getDataAt(listIndex);
}
}
RStringVector moreArgsNames = getNames.getNames(moreArgs);
RStringVector moreArgsNames = getNamesMoreArgs.getNames(moreArgs);
for (int listIndex = dotsLength; listIndex < dotsLength + moreArgsLength; listIndex++) {
values[listIndex] = moreArgs.getDataAt(listIndex - dotsLength);
names[listIndex] = moreArgsNames == null ? null : (moreArgsNames.getDataAt(listIndex - dotsLength).isEmpty() ? null : moreArgsNames.getDataAt(listIndex - dotsLength));
......@@ -221,17 +246,15 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
return RCallNode.createCall(Lapply.createCallSourceSection(), null, ArgumentsSignature.get(names), syntaxNodes);
}
protected ElementNode[] createElementNodeArray(RAbstractListVector dots, RAbstractListVector moreArgs) {
int length = dots.getLength() + moreArgs.getLength();
protected ElementNode[] createElementNodeArray(int dotsLength, int moreArgsLength, String[] cachedDotsNames, String[] cachedMoreArgsNames) {
int length = dotsLength + moreArgsLength;
ElementNode[] elementNodes = new ElementNode[length];
RStringVector dotsNames = getNames.getNames(dots);
for (int i = 0; i < dots.getLength(); i++) {
elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1), dotsNames == null ? null : (dotsNames.getDataAt(i).isEmpty() ? null : dotsNames.getDataAt(i))));
for (int i = 0; i < dotsLength; i++) {
elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1), cachedDotsNames == null ? null : (cachedDotsNames[i].isEmpty() ? null : cachedDotsNames[i])));
}
RStringVector moreArgsNames = getNames.getNames(moreArgs);
for (int i = dots.getLength(); i < dots.getLength() + moreArgs.getLength(); i++) {
elementNodes[i] = insert(new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1),
moreArgsNames == null ? null : moreArgsNames.getDataAt(i - dots.getLength()).isEmpty() ? null : moreArgsNames.getDataAt(i - dots.getLength())));
for (int i = 0; i < moreArgsLength; i++) {
elementNodes[i + dotsLength] = insert(
new ElementNode(VECTOR_ELEMENT_PREFIX + (i + 1 + dotsLength), cachedMoreArgsNames == null ? null : cachedMoreArgsNames[i].isEmpty() ? null : cachedMoreArgsNames[i]));
}
return elementNodes;
}
......@@ -240,29 +263,34 @@ public abstract class Mapply extends RBuiltinNode.Arg3 {
return ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
}
protected boolean sameNames(RAbstractListVector list, RAbstractListVector cachedList) {
RStringVector listNames = getNames.getNames(list);
RStringVector cachedListNames = getNames.getNames(cachedList);
if (listNames == null && cachedListNames == null) {
protected boolean sameNames(RAbstractListVector list, String[] cachedNames) {
RStringVector listNames = getNamesDots.getNames(list);
if (listNames == null && cachedNames == null) {
return true;
} else if (listNames == null || cachedListNames == null) {
} else if (listNames == null || cachedNames == null) {
return false;
} else {
for (int i = 0; i < list.getLength(); i++) {
for (int i = 0; i < cachedNames.length; i++) {
String name = listNames.getDataAt(i);
String cachedName = cachedListNames.getDataAt(i);
String cachedName = cachedNames[i];
if (name == cachedName) {
continue;
} else if (name == null || cachedName == null) {
return false;
} else if (!(name.equals(cachedName))) {
return false;
} else {
nonPerfectMatch.enter();
if (name == null || cachedName == null) {
return false;
} else if (!equals(name, cachedName)) {
return false;
}
}
}
return true;
}
}
@TruffleBoundary
private static boolean equals(String name, String cachedName) {
return name.equals(cachedName);
}
}
}
......@@ -33,8 +33,10 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.profiles.LoopConditionProfile;
import com.oracle.truffle.api.profiles.ValueProfile;
import com.oracle.truffle.r.nodes.builtin.RBuiltinNode;
import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RError.Message;
......@@ -413,6 +415,7 @@ public class TrigExpFunctions {
private final NACheck yNACheck = NACheck.create();
private final NACheck xNACheck = NACheck.create();
private final LoopConditionProfile profile = LoopConditionProfile.createCountingProfile();
static {
Casts casts = new Casts(Atan2.class);
......@@ -420,34 +423,19 @@ public class TrigExpFunctions {
casts.arg(1).mapIf(numericValue(), asDoubleVector());
}
private double doFunDouble(double y, double x) {
double result = x;
if (!yNACheck.check(y) && !xNACheck.check(x)) {
result = Math.atan2(y, x);
}
return result;
}
@FunctionalInterface
private interface IntDoubleFunction {
double apply(int i);
}
private RDoubleVector doFun(int length, IntDoubleFunction yFun, IntDoubleFunction xFun,
LoopConditionProfile profile) {
double[] resultVector = new double[length];
private double[] prepareArray(int length) {
reportWork(length);
profile.profileCounted(length);
for (int i = 0; profile.inject(i < length); i++) {
double y = yFun.apply(i);
double x = xFun.apply(i);
if (xNACheck.check(y) || yNACheck.check(x)) {
resultVector[i] = RRuntime.DOUBLE_NA;
} else {
resultVector[i] = Math.atan2(y, x);
}
}
return new double[length];
}
private RDoubleVector createResult(double[] resultVector) {
return RDataFactory.createDoubleVector(resultVector, xNACheck.neverSeenNA() && yNACheck.neverSeenNA());
}
......@@ -455,47 +443,76 @@ public class TrigExpFunctions {
protected double atan2(double y, double x) {
xNACheck.enable(x);
yNACheck.enable(y);
return doFunDouble(y, x);
if (yNACheck.check(y) || xNACheck.check(x)) {
return RRuntime.DOUBLE_NA;
} else {
return Math.atan2(y, x);
}
}
@Specialization
protected RDoubleVector atan2(double y, RAbstractDoubleVector x,
@Cached("createCountingProfile()") LoopConditionProfile profile) {
@Specialization(guards = "x.getLength() > 0")
protected RDoubleVector atan2(double y, RAbstractDoubleVector x) {
xNACheck.enable(x);
yNACheck.enable(y);
return doFun(x.getLength(), i -> y, i -> x.getDataAt(i), profile);
double[] array = prepareArray(x.getLength());
for (int i = 0; profile.inject(i < array.length); i++) {
double xValue = x.getDataAt(i);
if (xNACheck.check(y) || yNACheck.check(xValue)) {
array[i] = RRuntime.DOUBLE_NA;
} else {
array[i] = Math.atan2(y, xValue);
}
}
return createResult(array);
}
@Specialization
protected RDoubleVector atan2(RAbstractDoubleVector y, double x,
@Cached("createCountingProfile()") LoopConditionProfile profile) {
@Specialization(guards = "y.getLength() > 0")
protected RDoubleVector atan2(RAbstractDoubleVector y, double x) {
xNACheck.enable(x);
yNACheck.enable(y);
return doFun(y.getLength(), i -> y.getDataAt(i), i -> x, profile);
double[] array = prepareArray(y.getLength());
for (int i = 0; profile.inject(i < array.length); i++) {
double yValue = y.getDataAt(i);
if (xNACheck.check(yValue) || yNACheck.check(x)) {
array[i] = RRuntime.DOUBLE_NA;
} else {
array[i] = Math.atan2(yValue, x);
}
}
return createResult(array);
}
@Specialization
protected RDoubleVector atan2(RAbstractDoubleVector y, RAbstractDoubleVector x,
@Cached("createCountingProfile()") LoopConditionProfile profile) {
@Specialization(guards = {"y.getLength() > 0", "x.getLength() > 0"})
protected RDoubleVector atan2(RAbstractDoubleVector y, RAbstractDoubleVector x) {
int xLength = x.getLength();
int yLength = y.getLength();
xNACheck.enable(x);
yNACheck.enable(y);
return doFun(Math.max(yLength, xLength), i -> y.getDataAt(i % yLength), i -> x.getDataAt(i % xLength),
profile);
double[] array = prepareArray(Math.max(yLength, xLength));
for (int i = 0; profile.inject(i < array.length); i++) {
double yValue = y.getDataAt(i % yLength);
double xValue = x.getDataAt(i % xLength);
if (xNACheck.check(yValue) || yNACheck.check(xValue)) {
array[i] = RRuntime.DOUBLE_NA;
} else {
array[i] = Math.atan2(yValue, xValue);
}
}
return createResult(array);
}
@Specialization(guards = "y.getLength() == 0 || x.getLength() == 0")
protected RDoubleVector atan2Empty(@SuppressWarnings("unused") RAbstractDoubleVector y, @SuppressWarnings("unused") RAbstractDoubleVector x) {
return RDataFactory.createEmptyDoubleVector();
}
@Specialization(guards = {"!isDouble(x) || !isDouble(y)"})
@TruffleBoundary
@Fallback
protected Object atan2(Object x, Object y) {
CompilerDirectives.transferToInterpreter();
if (x instanceof RAbstractComplexVector || y instanceof RAbstractComplexVector) {
throw RInternalError.unimplemented("atan2 for complex values");
}
throw error(RError.Message.NON_NUMERIC_MATH);
}
protected static boolean isDouble(Object x) {
return x instanceof Double || x instanceof RAbstractDoubleVector;
}
}
}
......@@ -31,7 +31,6 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE;
import com.oracle.truffle.api.CompilerDirectives;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.profiles.ConditionProfile;
import com.oracle.truffle.r.nodes.attributes.RemoveAttributeNode;
......@@ -50,8 +49,10 @@ import com.oracle.truffle.r.runtime.RError;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.builtins.RBuiltin;
import com.oracle.truffle.r.runtime.data.RAttributable;
import com.oracle.truffle.r.runtime.data.RComplex;
import com.oracle.truffle.r.runtime.data.RList;
import com.oracle.truffle.r.runtime.data.RNull;
import com.oracle.truffle.r.runtime.data.RRaw;
import com.oracle.truffle.r.runtime.data.RShareable;
import com.oracle.truffle.r.runtime.data.RStringVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractContainer;
......@@ -247,16 +248,14 @@ public abstract class UpdateAttributes extends RBuiltinNode.Arg2 {
* All other, non-performance centric, {@link RAttributable} types, or error case for RNull
* value.
*/
@Fallback
@Specialization(guards = "!isRAbstractContainer(o)")
@TruffleBoundary
protected Object doOtherNull(Object o, Object operand) {
checkAttributable(o);
Object obj = getNonShared(o);
RAttributable attrObj = (RAttributable) obj;
attrObj.removeAllAttributes();
protected Object doOtherNull(RAttributable o, Object operand) {
RAttributable obj = getNonShared(o);
obj.removeAllAttributes();
if (operand == RNull.instance) {
attrObj.setClassAttr(null);
obj.setClassAttr(null);
} else {
RList list = (RList) operand;
RStringVector listNames = list.getNames();
......@@ -273,24 +272,27 @@ public abstract class UpdateAttributes extends RBuiltinNode.Arg2 {
if (attrValue == null) {
throw error(RError.Message.SET_INVALID_CLASS_ATTR);
}
attrObj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue));
obj.setClassAttr(UpdateAttr.convertClassAttrFromObject(attrValue));
} else {
attrObj.setAttr(attrName.intern(), list.getDataAt(i));
obj.setAttr(attrName.intern(), list.getDataAt(i));
}
}
}
return obj;
}
private void checkAttributable(Object obj) {
if (!(obj instanceof RAttributable)) {
throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
}
@Specialization(guards = {"!isRAttributable(o)", "!isScalar(o)"})
protected Object doFallback(@SuppressWarnings("unused") Object o, @SuppressWarnings("unused") Object operand) {
throw error(RError.Message.INVALID_OR_UNIMPLEMENTED_ARGUMENTS);
}
protected static boolean isScalar(Object o) {
return o instanceof Integer || o instanceof Double || o instanceof Byte || o instanceof RRaw || o instanceof RComplex;
}
private static Object getNonShared(Object obj) {
private static RAttributable getNonShared(RAttributable obj) {
if (obj instanceof RShareable) {
return ((RShareable) obj).getNonShared();
return (RAttributable) ((RShareable) obj).getNonShared();
}
return obj;
}
......
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.r.nodes.builtin.base.fastpaths;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector;
import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
import com.oracle.truffle.r.runtime.nodes.RFastPathNode;
abstract class AsScalarNode extends Node {
public abstract Object execute(Object value);
@Specialization
protected static int asScalar(int value) {
return value;
}
@Specialization
protected static double asScalar(double value) {
return value;
}
@Specialization(guards = {"value.getLength() == 1", "value.getAttributes() == null"})
protected static int asScalar(RAbstractIntVector value) {
return value.getDataAt(0);
}
@Specialization(guards = {"value.getLength() == 1", "value.getAttributes() == null"})
protected static double asScalar(RAbstractDoubleVector value) {
return value.getDataAt(0);
}
@Fallback
protected static Object asScalar(@SuppressWarnings("unused") Object value) {
return null;
}
public static AsScalarNode create() {
return AsScalarNodeGen.create();
}
}
public abstract class SubscriptDataFrameFastPath extends RFastPathNode {
@Child private ExtractVectorNode extractNode = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
@Specialization(guards = {"positions.getLength() == 1", "positions.getSignature().getNonNullCount() == 0"})
protected Object subscript1(VirtualFrame frame, RAbstractListVector df, RArgsValuesAndNames positions, Object exact,
@Cached("create()") AsScalarNode asScalar) {
Object pos = asScalar.execute(positions.getArgument(0));
if (pos == null) {
return null;
}
return extractNode.apply(frame, df, new Object[]{pos}, exact, RRuntime.LOGICAL_TRUE);
}
@Specialization(guards = {"positions.getLength() == 2", "positions.getSignature().getNonNullCount() == 0"})
protected Object subscript2(VirtualFrame frame, RAbstractListVector df, RArgsValuesAndNames positions, Object exact,
@Cached("create()") AsScalarNode asScalar1,
@Cached("create()") AsScalarNode asScalar2) {
Object pos2 = asScalar2.execute(positions.getArgument(1));
if (pos2 == null) {
return null;
}
Object extracted = extractNode.apply(frame, df, new Object[]{pos2}, exact, RRuntime.LOGICAL_TRUE);
Object pos1 = asScalar1.execute(positions.getArgument(0));
if (pos1 == null) {
return null;
}
return extractNode.apply(frame, extracted, new Object[]{pos1}, exact, RRuntime.LOGICAL_TRUE);
}
@Fallback
@SuppressWarnings("unused")
protected Object fallback(Object df, Object positions, Object exact) {
return null;
}
}
/*
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.r.nodes.builtin.base.fastpaths;
import com.oracle.truffle.api.dsl.Cached;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.Specialization;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
import com.oracle.truffle.r.runtime.RRuntime;
import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
import com.oracle.truffle.r.runtime.data.model.RAbstractListVector;
import com.oracle.truffle.r.runtime.nodes.RFastPathNode;
public abstract class SubsetDataFrameFastPath extends RFastPathNode {
@Child private ExtractVectorNode extractNode = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, false);
@Specialization(guards = {"positions.getLength() == 2", "positions.getSignature().getNonNullCount() == 0"})
protected Object subscript2(VirtualFrame frame, RAbstractListVector df, RArgsValuesAndNames positions, Object exact,
@Cached("create()") AsScalarNode asScalar1,
@Cached("create()") AsScalarNode asScalar2) {
Object pos2 = asScalar2.execute(positions.getArgument(1));
if (pos2 == null) {
return null;
}
Object extracted = extractNode.apply(frame, df, new Object[]{pos2}, exact, RRuntime.LOGICAL_TRUE);
Object pos1 = asScalar1.execute(positions.getArgument(0));
if (pos1 == null) {
return null;
}
return extractNode.apply(frame, extracted, new Object[]{pos1}, exact, RRuntime.LOGICAL_TRUE);
}
@Fallback
@SuppressWarnings("unused")
protected Object fallback(Object df, Object positions, Object exact) {
return null;
}
}
......@@ -176,7 +176,9 @@ public class DebugHandling {
}
accept(element.getSyntaxLHS());
for (RSyntaxElement arg : element.getSyntaxArguments()) {
accept(arg);
if (arg != null) {
accept(arg);
}
}
return null;
}
......
......@@ -73,13 +73,7 @@ public abstract class CastIntegerNode extends CastIntegerBaseNode {
public abstract Object executeInt(Object o);
@Specialization
protected RIntVector doIntVector(RIntVector operand) {
return operand;
}
@Specialization
protected RIntSequence doIntVector(RIntSequence operand) {
// sequence does not have attributes - nothing to copy or drop
protected RAbstractIntVector doIntVector(RAbstractIntVector operand) {
return operand;
}
......
......@@ -40,6 +40,7 @@ public enum RVersionInfo {
Day(RVersionNumber.RELEASE_DAY),
SvnRev("svn rev", null),
Language("R"),
Engine("FastR"),
VersionString("version.string", RVersionNumber.VERSION_STRING);
// @formatter:on
......
......@@ -15,6 +15,7 @@ package com.oracle.truffle.r.runtime.nmath;
import static com.oracle.truffle.r.runtime.nmath.GammaFunctions.lgammafn;
import static com.oracle.truffle.r.runtime.nmath.GammaFunctions.lgammafnSign;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.r.runtime.RError.Message;
// transcribed from nmath/choose.c
......@@ -26,6 +27,7 @@ public class Choose {
return -Math.log(n + 1.) - LBeta.lbeta(n - k + 1., k + 1.);
}
@TruffleBoundary
public static double choose(double n, double ka) {
double k = ka;
if (Double.isNaN(n) || Double.isNaN(ka)) {
......@@ -76,6 +78,7 @@ public class Choose {
return Math.exp(lfastchoose(n, k));
}
@TruffleBoundary
public static double lchoose(double n, double kIn) {
double k = RMath.forceint(kIn);
/* NaNs propagated correctly */
......
Source diff could not be displayed: it is too large. Options to address this: view the blob.
......@@ -494,7 +494,7 @@ public class TestBase {
}
private static String[] getAssertEvalFastR(String gnuROutput, String input) {
return new String[]{"if (length(grep(\"FastR\", R.Version()$version.string)) != 1) { " + gnuROutput + " } else { " + input + " }"};
return new String[]{"if (!any(R.version$engine == \"FastR\")) { " + gnuROutput + " } else { " + input + " }"};
}
/*
......
......@@ -63,14 +63,14 @@ public class TestBuiltin_rowsum extends TestBase {
public void testRowsumArgCoverage() {
assertEval("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, ug, FALSE, as.character(ug)))");
// 2nd parm function => GnuR Error: segfault
assertEvalFastR("{ x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug))); }",
"cat(\"Error in rowsum_matrix(x, print, ug, FALSE, as.character(ug)) :\\n invalid 'g' argument\"");
assertEvalFastR("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, print, ug, FALSE, as.character(ug)));",
"cat(\"Error: invalid 'g' argument\\n\")");
// 3rd parm is function => GnuR Error: "Error: unimplemented type 'closure' in
// 'HashTableSetup'"
assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, print, FALSE, as.character(ug)))");
// 2nd parm NULL => GnuR Error: segfault\n" +
assertEvalFastR("x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, NULL, ug, FALSE,as.character(ug)))",
"cat(\"Error in rowsum_matrix(x, NULL, ug, FALSE, as.character(ug)) :\\n invalid 'g' argument\"");
"cat(\"Error: invalid 'g' argument\\n\")");
// 3rd parm NULL => GnuR Error: Error: unimplemented type 'NULL' in 'HashTableSetup'
assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, g, NULL, FALSE,as.character(ug)))");
assertEval(Output.IgnoreErrorMessage, "x <- matrix(1:10, ncol=2); g <- c(1,2,3,2,1); ug <-unique(g); .Internal(rowsum_matrix(x, , ug, FALSE,as.character(ug)))");
......
......@@ -38,11 +38,10 @@ public class TestBuiltin_strrep extends TestBase {
@Test
public void testArgsCasts() {
// GnuR fails with segfault
assertEvalFastR("{ .Internal(strrep(NULL, 5) }", "cat(\"character(0)\")");
assertEvalFastR(".Internal(strrep(NULL, 5))", "cat(\"character(0)\\n\")");
// GnuR - infinite loop
assertEvalFastR("{ .Internal(strrep('aa', NULL) }", "cat(\"character(0)\")");
assertEvalFastR(".Internal(strrep('aa', NULL))", "cat(\"character(0)\\n\")");
assertEval("{ .Internal(strrep(, '') }");
assertEval("{ .Internal(strrep('', ) }");
}
}
# test remote updated of atomic vector (must stay private)
if (length(grep("FastR", R.Version()$version.string)) == 1) {
if (any(R.version$engine == "FastR")) {
ch <- .fastr.channel.create(1L)
code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1]<-7; .fastr.channel.send(ch, x)"
cx <- .fastr.context.spawn(code)
......
# test remote updated of atomic vector with shareable attribute (must stay private)
if (length(grep("FastR", R.Version()$version.string)) == 1) {
if (any(R.version$engine == "FastR")) {
ch <- .fastr.channel.create(1L)
code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1]<-7; .fastr.channel.send(ch, x)"
cx <- .fastr.context.spawn(code)
......
# test remote updated of atomic vector with serializable attribute (must stay private)
if (length(grep("FastR", R.Version()$version.string)) == 1) {
if (any(R.version$engine == "FastR")) {
ch <- .fastr.channel.create(1L)
code <- "ch <- .fastr.channel.get(1L); x<-.fastr.channel.receive(ch); x[1]<-7; .fastr.channel.send(ch, x)"
cx <- .fastr.context.spawn(code)
......
# test sending environment with global parent and assigning it remotely (should assign remotely but not locally)
if (length(grep("FastR", R.Version()$version.string)) == 1) {
if (any(R.version$engine == "FastR")) {
ch <- .fastr.channel.create(1L)
code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); assign('y', 7, pos=env); .fastr.channel.send(ch, get('x', envir=env))"
cx <- .fastr.context.spawn(code)
......
# test sending environment with a parent and global grandparent and assigning it remotely (should assign remotely but not locally)
if (length(grep("FastR", R.Version()$version.string)) == 1) {
if (any(R.version$engine == "FastR")) {
ch <- .fastr.channel.create(1L)
code <- "ch <- .fastr.channel.get(1L); env<-.fastr.channel.receive(ch); assign('y', 70, pos=env); assign('z', 420, pos=parent.env(env)); .fastr.channel.send(ch, c(get('w', envir=env), get('x', envir=parent.env(env))))"
cx <- .fastr.context.spawn(code)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment