diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java index 4a8ea1bfe1df35217683f504252afa0a464ed420..141b9841a229b852df644883d8de76e92ddcf47b 100644 --- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java +++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/common/JavaUpCallsRFFIImpl.java @@ -766,7 +766,7 @@ public abstract class JavaUpCallsRFFIImpl implements UpCallsRFFI { RList argsList = ((RPairList) args).toRList(); result = RContext.getEngine().evalFunction(f, env == REnvironment.globalEnv() ? null : ((REnvironment) env).getFrame(), RCaller.topLevel, true, ArgumentsSignature.fromNamesAttribute(argsList.getNames()), - argsList.getDataNonShared()); + argsList.getDataTemp()); } } else if (expr instanceof RSymbol) { RSyntaxNode lookup = RContext.getASTBuilder().lookup(RSyntaxNode.LAZY_DEPARSE, ((RSymbol) expr).getName(), false); diff --git a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java index 5f4df74f1a5a34e275d289194cd536c06dd9ad88..06353f7b49c45aaf5fd2b08f1d60611c62df7c89 100644 --- a/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java +++ b/com.oracle.truffle.r.ffi.processor/src/com/oracle/truffle/r/ffi/processor/FFIProcessor.java @@ -123,8 +123,12 @@ public final class FFIProcessor extends AbstractProcessor { private void generateTable(ExecutableElement[] methods) throws IOException { JavaFileObject fileObj = processingEnv.getFiler().createSourceFile("com.oracle.truffle.r.ffi.impl.upcalls.RFFIUpCallTable"); Writer w = fileObj.openWriter(); - w.append("// GENERATED; DO NOT EDIT\n"); + w.append("// GENERATED by com.oracle.truffle.r.ffi.processor.FFIProcessor class; DO NOT EDIT\n"); w.append("package com.oracle.truffle.r.ffi.impl.upcalls;\n"); + w.append("/**\n" + + " * The following enum contains an entry for each method in the interface annoated\n" + + " * with @RFFIUpCallRoot including inherited methods.\n" + + " */"); w.append("public enum RFFIUpCallTable {\n"); for (int i = 0; i < methods.length; i++) { ExecutableElement method = methods[i]; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java index 47a820c41aa22f757c6aeb7ab398585251bf28c8..e9b73da1514c22210656f0301bff85c889a10ec6 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cdist.java @@ -32,6 +32,8 @@ import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector.DoubleAccessor; import com.oracle.truffle.r.runtime.ops.na.NACheck; public abstract class Cdist extends RExternalBuiltinNode.Arg4 { @@ -49,6 +51,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { @Specialization(guards = "method == cachedMethod") protected RDoubleVector cdist(RAbstractDoubleVector x, @SuppressWarnings("unused") int method, RList list, double p, @SuppressWarnings("unused") @Cached("method") int cachedMethod, + @Cached("new()") AccessVector.Double xAccess, @Cached("getMethod(method)") Method methodObj, @Cached("create()") SetAttributeNode setAttrNode, @Cached("create()") SetClassAttributeNode setClassAttrNode, @@ -58,7 +61,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { int n = nr * (nr - 1) / 2; /* avoid int overflow for N ~ 50,000 */ double[] ans = new double[n]; RDoubleVector xm = x.materialize(); - rdistance(xm.getDataWithoutCopying(), nr, nc, ans, false, methodObj, p); + rdistance(new DoubleAccessor(x, xAccess), nr, nc, ans, false, methodObj, p); RDoubleVector result = RDataFactory.createDoubleVector(ans, naCheck.neverSeenNA()); DynamicObject resultAttrs = result.initAttributes(); @@ -93,7 +96,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { return Method.values()[method - 1]; } - private void rdistance(double[] x, int nr, int nc, double[] d, boolean diag, Method method, double p) { + private void rdistance(DoubleAccessor xAccess, int nr, int nc, double[] d, boolean diag, Method method, double p) { int ij; /* can exceed 2^31 - 1, but Java can't handle that */ // if (method == Method.MINKOWSKI) { @@ -106,7 +109,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { naCheck.enable(true); for (int j = 0; j <= nr; j++) { for (int i = j + dc; i < nr; i++) { - double r = method.dist(x, nr, nc, i, j, p); + double r = method.dist(xAccess, nr, nc, i, j, p); naCheck.check(r); d[ij++] = r; } @@ -116,7 +119,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { public enum Method { EUCLIDEAN { @Override - public double dist(double[] x, int nr, int nc, final int i1in, final int i2in, double p) { + public double dist(DoubleAccessor xAccess, int nr, int nc, final int i1in, final int i2in, double p) { int i1 = i1in; int i2 = i2in; double dev; @@ -127,8 +130,8 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { count = 0; dist = 0; for (j = 0; j < nc; j++) { - if (bothNonNAN(x[i1], x[i2])) { - dev = (x[i1] - x[i2]); + if (bothNonNAN(xAccess.getDataAt(i1), xAccess.getDataAt(i2))) { + dev = (xAccess.getDataAt(i1) - xAccess.getDataAt(i2)); if (!RRuntime.isNAorNaN(dev)) { dist += dev * dev; count++; @@ -149,7 +152,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { }, MAXIMUM { @Override - public double dist(double[] x, int nr, int nc, final int i1in, final int i2in, double p) { + public double dist(DoubleAccessor xAccess, int nr, int nc, final int i1in, final int i2in, double p) { int i1 = i1in; int i2 = i2in; double dev; @@ -160,8 +163,8 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { count = 0; dist = -Double.MAX_VALUE; for (j = 0; j < nc; j++) { - if (bothNonNAN(x[i1], x[i2])) { - dev = Math.abs(x[i1] - x[i2]); + if (bothNonNAN(xAccess.getDataAt(i1), xAccess.getDataAt(i2))) { + dev = Math.abs(xAccess.getDataAt(i1) - xAccess.getDataAt(i2)); if (!RRuntime.isNAorNaN(dev)) { if (dev > dist) { dist = dev; @@ -181,7 +184,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { }, MANHATTAN { @Override - public double dist(double[] x, int nr, int nc, final int i1in, final int i2in, double p) { + public double dist(DoubleAccessor xAccess, int nr, int nc, final int i1in, final int i2in, double p) { int i1 = i1in; int i2 = i2in; double dev; @@ -192,8 +195,8 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { count = 0; dist = 0; for (j = 0; j < nc; j++) { - if (bothNonNAN(x[i1], x[i2])) { - dev = Math.abs(x[i1] - x[i2]); + if (bothNonNAN(xAccess.getDataAt(i1), xAccess.getDataAt(i2))) { + dev = Math.abs(xAccess.getDataAt(i1) - xAccess.getDataAt(i2)); if (!RRuntime.isNAorNaN(dev)) { dist += dev; count++; @@ -214,7 +217,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { }, CANBERRA { @Override - public double dist(double[] x, int nr, int nc, final int i1in, final int i2in, double p) { + public double dist(DoubleAccessor xAccess, int nr, int nc, final int i1in, final int i2in, double p) { int i1 = i1in; int i2 = i2in; double dev; @@ -227,9 +230,9 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { count = 0; dist = 0; for (j = 0; j < nc; j++) { - if (bothNonNAN(x[i1], x[i2])) { - sum = Math.abs(x[i1] + x[i2]); - diff = Math.abs(x[i1] - x[i2]); + if (bothNonNAN(xAccess.getDataAt(i1), xAccess.getDataAt(i2))) { + sum = Math.abs(xAccess.getDataAt(i1) + xAccess.getDataAt(i2)); + diff = Math.abs(xAccess.getDataAt(i1) - xAccess.getDataAt(i2)); if (sum > DBL_MIN || diff > DBL_MIN) { dev = diff / sum; if (!RRuntime.isNAorNaN(dev) || @@ -255,7 +258,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { }, BINARY { @Override - public double dist(double[] x, int nr, int nc, final int i1in, final int i2in, double p) { + public double dist(DoubleAccessor xAccess, int nr, int nc, final int i1in, final int i2in, double p) { int i1 = i1in; int i2 = i2in; int total; @@ -268,13 +271,13 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { dist = 0; for (j = 0; j < nc; j++) { - if (bothNonNAN(x[i1], x[i2])) { - if (!bothFinite(x[i1], x[i2])) { + if (bothNonNAN(xAccess.getDataAt(i1), xAccess.getDataAt(i2))) { + if (!bothFinite(xAccess.getDataAt(i1), xAccess.getDataAt(i2))) { RError.warning(RError.SHOW_CALLER2, RError.Message.GENERIC, "treating non-finite values as NA"); } else { - if (x[i1] != 0. || x[i2] != 0.) { + if (xAccess.getDataAt(i1) != 0. || xAccess.getDataAt(i2) != 0.) { count++; - if (!(x[i1] != 0. && x[i2] != 0.)) { + if (!(xAccess.getDataAt(i1) != 0. && xAccess.getDataAt(i2) != 0.)) { dist++; } } @@ -297,7 +300,7 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { }, MINKOWSKI { @Override - public double dist(double[] x, int nr, int nc, final int i1in, final int i2in, double p) { + public double dist(DoubleAccessor xAccess, int nr, int nc, final int i1in, final int i2in, double p) { int i1 = i1in; int i2 = i2in; double dev; @@ -308,8 +311,8 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { count = 0; dist = 0; for (j = 0; j < nc; j++) { - if (bothNonNAN(x[i1], x[i2])) { - dev = (x[i1] - x[i2]); + if (bothNonNAN(xAccess.getDataAt(i1), xAccess.getDataAt(i2))) { + dev = (xAccess.getDataAt(i1) - xAccess.getDataAt(i2)); if (!RRuntime.isNAorNaN(dev)) { dist += Math.pow(Math.abs(dev), p); count++; @@ -328,6 +331,6 @@ public abstract class Cdist extends RExternalBuiltinNode.Arg4 { } }; - public abstract double dist(double[] x, int nr, int nc, int i1, int i2, double p); + public abstract double dist(DoubleAccessor xAccess, int nr, int nc, int i1, int i2, double p); } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java index d4f616e70c5549f6e549c139b0dc12099410b1b5..4bb86b4814f961b6c24be2ff3d46766a7771ad2b 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/Cutree.java @@ -10,8 +10,8 @@ */ package com.oracle.truffle.r.library.stats; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyIntegerVector; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -20,6 +20,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector; // translated from library/stats/src/hclust_utils.c @@ -32,10 +33,10 @@ public abstract class Cutree extends RExternalBuiltinNode.Arg2 { } @Specialization - protected RIntVector cutree(RAbstractIntVector mergeIn, RAbstractIntVector whichIn, + protected RIntVector cutree(RAbstractIntVector merge, RAbstractIntVector which, + @Cached("new()") AccessVector.Int mergeAccess, + @Cached("new()") AccessVector.Int whichAccess, @Cached("create()") GetDimAttributeNode getDimNode) { - RIntVector merge = mergeIn.materialize(); - RIntVector which = whichIn.materialize(); int whichLen = which.getLength(); int j; @@ -58,8 +59,8 @@ public abstract class Cutree extends RExternalBuiltinNode.Arg2 { int[] z = new int[n]; int[] iAns = new int[n * whichLen]; - int[] iMerge = merge.getDataWithoutCopying(); - int[] iWhich = which.getDataWithoutCopying(); + Object mergeStore = mergeAccess.init(merge); + Object whichStore = whichAccess.init(which); // for (k = 1; k <= n; k++) { for (k = 0; k < n; k++) { @@ -69,8 +70,8 @@ public abstract class Cutree extends RExternalBuiltinNode.Arg2 { for (k = 1; k <= n - 1; k++) { /* k-th merge, from n-k+1 to n-k atoms: (m1,m2) = merge[ k , ] */ - m1 = iMerge[k - 1]; - m2 = iMerge[n - 1 + k - 1]; + m1 = mergeAccess.getDataAt(merge, mergeStore, k - 1); + m2 = mergeAccess.getDataAt(merge, mergeStore, n - 1 + k - 1); if (m1 < 0 && m2 < 0) { /* merging atoms [-m1] and [-m2] */ mNr[adj(-m1)] = mNr[adj(-m2)] = k; @@ -104,7 +105,7 @@ public abstract class Cutree extends RExternalBuiltinNode.Arg2 { */ foundJ = false; for (j = 0; j < whichLen; j++) { - if (iWhich[j] == n - k) { + if (whichAccess.getDataAt(which, whichStore, j) == n - k) { if (!foundJ) { /* first match (and usually only one) */ foundJ = true; // for (l = 1; l <= n; l++) @@ -134,7 +135,7 @@ public abstract class Cutree extends RExternalBuiltinNode.Arg2 { /* Dealing with trivial case which[] = n : */ for (j = 0; j < whichLen; j++) { - if (iWhich[j] == n) { + if (whichAccess.getDataAt(which, whichStore, j) == n) { for (l = 1, m1 = j * n; l <= n; l++, m1++) { iAns[m1] = l; } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java index 9f35e9ded8df6ad2204d774c96389f66549ffc9d..b1b5b7c187e27f3f64ebfebeee367ecff6cf03a3 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/DoubleCentre.java @@ -10,8 +10,8 @@ */ package com.oracle.truffle.r.library.stats; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -20,6 +20,7 @@ import com.oracle.truffle.r.nodes.builtin.RExternalBuiltinNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector; public abstract class DoubleCentre extends RExternalBuiltinNode.Arg1 { @@ -30,29 +31,31 @@ public abstract class DoubleCentre extends RExternalBuiltinNode.Arg1 { @Specialization protected RDoubleVector doubleCentre(RAbstractDoubleVector aVecAbs, + @Cached("new()") AccessVector.Double aAccess, @Cached("create()") GetDimAttributeNode getDimNode) { RDoubleVector aVec = aVecAbs.materialize(); int n = getDimNode.nrows(aVec); - double[] a = aVec.getDataWithoutCopying(); // does not copy - + Object aStore = aAccess.init(aVec); for (int i = 0; i < n; i++) { double sum = 0; for (int j = 0; j < n; j++) { - sum += a[i + j * n]; + sum += aAccess.getDataAt(aVec, aStore, i + j * n); } sum /= n; for (int j = 0; j < n; j++) { - a[i + j * n] -= sum; + double val = aAccess.getDataAt(aVec, aStore, i + j * n); + aAccess.setDataAt(aVec, aStore, i + j * n, val - sum); } } for (int j = 0; j < n; j++) { double sum = 0; for (int i = 0; i < n; i++) { - sum += a[i + j * n]; + sum += aAccess.getDataAt(aVec, aStore, i + j * n); } sum /= n; for (int i = 0; i < n; i++) { - a[i + j * n] -= sum; + double val = aAccess.getDataAt(aVec, aStore, i + j * n); + aAccess.setDataAt(aVec, aStore, i + j * n, val - sum); } } return aVec; diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java index 0379b9d46dfdf186173170d2d399bd36c5ce55f2..8167a7610c109ba64237738c0739f3ef33bb9599 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/RMultinomNode.java @@ -14,8 +14,8 @@ package com.oracle.truffle.r.library.stats; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.notIntNA; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; import static com.oracle.truffle.r.runtime.RError.Message.NA_IN_PROB_VECTOR; import static com.oracle.truffle.r.runtime.RError.Message.NEGATIVE_PROBABILITY; import static com.oracle.truffle.r.runtime.RError.Message.NO_POSITIVE_PROBABILITIES; @@ -32,9 +32,12 @@ import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.data.RDataFactory; +import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector.DoubleAccessor; import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider; import com.oracle.truffle.r.runtime.nmath.distr.RMultinom; import com.oracle.truffle.r.runtime.nmath.distr.Rbinom; @@ -65,19 +68,20 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 { @Specialization protected RIntVector doMultinom(int n, int size, RAbstractDoubleVector probsVec, + @Cached("new()") AccessVector.Double probsAccess, @Cached("create()") ReuseNonSharedNode reuseNonSharedNode, @Cached("createClassProfile()") ValueProfile randGeneratorClassProfile, @Cached("createBinaryProfile()") ConditionProfile hasAttributesProfile, @Cached("create()") UpdateShareableChildValueNode updateSharedAttributeNode, @Cached("createNames()") GetFixedAttributeNode getNamesNode, @Cached("createDimNames()") SetFixedAttributeNode setDimNamesNode) { - RAbstractDoubleVector nonSharedProbs = (RAbstractDoubleVector) reuseNonSharedNode.execute(probsVec); - double[] probs = nonSharedProbs.materialize().getDataWithoutCopying(); - fixupProb(probs); + RDoubleVector nonSharedProbs = ((RAbstractDoubleVector) reuseNonSharedNode.execute(probsVec)).materialize(); + DoubleAccessor probs = new DoubleAccessor(nonSharedProbs, probsAccess); + fixupProb(nonSharedProbs, probs.store, probsAccess); RRNG.getRNGState(); RandomNumberProvider rand = new RandomNumberProvider(randGeneratorClassProfile.profile(RRNG.currentGenerator()), RRNG.currentNormKind()); - int k = probs.length; + int k = probs.vector.getLength(); int[] result = new int[k * n]; boolean isComplete = true; for (int i = 0, ik = 0; i < n; i++, ik += k) { @@ -96,10 +100,12 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 { return resultVec; } - private void fixupProb(double[] p) { + private void fixupProb(RDoubleVector p, Object pStore, AccessVector.Double pAccess) { double sum = 0.0; int npos = 0; - for (double prob : p) { + int pLength = p.getLength(); + for (int i = 0; i < pLength; i++) { + double prob = pAccess.getDataAt(p, pStore, i); if (!Double.isFinite(prob)) { throw error(NA_IN_PROB_VECTOR); } @@ -114,8 +120,9 @@ public abstract class RMultinomNode extends RExternalBuiltinNode.Arg3 { if (npos == 0) { throw error(NO_POSITIVE_PROBABILITIES); } - for (int i = 0; i < p.length; i++) { - p[i] /= sum; + for (int i = 0; i < pLength; i++) { + double prob = pAccess.getDataAt(p, pStore, i); + pAccess.setDataAt(p, pStore, i, prob / sum); } } } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java index 2af07cc9e5d58828686678f3503daa476edb5c3a..f5046039d3ef3d828236f0261e127caa80c3bc1b 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/SplineFunctions.java @@ -88,7 +88,7 @@ public class SplineFunctions { double[] c = new double[n]; double[] d = new double[n]; - SplineFunctions.splineCoef(method, n, x.getDataWithoutCopying(), y.getDataWithoutCopying(), b, c, d); + SplineFunctions.splineCoef(method, n, x.getReadonlyData(), y.getReadonlyData(), b, c, d); final boolean complete = x.isComplete() && y.isComplete(); RDoubleVector bv = RDataFactory.createDoubleVector(b, complete); @@ -421,8 +421,8 @@ public class SplineFunctions { RDoubleVector c = (RDoubleVector) z.getDataAt(z.getElementIndexByName("c")); RDoubleVector d = (RDoubleVector) z.getDataAt(z.getElementIndexByName("d")); - splineEval(method, nu, xout.getDataWithoutCopying(), yout, nx, x.getDataWithoutCopying(), y.getDataWithoutCopying(), b.getDataWithoutCopying(), c.getDataWithoutCopying(), - d.getDataWithoutCopying()); + splineEval(method, nu, xout.getReadonlyData(), yout, nx, x.getReadonlyData(), y.getReadonlyData(), b.getReadonlyData(), c.getReadonlyData(), + d.getReadonlyData()); return RDataFactory.createDoubleVector(yout, xout.isComplete() && x.isComplete() && y.isComplete()); } diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java index ec765e5a52901a9f96ca97ee9c14af841a886072..ee14351e7b93cc44b31ab3ceb978d7c1fae92ecc 100644 --- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java +++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/stats/StatsFunctionsNodes.java @@ -12,11 +12,11 @@ */ package com.oracle.truffle.r.library.stats; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.doubleValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.emptyDoubleVector; -import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.instanceOf; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.missingValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.nullValue; +import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.numericValue; import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; @@ -46,6 +46,8 @@ import com.oracle.truffle.r.runtime.data.RDouble; import com.oracle.truffle.r.runtime.data.RDoubleVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector.DoubleAccessor; import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function2_1; import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function2_2; import com.oracle.truffle.r.runtime.nmath.MathFunctions.Function3_1; @@ -363,8 +365,8 @@ public final class StatsFunctionsNodes { static { Casts casts = new Casts(Approx.class); - casts.arg(0).mustBe(instanceOf(RDoubleVector.class)); - casts.arg(1).mustBe(instanceOf(RDoubleVector.class)); + casts.arg(0).mustBe(doubleValue()); + casts.arg(1).mustBe(doubleValue()); casts.arg(2).mustBe(missingValue().not()).mapIf(nullValue(), emptyDoubleVector()).asDoubleVector(); casts.arg(3).asIntegerVector().findFirst(); casts.arg(4).asDoubleVector().findFirst(); @@ -373,7 +375,9 @@ public final class StatsFunctionsNodes { } @Specialization - protected RDoubleVector approx(RDoubleVector x, RDoubleVector y, RAbstractDoubleVector v, int method, double yl, double yr, double f) { + protected RDoubleVector approx(RAbstractDoubleVector x, RAbstractDoubleVector y, RAbstractDoubleVector v, int method, double yl, double yr, double f, + @Cached("new()") AccessVector.Double xAccess, + @Cached("new()") AccessVector.Double yAccess) { int nx = x.getLength(); int nout = v.getLength(); double[] yout = new double[nout]; @@ -385,9 +389,12 @@ public final class StatsFunctionsNodes { apprMeth.ylow = yl; apprMeth.yhigh = yr; naCheck.enable(true); + + DoubleAccessor xAccessor = new DoubleAccessor(x, xAccess); + DoubleAccessor yAccessor = new DoubleAccessor(y, yAccess); for (int i = 0; i < nout; i++) { double xouti = v.getDataAt(i); - yout[i] = RRuntime.isNAorNaN(xouti) ? xouti : approx1(xouti, x.getDataWithoutCopying(), y.getDataWithoutCopying(), nx, apprMeth); + yout[i] = RRuntime.isNAorNaN(xouti) ? xouti : approx1(xouti, xAccessor, yAccessor, nx, apprMeth); naCheck.check(yout[i]); } return RDataFactory.createDoubleVector(yout, naCheck.neverSeenNA()); @@ -401,8 +408,8 @@ public final class StatsFunctionsNodes { int kind; } - private static double approx1(double v, double[] x, double[] y, int n, - ApprMeth apprMeth) { + private static double approx1(double v, DoubleAccessor x, DoubleAccessor y, int n, + ApprMeth apprMeth) { /* Approximate y(v), given (x,y)[i], i = 0,..,n-1 */ int i; int j; @@ -416,17 +423,17 @@ public final class StatsFunctionsNodes { j = n - 1; /* handle out-of-domain points */ - if (v < x[i]) { + if (v < x.getDataAt(i)) { return apprMeth.ylow; } - if (v > x[j]) { + if (v > x.getDataAt(j)) { return apprMeth.yhigh; } /* find the correct interval by bisection */ - while (i < j - 1) { /* x[i] <= v <= x[j] */ + while (i < j - 1) { /* x.getDataAt(i) <= v <= x.getDataAt(j) */ ij = (i + j) / 2; /* i+1 <= ij <= j-1 */ - if (v < x[ij]) { + if (v < x.getDataAt(ij)) { j = ij; } else { i = ij; @@ -437,18 +444,18 @@ public final class StatsFunctionsNodes { /* interpolation */ - if (v == x[j]) { - return y[j]; + if (v == x.getDataAt(j)) { + return y.getDataAt(j); } - if (v == x[i]) { - return y[i]; + if (v == x.getDataAt(i)) { + return y.getDataAt(i); } - /* impossible: if(x[j] == x[i]) return y[i]; */ + /* impossible: if(x.getDataAt(j) == x.getDataAt(i)) return y.getDataAt(i); */ if (apprMeth.kind == 1) { /* linear */ - return y[i] + (y[j] - y[i]) * ((v - x[i]) / (x[j] - x[i])); + return y.getDataAt(i) + (y.getDataAt(j) - y.getDataAt(i)) * ((v - x.getDataAt(i)) / (x.getDataAt(j) - x.getDataAt(i))); } else { /* 2 : constant */ - return (apprMeth.f1 != 0.0 ? y[i] * apprMeth.f1 : 0.0) + (apprMeth.f2 != 0.0 ? y[j] * apprMeth.f2 : 0.0); + return (apprMeth.f1 != 0.0 ? y.getDataAt(i) * apprMeth.f1 : 0.0) + (apprMeth.f2 != 0.0 ? y.getDataAt(j) * apprMeth.f2 : 0.0); } }/* approx1() */ diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CrossprodCommon.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CrossprodCommon.java index 3b4ca6fb6ce7420ac66d24bb5791682dd2dfa6c9..0b0041f6e72690ce43716b6a75d4daf6e94ccea0 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CrossprodCommon.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/CrossprodCommon.java @@ -44,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorToArray; /** * Implements the basic logic for {@code crossprod} and {@code tcrossprod}. Either the first matrix @@ -101,6 +102,7 @@ public abstract class CrossprodCommon extends RBuiltinNode.Arg2 { @Specialization(guards = "x.isMatrix()") protected RDoubleVector crossprodDoubleMatrix(RAbstractDoubleVector x, @SuppressWarnings("unused") RNull y, + @Cached("create()") VectorToArray vectorToArrayNode, @Cached("create()") GetDimAttributeNode getDimsNode, @Cached("create()") GetDimAttributeNode getResultDimsNode) { int[] xDims = getDimsNode.getDimensions(x); @@ -110,7 +112,8 @@ public abstract class CrossprodCommon extends RBuiltinNode.Arg2 { int yCols = transposeX ? xDims[1] : xDims[0]; RDoubleVector result = mirror( matMult.doubleMatrixMultiply(x, x, xRows, xCols, yRows, yCols, getXRowStride(xDims[0]), getXColStride(xDims[0]), getYRowStride(xDims[0]), getYColStride(xDims[0]), true), - getResultDimsNode); + getResultDimsNode, + vectorToArrayNode); return copyDimNames(x, x, result); } @@ -169,13 +172,13 @@ public abstract class CrossprodCommon extends RBuiltinNode.Arg2 { return result; } - private static RDoubleVector mirror(RDoubleVector result, GetDimAttributeNode getResultDimsNode) { + private static RDoubleVector mirror(RDoubleVector result, GetDimAttributeNode getResultDimsNode, VectorToArray vectorToArrayNode) { // Mirroring the result is not only good for performance, but it is also required to produce // the same result as GNUR. int[] resultDims = getResultDimsNode.getDimensions(result); assert result.isMatrix() && resultDims[0] == resultDims[1]; int size = resultDims[0]; - double[] data = result.getDataWithoutCopying(); + double[] data = vectorToArrayNode.getReadonly(result); for (int row = 0; row < size; row++) { int destIndex = row * size + row + 1; int sourceIndex = (row + 1) * size + row; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java index 271e4ac0bd5980f0966e60189d3f043000dab43e..b864672ccb2bf20855dffd1ce73434cc8524af59 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java @@ -28,8 +28,6 @@ import static com.oracle.truffle.r.nodes.builtin.CastBuilder.Predef.toBoolean; import static com.oracle.truffle.r.runtime.RVisibility.CUSTOM; import static com.oracle.truffle.r.runtime.builtins.RBehavior.COMPLEX; -import java.util.Arrays; - import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -145,11 +143,9 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta @Cached("createBinaryProfile()") ConditionProfile quoteProfile, @Cached("create()") BranchProfile containsRSymbolProfile, @Cached("createClassProfile()") ValueProfile frameAccessProfile) { - Object[] argValuesData = argsAsList.getDataWithoutCopying(); - Object[] argValues = argValuesData; + Object[] argValues = argsAsList.getDataCopy(); MaterializedFrame envFrame = env.getFrame(frameAccessProfile).materialize(); if (quoteProfile.profile(!quote)) { - argValues = Arrays.copyOf(argValuesData, argValuesData.length); for (int i = 0; i < argValues.length; i++) { Object arg = argValues[i]; if (arg instanceof RSymbol) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java index 0be5eb231324116a9ac7c2f4639f52f6a8a19496..a5b17287ed083383a96af787d33adb6a8cf64bbb 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/FileFunctions.java @@ -847,7 +847,7 @@ public class FileFunctions { if (elem instanceof String) { inputs[i] = new String[]{(String) elem}; } else if (elem instanceof RStringVector) { - inputs[i] = ((RStringVector) elem).getDataWithoutCopying(); + inputs[i] = ((RStringVector) elem).getReadonlyData(); } else { throw error(RError.Message.NON_STRING_ARG_TO_INTERNAL_PASTE); } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java index 48044327ef71962c683e810d0c5fffc8d4a0834e..8902a830b06761acf78c1589a33f1bd759f088f9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/LaFunctions.java @@ -32,6 +32,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; import java.lang.ref.SoftReference; import java.util.function.Function; +import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Cached; @@ -43,6 +44,7 @@ import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.GetDimNa import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetDimNamesAttributeNode; import com.oracle.truffle.r.nodes.attributes.SpecialAttributesFunctions.SetNamesAttributeNode; +import com.oracle.truffle.r.nodes.attributes.UnaryCopyAttributesNode; import com.oracle.truffle.r.nodes.builtin.NodeWithArgumentCasts.Casts; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.unary.CastDoubleNode; @@ -60,6 +62,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorToArray; import com.oracle.truffle.r.runtime.ffi.LapackRFFI; import com.oracle.truffle.r.runtime.ffi.RFFIFactory; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -317,20 +320,19 @@ public class LaFunctions { } @Specialization - protected RDoubleVector doQrCoefReal(RList qIn, RAbstractDoubleVector bIn, + protected RDoubleVector doQrCoefReal(RList qIn, RAbstractDoubleVector b, + @Cached("create()") VectorToArray qrToArrayNode, + @Cached("create()") VectorToArray tauToArrayNode, @Cached("create()") GetDimAttributeNode getBDimsNode, @Cached("create()") GetDimAttributeNode getQDimsNode, @Cached("create()") LapackRFFI.DormqrNode dormqrNode, @Cached("create()") LapackRFFI.DtrtrsNode dtrtrsNode) { - // If bIn was coerced this extra copy is unnecessary - RDoubleVector b = (RDoubleVector) bIn.copy(); - RDoubleVector qr = (RDoubleVector) qIn.getDataAt(0); RDoubleVector tau = (RDoubleVector) qIn.getDataAt(2); int k = tau.getLength(); - int[] bDims = getBDimsNode.getDimensions(bIn); + int[] bDims = getBDimsNode.getDimensions(b); int[] qrDims = getQDimsNode.getDimensions(qr); int n = qrDims[0]; if (bDims[0] != n) { @@ -339,10 +341,10 @@ public class LaFunctions { int nrhs = bDims[1]; double[] work = new double[1]; // qr and tau do not really need copying - double[] qrData = qr.getDataWithoutCopying(); - double[] tauData = tau.getDataWithoutCopying(); - // we work directly in the internal data of b - double[] bData = b.getDataWithoutCopying(); + double[] qrData = qrToArrayNode.getReadonly(qr); + double[] tauData = tauToArrayNode.getReadonly(tau); + // this will be the result, we are going to modify this array + double[] bData = b.materialize().getDataCopy(); // ask for optimal size of work array int info = dormqrNode.execute(SIDE, TRANS, n, nrhs, k, qrData, n, tauData, bData, n, work, -1); if (info < 0) { @@ -359,7 +361,7 @@ public class LaFunctions { throw error(Message.LAPACK_ERROR, info, "dtrtrs"); } // TODO check complete - return b; + return RDataFactory.createDoubleVector(bData, RDataFactory.INCOMPLETE_VECTOR); } } @@ -385,6 +387,7 @@ public class LaFunctions { @Specialization protected RList doDetGeReal(RAbstractDoubleVector aIn, boolean useLog, + @Cached("create()") VectorToArray vectorToArrayNode, @Cached("create()") GetDimAttributeNode getDimsNode, @Cached("create()") LapackRFFI.DgetrfNode dgetrfNode) { RDoubleVector a = (RDoubleVector) aIn.copy(); @@ -392,7 +395,7 @@ public class LaFunctions { int n = aDims[0]; int[] ipiv = new int[n]; double modulus = 0; - double[] aData = a.getDataWithoutCopying(); + double[] aData = vectorToArrayNode.getReadonly(a); int info = dgetrfNode.execute(n, n, aData, n, ipiv); int sign = 1; if (info < 0) { @@ -465,51 +468,63 @@ public class LaFunctions { @Specialization protected RDoubleVector doDetGeReal(RAbstractDoubleVector aIn, boolean piv, double tol, + @Cached("create()") UnaryCopyAttributesNode copyAttributesNode, @Cached("create()") GetDimAttributeNode getDimsNode, @Cached("create()") SetDimNamesAttributeNode setDimNamesNode, @Cached("create()") GetDimNamesAttributeNode getDimNamesNode, @Cached("create()") LapackRFFI.DpotrfNode dpotrfNode, @Cached("create()") LapackRFFI.DpstrfNode dpstrfNode) { - RDoubleVector a = (RDoubleVector) aIn.copy(); + double[] aData = aIn.materialize().getDataCopy(); int[] aDims = getDimsNode.getDimensions(aIn); int n = aDims[0]; int m = aDims[1]; - double[] aData = a.getDataWithoutCopying(); /* zero the lower triangle */ for (int j = 0; j < n; j++) { for (int i = j + 1; i < n; i++) { aData[i + n * j] = 0; } } + int info; if (noPivot.profile(!piv)) { info = dpotrfNode.execute('U', m, aData, m); if (info != 0) { - // TODO informative error message (aka GnuR) - throw error(Message.LAPACK_ERROR, info, "dpotrf"); + CompilerDirectives.transferToInterpreter(); + if (info > 0) { + throw error(Message.LAPACK_CHOL_NOT_POSITIVE_DEFINITE, info); + } else { + throw error(Message.LAPACK_ERROR, info, "dpotrf"); + } } - } else { - int[] ipiv = new int[m]; - double[] work = new double[2 * m]; - int[] rank = new int[1]; - info = dpstrfNode.execute('U', n, aData, n, ipiv, rank, tol, work); - if (info != 0) { - // TODO informative error message (aka GnuR) + return (RDoubleVector) copyAttributesNode.execute(RDataFactory.createDoubleVector(aData, RDataFactory.INCOMPLETE_VECTOR), aIn); + } + + int[] ipiv = new int[m]; + double[] work = new double[2 * m]; + int[] rank = new int[1]; + info = dpstrfNode.execute('U', n, aData, n, ipiv, rank, tol, work); + if (info != 0) { + CompilerDirectives.transferToInterpreter(); + if (info > 0) { + throw error(Message.LAPACK_CHOL_RANK_DEF_OR_INDEF, info); + } else { throw error(Message.LAPACK_ERROR, info, "dpotrf"); } - setPivotAttrNode.execute(a, RRuntime.asLogical(piv)); - setRankAttrNode.execute(a, rank[0]); - RList dn = getDimNamesNode.getDimNames(a); - if (dn != null && dn.getDataAt(0) != null) { - Object[] dn2 = new Object[m]; - // need to pivot the colnames - for (int i = 0; i < m; i++) { - dn2[i] = dn.getDataAt(ipiv[i] - 1); - } - setDimNamesNode.setDimNames(a, RDataFactory.createList(dn2)); + } + + RDoubleVector result = (RDoubleVector) copyAttributesNode.execute(RDataFactory.createDoubleVector(aData, RDataFactory.INCOMPLETE_VECTOR), aIn); + setPivotAttrNode.execute(result, RRuntime.asLogical(piv)); + setRankAttrNode.execute(result, rank[0]); + RList dn = getDimNamesNode.getDimNames(aIn); + if (dn != null && dn.getDataAt(0) != null) { + Object[] dn2 = new Object[m]; + // need to pivot the colnames + for (int i = 0; i < m; i++) { + dn2[i] = dn.getDataAt(ipiv[i] - 1); } + setDimNamesNode.setDimNames(result, RDataFactory.createList(dn2)); } - return a; + return result; } } @@ -684,9 +699,10 @@ public class LaFunctions { double[] avals; if (aDouble.isShared()) { avals = aCache.get(aDouble.getLength()); - System.arraycopy(aDouble.getDataWithoutCopying(), 0, avals, 0, n * p); + // TODO: fixme more efficient copying + System.arraycopy(aDouble.getDataCopy(), 0, avals, 0, n * p); } else { - avals = aDouble.getDataWithoutCopying(); + avals = aDouble.getDataCopy(); } int info = dgesvNode.execute(n, p, avals, n, ipiv, bData, n); if (info < 0) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java index 1321af4d0cebde99a813941ce1a431b947371831..bddcb8ae9ddcea89c572c7bd7d4363be1daf4b4c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/MatMult.java @@ -58,6 +58,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorToArray; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -150,6 +151,9 @@ public abstract class MatMult extends RBuiltinNode.Arg2 { private final BranchProfile incompleteProfile = BranchProfile.create(); @CompilationFinal private boolean seenLargeMatrix; + @Child private VectorToArray aToArrayNode = VectorToArray.create(); + @Child private VectorToArray bToArrayNode = VectorToArray.create(); + private RDoubleVector doubleMatrixMultiply(RAbstractDoubleVector a, RAbstractDoubleVector b, int aRows, int aCols, int bRows, int bCols) { return doubleMatrixMultiply(a, b, aRows, aCols, bRows, bCols, 1, aRows, 1, bRows, false); } @@ -176,8 +180,8 @@ public abstract class MatMult extends RBuiltinNode.Arg2 { if (aCols != bRows) { throw error(RError.Message.NON_CONFORMABLE_ARGS); } - double[] dataA = a.materialize().getDataWithoutCopying(); - double[] dataB = b.materialize().getDataWithoutCopying(); + double[] dataA = aToArrayNode.getReadonly(a.materialize()); + double[] dataB = bToArrayNode.getReadonly(b.materialize()); double[] result = new double[aRows * bCols]; if (!seenLargeMatrix && (aRows > BLOCK_SIZE || aCols > BLOCK_SIZE || bRows > BLOCK_SIZE || bCols > BLOCK_SIZE)) { diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java index c2ededbc786e8ec0835efb45edd40b2f4176718c..c7f2e016619af2ea22b6d472d57d526a009824c9 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Merge.java @@ -20,6 +20,7 @@ import static com.oracle.truffle.r.runtime.RError.Message.INVALID_LOGICAL; import static com.oracle.truffle.r.runtime.builtins.RBehavior.PURE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.INTERNAL; +import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.runtime.RError; @@ -30,6 +31,7 @@ import com.oracle.truffle.r.runtime.data.RIntVector; import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorToArray; /** * Note: invoked from merge.data.frame. @@ -79,7 +81,9 @@ public abstract class Merge extends RBuiltinNode.Arg4 { } @Specialization - RList merge(RAbstractIntVector xIndsAbstract, RAbstractIntVector yIndsAbstract, boolean allX, boolean allY) { + RList merge(RAbstractIntVector xIndsAbstract, RAbstractIntVector yIndsAbstract, boolean allX, boolean allY, + @Cached("create()") VectorToArray xIndsToArray, + @Cached("create()") VectorToArray yIndsToArray) { RIntVector xInds = xIndsAbstract.materialize(); RIntVector yInds = yIndsAbstract.materialize(); @@ -94,8 +98,8 @@ public abstract class Merge extends RBuiltinNode.Arg4 { for (int i = 0; i < ny; i++) { iy[i] = i + 1; } - int[] xIndsData = xInds.getDataWithoutCopying(); - int[] yIndsData = yInds.getDataWithoutCopying(); + int[] xIndsData = xIndsToArray.getReadonly(xInds); + int[] yIndsData = yIndsToArray.getReadonly(yInds); isortWithIndex(xIndsData, ix, nx); isortWithIndex(yIndsData, iy, ny); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java index 55a76080cb08370639afb5555aaf5e0a806f9f3f..4db45a113dcfb5ff6de7ba0969a2e32853477643 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Paste.java @@ -152,7 +152,7 @@ public abstract class Paste extends RBuiltinNode.Arg3 { int emptyCnt = 0; for (int i = 0; i < length; i++) { Object element = values.getDataAt(i); - String[] array = castCharacterVector(frame, element).materialize().getDataWithoutCopying(); + String[] array = castCharacterVector(frame, element).materialize().getReadonlyData(); maxLength = Math.max(maxLength, array.length); if (array.length == 0) { converted[i] = ONE_EMPTY_STRING; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java index 0069d9e8851782c95f4c4ac00845a5c264c49550..57d232e5c9617d276e19f65246073deb5ff2b49d 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Split.java @@ -44,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractListVector; import com.oracle.truffle.r.runtime.data.model.RAbstractLogicalVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector; /** * The {@code split} internal. Internal version of 'split' is invoked from 'split.default' function @@ -63,6 +64,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { @SuppressWarnings("unused") private final ConditionProfile noStringLevels = ConditionProfile.createBinaryProfile(); private final ConditionProfile namesProfile = ConditionProfile.createBinaryProfile(); + @Child private AccessVector.Int factorAccess = new AccessVector.Int(); private static final int INITIAL_SIZE = 5; private static final int SCALE_FACTOR = 2; @@ -73,7 +75,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { @Specialization protected RList split(RAbstractListVector x, RAbstractIntVector f) { - int[] factor = f.materialize().getDataWithoutCopying(); + Object fStore = factorAccess.init(f); RStringVector names = getLevelNode.execute(f); final int nLevels = getNLevels(names); @@ -85,8 +87,9 @@ public abstract class Split extends RBuiltinNode.Arg2 { } // perform split - for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { - int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + int factorLen = f.getLength(); + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factorLen)) { + int resultIndex = factorAccess.getDataAt(f, fStore, fi) - 1; // a factor is a 1-based int vector Object[] collect = collectResults[resultIndex]; if (collect.length == collectResultSize[resultIndex]) { collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR); @@ -96,7 +99,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { } Object[] results = new Object[nLevels]; - RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize); + RStringVector[] resultNames = getNames(x, f, fStore, nLevels, collectResultSize); for (int i = 0; i < nLevels; i++) { results[i] = RDataFactory.createList(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), (resultNames != null) ? resultNames[i] : null); @@ -106,7 +109,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { @Specialization protected RList split(RAbstractIntVector x, RAbstractIntVector f) { - int[] factor = f.materialize().getDataWithoutCopying(); + Object fStore = factorAccess.init(f); RStringVector names = getLevelNode.execute(f); final int nLevels = getNLevels(names); @@ -118,8 +121,9 @@ public abstract class Split extends RBuiltinNode.Arg2 { } // perform split - for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { - int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + int factorLen = f.getLength(); + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factorLen)) { + int resultIndex = factorAccess.getDataAt(f, fStore, fi) - 1; // a factor is a 1-based int vector int[] collect = collectResults[resultIndex]; if (collect.length == collectResultSize[resultIndex]) { collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR); @@ -129,7 +133,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { } Object[] results = new Object[nLevels]; - RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize); + RStringVector[] resultNames = getNames(x, f, fStore, nLevels, collectResultSize); for (int i = 0; i < nLevels; i++) { results[i] = RDataFactory.createIntVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), x.isComplete(), (resultNames != null) ? resultNames[i] : null); @@ -139,7 +143,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { @Specialization protected RList split(RAbstractDoubleVector x, RAbstractIntVector f) { - int[] factor = f.materialize().getDataWithoutCopying(); + Object fStore = factorAccess.init(f); RStringVector names = getLevelNode.execute(f); final int nLevels = getNLevels(names); @@ -151,8 +155,9 @@ public abstract class Split extends RBuiltinNode.Arg2 { } // perform split - for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { - int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + int factorLen = f.getLength(); + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factorLen)) { + int resultIndex = factorAccess.getDataAt(f, fStore, fi) - 1; // a factor is a 1-based int vector double[] collect = collectResults[resultIndex]; if (collect.length == collectResultSize[resultIndex]) { collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR); @@ -162,7 +167,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { } Object[] results = new Object[nLevels]; - RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize); + RStringVector[] resultNames = getNames(x, f, fStore, nLevels, collectResultSize); for (int i = 0; i < nLevels; i++) { results[i] = RDataFactory.createDoubleVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), RDataFactory.COMPLETE_VECTOR, (resultNames != null) ? resultNames[i] : null); @@ -172,7 +177,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { @Specialization protected RList split(RAbstractStringVector x, RAbstractIntVector f) { - int[] factor = f.materialize().getDataWithoutCopying(); + Object fStore = factorAccess.init(f); RStringVector names = getLevelNode.execute(f); final int nLevels = getNLevels(names); @@ -184,8 +189,9 @@ public abstract class Split extends RBuiltinNode.Arg2 { } // perform split - for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { - int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + int factorLen = f.getLength(); + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factorLen)) { + int resultIndex = factorAccess.getDataAt(f, fStore, fi) - 1; // a factor is a 1-based int vector String[] collect = collectResults[resultIndex]; if (collect.length == collectResultSize[resultIndex]) { collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR); @@ -195,7 +201,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { } Object[] results = new Object[nLevels]; - RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize); + RStringVector[] resultNames = getNames(x, f, fStore, nLevels, collectResultSize); for (int i = 0; i < nLevels; i++) { results[i] = RDataFactory.createStringVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), RDataFactory.COMPLETE_VECTOR, (resultNames != null) ? resultNames[i] : null); @@ -205,7 +211,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { @Specialization protected RList split(RAbstractLogicalVector x, RAbstractIntVector f) { - int[] factor = f.materialize().getDataWithoutCopying(); + Object fStore = factorAccess.init(f); RStringVector names = getLevelNode.execute(f); final int nLevels = getNLevels(names); @@ -217,8 +223,9 @@ public abstract class Split extends RBuiltinNode.Arg2 { } // perform split - for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { - int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + int factorLen = f.getLength(); + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factorLen)) { + int resultIndex = factorAccess.getDataAt(f, fStore, fi) - 1; // a factor is a 1-based int vector byte[] collect = collectResults[resultIndex]; if (collect.length == collectResultSize[resultIndex]) { collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR); @@ -228,7 +235,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { } Object[] results = new Object[nLevels]; - RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize); + RStringVector[] resultNames = getNames(x, f, fStore, nLevels, collectResultSize); for (int i = 0; i < nLevels; i++) { results[i] = RDataFactory.createLogicalVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), x.isComplete(), (resultNames != null) ? resultNames[i] : null); @@ -238,7 +245,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { @Specialization protected RList split(RRawVector x, RAbstractIntVector f) { - int[] factor = f.materialize().getDataWithoutCopying(); + Object fStore = factorAccess.init(f); RStringVector names = getLevelNode.execute(f); final int nLevels = getNLevels(names); @@ -250,8 +257,9 @@ public abstract class Split extends RBuiltinNode.Arg2 { } // perform split - for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { - int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + int factorLen = f.getLength(); + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factorLen)) { + int resultIndex = factorAccess.getDataAt(f, fStore, fi) - 1; // a factor is a 1-based int vector byte[] collect = collectResults[resultIndex]; if (collect.length == collectResultSize[resultIndex]) { collectResults[resultIndex] = Arrays.copyOf(collect, collect.length * SCALE_FACTOR); @@ -261,7 +269,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { } Object[] results = new Object[nLevels]; - RStringVector[] resultNames = getNames(x, factor, nLevels, collectResultSize); + RStringVector[] resultNames = getNames(x, f, fStore, nLevels, collectResultSize); for (int i = 0; i < nLevels; i++) { results[i] = RDataFactory.createRawVector(Arrays.copyOfRange(collectResults[i], 0, collectResultSize[i]), (resultNames != null) ? resultNames[i] : null); @@ -269,7 +277,7 @@ public abstract class Split extends RBuiltinNode.Arg2 { return RDataFactory.createList(results, names); } - private RStringVector[] getNames(RAbstractVector x, int[] factor, int nLevels, int[] collectResultSize) { + private RStringVector[] getNames(RAbstractVector x, RAbstractIntVector factor, Object fStore, int nLevels, int[] collectResultSize) { RStringVector xNames = getNamesNode.getNames(x); if (namesProfile.profile(xNames != null)) { String[][] namesArr = new String[nLevels][]; @@ -277,8 +285,9 @@ public abstract class Split extends RBuiltinNode.Arg2 { for (int i = 0; i < nLevels; i++) { namesArr[i] = new String[collectResultSize[i]]; } - for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factor.length)) { - int resultIndex = factor[fi] - 1; // a factor is a 1-based int vector + int factorLen = factor.getLength(); + for (int i = 0, fi = 0; i < x.getLength(); ++i, fi = Utils.incMod(fi, factorLen)) { + int resultIndex = factorAccess.getDataAt(factor, fStore, fi) - 1; // a factor is a 1-based int vector namesArr[resultIndex][resultNamesIdxs[resultIndex]++] = xNames.getDataAt(i); } RStringVector[] resultNames = new RStringVector[nLevels]; diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java index 00fbadeb93c2ed6e3bb8c7923f10a38ebf9865c7..aa0cd2a7d0bd8017a4615264e7c6ba9686a6b60c 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Sum.java @@ -42,6 +42,7 @@ import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.builtins.RBuiltin; import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames; import com.oracle.truffle.r.runtime.data.RDoubleVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorToArray; import com.oracle.truffle.r.runtime.ffi.MiscRFFI; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -74,6 +75,7 @@ public abstract class Sum extends RBuiltinNode.Arg2 { @Specialization(guards = {"FULL_PRECISION", "args.getLength() == 1", "isRDoubleVector(args.getArgument(0))", "naRm == cachedNaRm"}) protected double sumLengthOneRDoubleVector(RArgsValuesAndNames args, @SuppressWarnings("unused") boolean naRm, + @Cached("create()") VectorToArray vectorToArrayNode, @Cached("naRm") boolean cachedNaRm, @Cached("create()") VectorLengthProfile lengthProfile, @Cached("createCountingProfile()") LoopConditionProfile loopProfile, @@ -84,7 +86,7 @@ public abstract class Sum extends RBuiltinNode.Arg2 { int length = lengthProfile.profile(vector.getLength()); if (needsExactSumProfile.profile(length >= 3)) { - return exactSumNode.execute(vector.getDataWithoutCopying(), !vector.isComplete(), cachedNaRm); + return exactSumNode.execute(vectorToArrayNode.getReadonly(vector), !vector.isComplete(), cachedNaRm); } else { na.enable(vector); loopProfile.profileCounted(length); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java index 36cf01ffbe3ead88ac0e13686cea150534705af0..dee733d610767ce17f9da037ee79639076c60102 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/infix/UpdateSubscript.java @@ -83,7 +83,7 @@ abstract class UpdateSubscriptSpecial extends SubscriptSpecialCommon { @Specialization(guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index)", "isSingleElement(value)"}) protected static Object set(RList list, int index, Object value) { - list.setDataAt(list.getInternalStore(), index - 1, value); + list.setDataAt(index - 1, value); return list; } @@ -130,7 +130,7 @@ abstract class UpdateSubscriptSpecial2 extends SubscriptSpecial2Common { @Specialization(guards = {"simpleVector(list)", "!list.isShared()", "isValidIndex(list, index1, index2)", "isSingleElement(value)"}) protected Object set(RList list, int index1, int index2, Object value) { - list.setDataAt(list.getInternalStore(), matrixIndex(list, index1, index2), value); + list.setDataAt(matrixIndex(list, index1, index2), value); return list; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java index 62a9cba7c6bf912bc59c8a61e5c4c5c4e0abb916..4a3d4606b1ef7486d3927e80e7847a1b1d3013f0 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/S3FunctionLookupNode.java @@ -11,7 +11,6 @@ package com.oracle.truffle.r.nodes.function; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import com.oracle.truffle.api.CompilerDirectives; @@ -160,7 +159,11 @@ public abstract class S3FunctionLookupNode extends RBaseNode { if (i == 0) { dispatchType = type.copyResized(type.getLength(), false); } else { - RStringVector clazz = RDataFactory.createStringVector(Arrays.copyOfRange(type.getDataWithoutCopying(), i, type.getLength()), true); + String[] clazzData = new String[type.getLength() - i]; + for (int j = i; j < type.getLength(); j++) { + clazzData[j - i] = type.getDataAt(j); + } + RStringVector clazz = RDataFactory.createStringVector(clazzData, true); clazz.setAttr(RRuntime.PREVIOUS_ATTR_KEY, type.copyResized(type.getLength(), false)); dispatchType = clazz; } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java index 28fe8a13b4c821b874880fe25407165efb736743..686c14ef60b48334fc09d3341535f15a69b03d97 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/RFactorNodes.java @@ -28,10 +28,10 @@ import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.profiles.BranchProfile; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.nodes.attributes.GetFixedAttributeNode; +import com.oracle.truffle.r.nodes.function.opt.UpdateShareableChildValueNode; import com.oracle.truffle.r.nodes.unary.CastStringNode; import com.oracle.truffle.r.nodes.unary.CastStringNodeGen; import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.data.RDataFactory; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; @@ -71,6 +71,7 @@ public final class RFactorNodes { public static final class GetLevels extends Node { @Child private CastStringNode castString; @Child private GetFixedAttributeNode attrAccess = GetFixedAttributeNode.create(RRuntime.LEVELS_ATTR_KEY); + @Child UpdateShareableChildValueNode updateAttrValue = UpdateShareableChildValueNode.create(); private final BranchProfile notVectorBranch = BranchProfile.create(); private final ConditionProfile nonScalarLevels = ConditionProfile.createBinaryProfile(); @@ -85,7 +86,7 @@ public final class RFactorNodes { * cast is done. May return null, if the 'levels' attribute is not present. */ public RStringVector execute(RAbstractIntVector factor) { - Object attr = attrAccess.execute(factor.getAttributes()); + Object attr = updateAttrValue.updateState(factor, attrAccess.execute(factor.getAttributes())); // Convert scalars to vector if necessary RAbstractVector vec; @@ -110,7 +111,8 @@ public final class RFactorNodes { castString = insert(CastStringNodeGen.create(false, false, false)); } RStringVector slevels = ((RAbstractStringVector) castString.executeString(vec)).materialize(); - return RDataFactory.createStringVector(slevels.getDataWithoutCopying(), RDataFactory.COMPLETE_VECTOR); + assert slevels.isTemporary() : "cast should create a new tmp vector since !(vec instanceof RStringVector)"; + return slevels; } } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java index 369ea71c7184823354b34bb077956e5a4d42d99a..b6ecdaa12c7c2a9938bc485faa4bbb4635a595e2 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/unary/UnaryArithmeticReduceNode.java @@ -45,6 +45,7 @@ import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.RStringVector; import com.oracle.truffle.r.runtime.data.RTypes; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector; import com.oracle.truffle.r.runtime.interop.ForeignArray2R; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.BinaryArithmetic; @@ -201,15 +202,16 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { } @Specialization - protected Object doIntVector(RIntVector operand, boolean naRm, boolean finite) { + protected int doIntVector(RIntVector operand, boolean naRm, boolean finite, + @Cached("new()") AccessVector.Int access) { RBaseNode.reportWork(this, operand.getLength()); boolean profiledNaRm = naRmProfile.profile(naRm || finite); int result = semantics.getIntStart(); na.enable(operand); int opCount = 0; - int[] data = operand.getDataWithoutCopying(); + Object store = access.init(operand); for (int i = 0; i < operand.getLength(); i++) { - int d = data[i]; + int d = access.getDataAt(operand, store, i); if (na.check(d)) { if (profiledNaRm) { continue; @@ -236,6 +238,7 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { @Specialization protected double doDoubleVector(RDoubleVector operand, boolean naRm, boolean finite, + @Cached("new()") AccessVector.Double access, @Cached("createBinaryProfile()") ConditionProfile finiteProfile, @Cached("createBinaryProfile()") ConditionProfile isInfiniteProfile) { RBaseNode.reportWork(this, operand.getLength()); @@ -244,9 +247,9 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { double result = semantics.getDoubleStart(); na.enable(operand); int opCount = 0; - double[] data = operand.getDataWithoutCopying(); + Object store = access.init(operand); for (int i = 0; i < operand.getLength(); i++) { - double d = data[i]; + double d = access.getDataAt(operand, store, i); if (na.checkNAorNaN(d)) { if (profiledNaRm) { continue; // ignore NA/NaN @@ -271,15 +274,16 @@ public abstract class UnaryArithmeticReduceNode extends RBaseNode { } @Specialization - protected Object doLogicalVector(RLogicalVector operand, boolean naRm, @SuppressWarnings("unused") boolean finite) { + protected int doLogicalVector(RLogicalVector operand, boolean naRm, @SuppressWarnings("unused") boolean finite, + @Cached("new()") AccessVector.Logical access) { RBaseNode.reportWork(this, operand.getLength()); boolean profiledNaRm = naRmProfile.profile(naRm); int result = semantics.getIntStart(); na.enable(operand); int opCount = 0; - byte[] data = operand.getDataWithoutCopying(); + Object store = access.init(operand); for (int i = 0; i < operand.getLength(); i++) { - byte d = data[i]; + byte d = access.getDataAt(operand, store, i); if (na.check(d)) { if (profiledNaRm) { continue; 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 6dedde1535352ed78b38f7aa66e496d2e6ccf3ad..d8a18bfca7d19bc019bea4df248d9ef5acf477ef 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 @@ -76,7 +76,8 @@ public final class ArgumentsSignature implements Iterable<String> { * converted to {@code null} value. */ public static ArgumentsSignature fromNamesAttribute(RStringVector names) { - return names == null ? null : get(names.getDataWithoutCopying(), true); + // Note: get makes a defensive copy of names anyway + return names == null ? null : get(names.getReadonlyData(), true); } @TruffleBoundary 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 c0a021efa81949f83664786c0f8bb8d7fac9ff8f..c1436c21875cad6f14b507610bc5423a9c86e7e0 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 @@ -573,6 +573,8 @@ public final class RError extends RuntimeException implements TruffleException { LAPACK_INVALID_VALUE("argument %d of Lapack routine %s had invalid value"), LAPACK_ZERO_INVERSE("element (%d, %d) is zero, so the inverse cannot be computed"), LAPACK_EXACTLY_SINGULAR("Lapack routine %s: system is exactly singular: U[%d,%d] = 0"), + LAPACK_CHOL_NOT_POSITIVE_DEFINITE("the leading minor of order %d is not positive definite"), + LAPACK_CHOL_RANK_DEF_OR_INDEF("the matrix is either rank-deficient or indefinite"), SYSTEM_COMP_SINGULAR("system is computationally singular: reciprocal condition number = %g"), RHS_SHOULD_HAVE_ROWS("right-hand side should have %d not %d rows"), SAME_NUMBER_ROWS("'%s' and '%s' must have the same number of rows"), diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java index 00ed14aecea4faa1e75f344e508768d4e918f48c..93c1cab891f025f44824415e9707b8aca331a55f 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java @@ -318,7 +318,7 @@ public class RSerialize { @TruffleBoundary public static Object unserialize(RAbstractRawVector data) { - byte[] buffer = data.materialize().getDataWithoutCopying(); + byte[] buffer = data.materialize().getReadonlyData(); try { return new Input(new ByteArrayInputStream(buffer)).unserialize(); } catch (IOException e) { @@ -1520,10 +1520,10 @@ public class RSerialize { * matter, so we use the "frame" form, which is a pairlist. tag is * binding name, car is binding value */ - String[] bindings = env.ls(true, null, false).getDataWithoutCopying(); - for (String binding : bindings) { - Object value = getValueIgnoreActiveBinding(env.getFrame(), binding); - writePairListEntry(binding, value); + RStringVector bindings = env.ls(true, null, false); + for (int i = 0; i < bindings.getLength(); i++) { + Object value = getValueIgnoreActiveBinding(env.getFrame(), bindings.getDataAt(i)); + writePairListEntry(bindings.getDataAt(i), value); } terminatePairList(); writeItem(RNull.instance); // hashtab @@ -1631,7 +1631,7 @@ public class RSerialize { case RAWSXP: { RRawVector raw = (RRawVector) obj; - byte[] data = raw.getDataWithoutCopying(); + byte[] data = raw.getReadonlyData(); stream.writeInt(data.length); stream.writeRaw(data); break; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java index 341f5e16bfe88ba760be8ebedbc9fc0c6a7cd6d2..6b3fdc386347450f0f2eaafbb1ec09508d14ec23 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/TextConnections.java @@ -235,9 +235,9 @@ public class TextConnections { } void appendData(String[] appendedData) { - String[] existingData = textVec != null ? textVec.getDataWithoutCopying() : new String[0]; String[] updateData = appendedData; - if (existingData.length > 0) { + if (textVec != null && textVec.getLength() > 0) { + String[] existingData = textVec.getReadonlyData(); updateData = new String[existingData.length + appendedData.length]; System.arraycopy(existingData, 0, updateData, 0, existingData.length); System.arraycopy(appendedData, 0, updateData, existingData.length, appendedData.length); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java index 8822d7b40175edbb0e8a889a5cde0896b4d3ec09..f8c9740e0670919634015cd2f65032f6d833872d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/NativeDataAccess.java @@ -74,14 +74,38 @@ class UnsafeAdapter { } } +/** + * Provides API to work with objects returned by {@link RObject#getNativeMirror()}. The native + * mirror represents what on the native side is SEXP, but not directly the raw data of the vector. + * Use {@link #asPointer(Object)} to assign a native mirror object to the given vector. The raw data + * in native memory for a vector that already has a native mirror object assigned can be allocated + * using e.g. {@link #allocateNativeContents(RIntVector, int[], int)} . + * + * There is a registry of weak references to all native mirrors ever assigned to some vector object. + * We use the finalizer to free the native memory (if allocated). + */ public final class NativeDataAccess { private NativeDataAccess() { // no instances } + public static boolean isNativeMirror(Object o) { + return o instanceof NativeMirror; + } + private static final class NativeMirror { + /** + * ID of the mirror, this will be used as the value for SEXP. When native up-calls to Java, + * we get this value and find the corresponding object for it. + */ private final long id; + /** + * Address of the start of the native memory array. Zero if not allocated yet. + */ private long dataAddress; + /** + * Length of the native data array. E.g. for CHARSXP this is not just the length of the Java String. + */ private long length; NativeMirror() { @@ -141,6 +165,9 @@ public final class NativeDataAccess { }); } + /** + * Assigns a native mirror object to the given RObject object. + */ public static long asPointer(Object arg) { if (arg instanceof RObject) { RObject obj = (RObject) arg; @@ -161,6 +188,9 @@ public final class NativeDataAccess { return obj; } + /** + * For given native mirror ID returns the Java side object (vector). + */ public static Object lookup(long address) { WeakReference<RObject> reference = nativeMirrors.get(address); if (reference == null) { @@ -175,6 +205,72 @@ public final class NativeDataAccess { return result; } + // methods operating on the native mirror object directly: + + public static int getIntNativeMirrorData(Object nativeMirror, int index) { + long address = ((NativeMirror) nativeMirror).dataAddress; + assert address != 0; + assert index < ((NativeMirror) nativeMirror).length; + return UnsafeAdapter.UNSAFE.getInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE); + } + + public static double getDoubleNativeMirrorData(Object nativeMirror, int index) { + long address = ((NativeMirror) nativeMirror).dataAddress; + assert address != 0; + assert index < ((NativeMirror) nativeMirror).length; + return UnsafeAdapter.UNSAFE.getDouble(address + index * Unsafe.ARRAY_DOUBLE_INDEX_SCALE); + } + + public static byte getLogicalNativeMirrorData(Object nativeMirror, int index) { + long address = ((NativeMirror) nativeMirror).dataAddress; + assert address != 0; + assert index < ((NativeMirror) nativeMirror).length; + return RRuntime.int2logical(UnsafeAdapter.UNSAFE.getInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE)); + } + + public static byte getRawNativeMirrorData(Object nativeMirror, int index) { + long address = ((NativeMirror) nativeMirror).dataAddress; + assert address != 0; + assert index < ((NativeMirror) nativeMirror).length; + return UnsafeAdapter.UNSAFE.getByte(address + index * Unsafe.ARRAY_BYTE_INDEX_SCALE); + } + + public static void setNativeMirrorData(Object nativeMirror, int index, double value) { + long address = ((NativeMirror) nativeMirror).dataAddress; + assert address != 0; + assert index < ((NativeMirror) nativeMirror).length; + UnsafeAdapter.UNSAFE.putDouble(address + index * Unsafe.ARRAY_DOUBLE_INDEX_SCALE, value); + } + + public static double[] copyDoubleNativeData(Object mirrorObj) { + NativeMirror mirror = (NativeMirror) mirrorObj; + long address = mirror.dataAddress; + assert address != 0; + double[] data = new double[(int) mirror.length]; + UnsafeAdapter.UNSAFE.copyMemory(null, address, data, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, data.length * Unsafe.ARRAY_DOUBLE_INDEX_SCALE); + return data; + } + + public static int[] copyIntNativeData(Object mirrorObj) { + NativeMirror mirror = (NativeMirror) mirrorObj; + long address = mirror.dataAddress; + assert address != 0; + int[] data = new int[(int) mirror.length]; + UnsafeAdapter.UNSAFE.copyMemory(null, address, data, Unsafe.ARRAY_INT_BASE_OFFSET, data.length * Unsafe.ARRAY_INT_INDEX_SCALE); + return data; + } + + public static byte[] copyByteNativeData(Object mirrorObj) { + NativeMirror mirror = (NativeMirror) mirrorObj; + long address = mirror.dataAddress; + assert address != 0; + byte[] data = new byte[(int) mirror.length]; + UnsafeAdapter.UNSAFE.copyMemory(null, address, data, Unsafe.ARRAY_BYTE_BASE_OFFSET, data.length * Unsafe.ARRAY_BYTE_INDEX_SCALE); + return data; + } + + // methods operating on vectors that may have a native mirror assigned: + private static final Assumption noIntNative = Truffle.getRuntime().createAssumption(); private static final Assumption noLogicalNative = Truffle.getRuntime().createAssumption(); private static final Assumption noDoubleNative = Truffle.getRuntime().createAssumption(); @@ -186,9 +282,7 @@ public final class NativeDataAccess { if (noIntNative.isValid() || data != null) { return data[index]; } else { - long address = ((NativeMirror) vector.getNativeMirror()).dataAddress; - assert address != 0; - return UnsafeAdapter.UNSAFE.getInt(address + index * Unsafe.ARRAY_INT_INDEX_SCALE); + return getIntNativeMirrorData(vector.getNativeMirror(), index); } } @@ -242,9 +336,7 @@ public final class NativeDataAccess { if (noRawNative.isValid() || data != null) { return data[index]; } else { - long address = ((NativeMirror) vector.getNativeMirror()).dataAddress; - assert address != 0; - return UnsafeAdapter.UNSAFE.getByte(address + index * Unsafe.ARRAY_BYTE_INDEX_SCALE); + return getRawNativeMirrorData(vector.getNativeMirror(), index); } } @@ -270,9 +362,7 @@ public final class NativeDataAccess { if (noDoubleNative.isValid() || data != null) { return data[index]; } else { - long address = ((NativeMirror) vector.getNativeMirror()).dataAddress; - assert address != 0; - return UnsafeAdapter.UNSAFE.getDouble(address + index * Unsafe.ARRAY_INT_INDEX_SCALE); + return getDoubleNativeMirrorData(vector.getNativeMirror(), index); } } @@ -288,9 +378,7 @@ public final class NativeDataAccess { if (noDoubleNative.isValid() || data != null) { data[index] = value; } else { - long address = ((NativeMirror) vector.getNativeMirror()).dataAddress; - assert address != 0; - UnsafeAdapter.UNSAFE.putDouble(address + index * Unsafe.ARRAY_INT_INDEX_SCALE, value); + setNativeMirrorData(vector.getNativeMirror(), index, value); } } @@ -300,8 +388,8 @@ public final class NativeDataAccess { } else { long address = ((NativeMirror) vector.getNativeMirror()).dataAddress; assert address != 0; - return RComplex.valueOf(UnsafeAdapter.UNSAFE.getDouble(address + index * 2 * Unsafe.ARRAY_INT_INDEX_SCALE), - UnsafeAdapter.UNSAFE.getDouble(address + (index * 2 + 1) * Unsafe.ARRAY_INT_INDEX_SCALE)); + return RComplex.valueOf(UnsafeAdapter.UNSAFE.getDouble(address + index * 2 * Unsafe.ARRAY_DOUBLE_INDEX_SCALE), + UnsafeAdapter.UNSAFE.getDouble(address + (index * 2 + 1) * Unsafe.ARRAY_DOUBLE_INDEX_SCALE)); } } @@ -320,8 +408,8 @@ public final class NativeDataAccess { } else { long address = ((NativeMirror) vector.getNativeMirror()).dataAddress; assert address != 0; - UnsafeAdapter.UNSAFE.putDouble(address + index * 2 * Unsafe.ARRAY_INT_INDEX_SCALE, re); - UnsafeAdapter.UNSAFE.putDouble(address + (index * 2 + 1) * Unsafe.ARRAY_INT_INDEX_SCALE, im); + UnsafeAdapter.UNSAFE.putDouble(address + index * 2 * Unsafe.ARRAY_DOUBLE_INDEX_SCALE, re); + UnsafeAdapter.UNSAFE.putDouble(address + (index * 2 + 1) * Unsafe.ARRAY_DOUBLE_INDEX_SCALE, im); } } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java index 207dc2d50e3bc6777cdbb15f068a4d92ad1455f1..d84e75629f1a8fbc967095b3a3efc5c1a45f1a93 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplexVector.java @@ -55,6 +55,11 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract return new RComplexVector(Arrays.copyOf(data, data.length), this.isComplete()); } + @Override + public double[] getInternalManagedData() { + return data; + } + @Override public double[] getInternalStore() { return data; @@ -119,12 +124,8 @@ public final class RComplexVector extends RVector<double[]> implements RAbstract return Arrays.copyOf(data, data.length); } - /** - * Intended for external calls where a copy is not needed. WARNING: think carefully before using - * this method rather than {@link #getDataCopy()}. - */ @Override - public double[] getDataWithoutCopying() { + public double[] getReadonlyData() { assert data != null; return data; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java index d1a8ced337293f4efa4ddd8a33aacd444a9308f2..b14fb519c88aad3e608ee5b598334bd6090f1998 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDoubleVector.java @@ -72,6 +72,11 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD return new RDoubleVector(Arrays.copyOf(data, data.length), this.isComplete()); } + @Override + public double[] getInternalManagedData() { + return data; + } + @Override public double[] getInternalStore() { return data; @@ -135,12 +140,8 @@ public final class RDoubleVector extends RVector<double[]> implements RAbstractD return Arrays.copyOf(data, data.length); } - /** - * Intended for external calls where a copy is not needed. WARNING: think carefully before using - * this method rather than {@link #getDataCopy()}. - */ @Override - public double[] getDataWithoutCopying() { + public double[] getReadonlyData() { assert data != null; return data; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java index 42be6bdb5eeffc6592a4ce953a8da75b3f0c7aa5..bb21a383242e321095bbf9ff51512b3a8c19ef0e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RIntVector.java @@ -136,12 +136,13 @@ public final class RIntVector extends RVector<int[]> implements RAbstractIntVect return Arrays.copyOf(data, data.length); } - /** - * Intended for external calls where a copy is not needed. WARNING: think carefully before using - * this method rather than {@link #getDataCopy()}. - */ @Override - public int[] getDataWithoutCopying() { + public int[] getInternalManagedData() { + return data; + } + + @Override + public int[] getReadonlyData() { assert data != null; return data; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java index 305e605d2621b422c7365abfb63dfe30646abe25..73cb3411ce64c3a449726641d3dc8242367315de 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RListBase.java @@ -109,15 +109,23 @@ public abstract class RListBase extends RVector<Object[]> implements RAbstractLi return true; } + @Override + public Object[] getInternalManagedData() { + return data; + } + /** - * Intended for external calls where a copy is not needed. WARNING: think carefully before using - * this method rather than {@link #getDataCopy()}. + * Unlike atomic vectors, {@code RList} cannot have a native memory mirror, therefore this is a + * fast operation. */ - @Override - public final Object[] getDataWithoutCopying() { + public final Object[] getReadonlyData() { return data; } + public final Object[] getDataWithoutCopying() { + return getReadonlyData(); + } + @Override public final Object[] getDataCopy() { Object[] copy = new Object[data.length]; diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java index 14902799427cd5c0566c906eb610bbb48da21b92..0eee40bd3acf6cad1eb87e06bf94fb9131bcee43 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogicalVector.java @@ -68,6 +68,11 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo } } + @Override + public byte[] getInternalManagedData() { + return data; + } + @Override public byte[] getInternalStore() { assert data != null; @@ -187,12 +192,8 @@ public final class RLogicalVector extends RVector<byte[]> implements RAbstractLo return Arrays.copyOf(data, data.length); } - /** - * Intended for external calls where a copy is not needed. WARNING: think carefully before using - * this method rather than {@link #getDataCopy()}. - */ @Override - public byte[] getDataWithoutCopying() { + public byte[] getReadonlyData() { assert data != null; return data; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java index fb6529e506d085bd21d1147de19e3a4a299fe00f..5771c618e3554fdbe2ce03fc7564a3a2245d9deb 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRawVector.java @@ -66,6 +66,11 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec } } + @Override + public byte[] getInternalManagedData() { + return data; + } + @Override public byte[] getInternalStore() { return data; @@ -120,12 +125,8 @@ public final class RRawVector extends RVector<byte[]> implements RAbstractRawVec return Arrays.copyOf(data, data.length); } - /** - * Intended for external calls where a copy is not needed. WARNING: think carefully before using - * this method rather than {@link #getDataCopy()}. - */ @Override - public byte[] getDataWithoutCopying() { + public byte[] getReadonlyData() { assert data != null; return data; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java index 7fb2ffdad2bb3f978fda84fe63838ba6e1095ef1..b0e42cf3ac099c4b0717cf5404b37f71613974ab 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RStringVector.java @@ -61,6 +61,11 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS } } + @Override + public String[] getInternalManagedData() { + return data; + } + @Override public String[] getInternalStore() { return data; @@ -108,12 +113,8 @@ public final class RStringVector extends RVector<String[]> implements RAbstractS return result; } - /** - * Intended for external calls where a copy is not needed. WARNING: think carefully before using - * this method rather than {@link #getDataCopy()}. - */ @Override - public String[] getDataWithoutCopying() { + public String[] getReadonlyData() { return data; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java index 846193104cbe95021aa0b18859b180ce2e6c6235..16e53cf26ee6b3014a75e21ccc4c48369289a3bf 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RVector.java @@ -39,6 +39,7 @@ import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; import com.oracle.truffle.r.runtime.data.model.RAbstractVector; +import com.oracle.truffle.r.runtime.data.nodes.VectorToArray; import com.oracle.truffle.r.runtime.nodes.RBaseNode; import com.oracle.truffle.r.runtime.ops.na.NACheck; @@ -84,35 +85,52 @@ public abstract class RVector<ArrayT> extends RSharingAttributeStorage implement } } + /** + * Returns the internal data Java array for read only purposes only or {@code null} if the + * vector has been materialized to native mirror and it does not hold managed data anymore. This + * method is for only very specific purposes especially of {@link VectorToArray}. + * + * @return vector data + */ + public abstract ArrayT getInternalManagedData(); + /** * Intended for external calls where a mutable copy is needed. */ public abstract ArrayT getDataCopy(); /** - * Intended for external calls where a copy is not needed. WARNING: think carefully before using - * this method rather than {@link #getDataCopy()}. + * Returns data for read-only purposes. The result may or may not be copy of the internal data. + * This is a slow path operation for vector types that may have a native mirror, use + * {@link VectorToArray} node for fast path in such cases. + * + * @see VectorToArray + * @see RObject#getNativeMirror() + * @return vector data */ - public abstract ArrayT getDataWithoutCopying(); + public abstract ArrayT getReadonlyData(); /** - * Return vector data (copying if necessary) that's guaranteed not to be shared with any other - * vector instance (but maybe non-temporary in terms of vector's sharing mode). + * Return vector data (copying if necessary) that's guaranteed to be either temporary in terms + * of vector sharing mode, or owned by only one location (non-shared). It is not safe to re-use + * the array returned to create a new vector. * * @return vector data */ public final ArrayT getDataNonShared() { - return isShared() ? getDataCopy() : getDataWithoutCopying(); + return !isShared() ? getReadonlyData() : getDataCopy(); } /** * Return vector data (copying if necessary) that's guaranteed to be "fresh" (temporary in terms - * of vector sharing mode). + * of vector sharing mode). As long as the vector is not retuned or put into a list/environment + * (i.e. if it is temporary, it will stay temporary), it is safe to reuse the array retuned by + * this method to create a new vector. * * @return vector data */ public final ArrayT getDataTemp() { - return isTemporary() ? getDataWithoutCopying() : getDataCopy(); + return isTemporary() ? getReadonlyData() : getDataCopy(); } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java index 5afbae372907df8ac0f98640c8a71f1ce1a17f66..928229bfae518308c85b04370c86df5d66a28c40 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractContainer.java @@ -58,6 +58,15 @@ public interface RAbstractContainer extends RAttributable, RTypedValue { return getDataAtAsObject(index); } + /** + * Returns an object that could be passed to {@link #getDataAtAsObject(Object, int)} or type + * specialized versions in concrete vector types. The {@code store} object should contain data + * necessary for the vector to perform {@link #getDataAtAsObject(Object, int)} and similar + * methods without any field loads. If {@code store} is saved into a local variable, then the + * {@code getDataAsObject} overloads with {@code store} parameter do not have to load the + * vector's fields, but instead read the necessary data from a local variable, which could be + * beneficial when in loop. + */ default Object getInternalStore() { return null; } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java index a932ec25774ba052f178f8b757ed468ac516fba4..c5cb2fe28d7ed2164b885310c67de92827874ca7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java @@ -154,15 +154,6 @@ public abstract class REnvironment extends RAttributeStorage { @Override public void beforeDispose(RContext context) { beforeDestroyContext(context, this); - for (FrameSlot slot : globalFrame.getFrameDescriptor().getSlots()) { - if (globalFrame.isObject(slot)) { - globalFrame.setObject(slot, null); - } - } - baseEnv = null; - namespaceRegistry = null; - searchPath = null; - parentGlobalFrame = null; } public static ContextStateImpl newContextState(RContext context) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java index 24685419efb0e382b59e3599281dfcabb4d94d6e..b8cb17148db018cb5284aaaef45bcd444fd95efd 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java @@ -191,7 +191,9 @@ public final class RScope extends AbstractScope { private String[] ls() { RStringVector ls = frameAccess.ls(true, null, false); - return ls.getDataWithoutCopying(); + // we make a defensive copy, another option would be to make the vector shared and reuse + // the underlying array + return ls.getDataCopy(); } public static boolean isInstance(TruffleObject obj) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java index bcb0a801559bbe7faf54e60d9d85b835a8fa5881..37e2afc0d46ce0a0e101c3cdb02cd334b9916bca 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CRFFI.java @@ -46,6 +46,7 @@ import com.oracle.truffle.r.runtime.data.RList; import com.oracle.truffle.r.runtime.data.RLogicalVector; import com.oracle.truffle.r.runtime.data.RRawVector; import com.oracle.truffle.r.runtime.data.RStringVector; +import com.oracle.truffle.r.runtime.data.RVector; import com.oracle.truffle.r.runtime.data.model.RAbstractAtomicVector; import com.oracle.truffle.r.runtime.data.model.RAbstractComplexVector; import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; @@ -117,7 +118,7 @@ abstract class TemporaryWrapper implements TruffleObject { protected long address; protected RAbstractAtomicVector vector; - public TemporaryWrapper(RAbstractAtomicVector vector) { + TemporaryWrapper(RAbstractAtomicVector vector) { this.vector = vector; } @@ -145,11 +146,16 @@ abstract class TemporaryWrapper implements TruffleObject { } protected abstract RAbstractAtomicVector copyBack(); + + protected static <ArrayT> ArrayT reuseData(RVector<ArrayT> vec) { + // Note: maybe we can reuse non-shared vectors too? + return vec.isTemporary() ? vec.getInternalManagedData() : null; + } } final class StringWrapper extends TemporaryWrapper { - public StringWrapper(RAbstractStringVector vector) { + StringWrapper(RAbstractStringVector vector) { super(vector); } @@ -181,7 +187,10 @@ final class StringWrapper extends TemporaryWrapper { @TruffleBoundary protected RStringVector copyBack() { RStringVector result = ((RAbstractStringVector) vector).materialize(); - String[] data = result.isTemporary() ? result.getDataWithoutCopying() : result.getDataCopy(); + String[] data = reuseData(result); + if (data == null) { + data = new String[result.getLength()]; + } for (int i = 0; i < data.length; i++) { long ptr = UnsafeAdapter.UNSAFE.getLong(address + i * 8); int length = 0; @@ -199,7 +208,7 @@ final class StringWrapper extends TemporaryWrapper { final class IntWrapper extends TemporaryWrapper { - public IntWrapper(RAbstractIntVector vector) { + IntWrapper(RAbstractIntVector vector) { super(vector); } @@ -219,7 +228,10 @@ final class IntWrapper extends TemporaryWrapper { @TruffleBoundary protected RIntVector copyBack() { RIntVector result = ((RAbstractIntVector) vector).materialize(); - int[] data = result.isTemporary() ? result.getDataWithoutCopying() : result.getDataCopy(); + int[] data = reuseData(result); + if (data == null) { + data = new int[vector.getLength()]; + } UnsafeAdapter.UNSAFE.copyMemory(null, address, data, Unsafe.ARRAY_INT_BASE_OFFSET, vector.getLength() * Unsafe.ARRAY_INT_INDEX_SCALE); UnsafeAdapter.UNSAFE.freeMemory(address); return RDataFactory.createIntVector(data, false); @@ -228,7 +240,7 @@ final class IntWrapper extends TemporaryWrapper { final class LogicalWrapper extends TemporaryWrapper { - public LogicalWrapper(RAbstractLogicalVector vector) { + LogicalWrapper(RAbstractLogicalVector vector) { super(vector); } @@ -248,7 +260,10 @@ final class LogicalWrapper extends TemporaryWrapper { @TruffleBoundary protected RLogicalVector copyBack() { RLogicalVector result = ((RAbstractLogicalVector) vector).materialize(); - byte[] data = result.isTemporary() ? result.getDataWithoutCopying() : result.getDataCopy(); + byte[] data = reuseData(result); + if (data == null) { + data = new byte[result.getLength()]; + } int length = vector.getLength(); for (int i = 0; i < length; i++) { data[i] = RRuntime.int2logical(UnsafeAdapter.UNSAFE.getInt(address + (i * Unsafe.ARRAY_INT_INDEX_SCALE))); @@ -260,7 +275,7 @@ final class LogicalWrapper extends TemporaryWrapper { final class DoubleWrapper extends TemporaryWrapper { - public DoubleWrapper(RAbstractDoubleVector vector) { + DoubleWrapper(RAbstractDoubleVector vector) { super(vector); } @@ -280,7 +295,10 @@ final class DoubleWrapper extends TemporaryWrapper { @TruffleBoundary protected RDoubleVector copyBack() { RDoubleVector result = ((RAbstractDoubleVector) vector).materialize(); - double[] data = result.isTemporary() ? result.getDataWithoutCopying() : result.getDataCopy(); + double[] data = reuseData(result); + if (data == null) { + data = new double[vector.getLength()]; + } UnsafeAdapter.UNSAFE.copyMemory(null, address, data, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, vector.getLength() * Unsafe.ARRAY_DOUBLE_INDEX_SCALE); UnsafeAdapter.UNSAFE.freeMemory(address); return RDataFactory.createDoubleVector(data, false); @@ -289,7 +307,7 @@ final class DoubleWrapper extends TemporaryWrapper { final class ComplexWrapper extends TemporaryWrapper { - public ComplexWrapper(RAbstractComplexVector vector) { + ComplexWrapper(RAbstractComplexVector vector) { super(vector); } @@ -311,7 +329,10 @@ final class ComplexWrapper extends TemporaryWrapper { @TruffleBoundary protected RComplexVector copyBack() { RComplexVector result = ((RAbstractComplexVector) vector).materialize(); - double[] data = result.isTemporary() ? result.getDataWithoutCopying() : result.getDataCopy(); + double[] data = reuseData(result); + if (data == null) { + data = new double[result.getLength() * 2]; + } UnsafeAdapter.UNSAFE.copyMemory(null, address, data, Unsafe.ARRAY_DOUBLE_BASE_OFFSET, vector.getLength() * 2 * Unsafe.ARRAY_DOUBLE_INDEX_SCALE); UnsafeAdapter.UNSAFE.freeMemory(address); return RDataFactory.createComplexVector(data, false); @@ -320,7 +341,7 @@ final class ComplexWrapper extends TemporaryWrapper { final class RawWrapper extends TemporaryWrapper { - public RawWrapper(RAbstractRawVector vector) { + RawWrapper(RAbstractRawVector vector) { super(vector); } @@ -340,7 +361,10 @@ final class RawWrapper extends TemporaryWrapper { @TruffleBoundary protected RRawVector copyBack() { RRawVector result = ((RAbstractRawVector) vector).materialize(); - byte[] data = result.isTemporary() ? result.getDataWithoutCopying() : result.getDataCopy(); + byte[] data = reuseData(result); + if (data == null) { + data = new byte[result.getLength()]; + } UnsafeAdapter.UNSAFE.copyMemory(null, address, data, Unsafe.ARRAY_BYTE_BASE_OFFSET, vector.getLength() * Unsafe.ARRAY_BYTE_INDEX_SCALE); UnsafeAdapter.UNSAFE.freeMemory(address); return RDataFactory.createRawVector(data); @@ -352,7 +376,7 @@ final class RawWrapper extends TemporaryWrapper { */ public interface CRFFI { - public static abstract class InvokeCNode extends RBaseNode { + abstract class InvokeCNode extends RBaseNode { /** * Invoke the native method identified by {@code symbolInfo} passing it the arguments in diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RMultinom.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RMultinom.java index 62336feae6fcca50ce1ef0d698422896e9e5e667..2a79a1339b1279cdf234b83520f240aa8b4381ac 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RMultinom.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/nmath/distr/RMultinom.java @@ -18,6 +18,7 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RError.Message; import com.oracle.truffle.r.runtime.RRuntime; +import com.oracle.truffle.r.runtime.data.nodes.AccessVector.DoubleAccessor; import com.oracle.truffle.r.runtime.nmath.RandomFunctions.RandomNumberProvider; public final class RMultinom { @@ -31,7 +32,7 @@ public final class RMultinom { * prob[j]) , sum_j rN[j] == n, sum_j prob[j] == 1. */ @TruffleBoundary - public static boolean rmultinom(int nIn, double[] prob, int maxK, int[] rN, int rnStartIdx, RandomNumberProvider rand, Rbinom rbinom) { + public static boolean rmultinom(int nIn, DoubleAccessor prob, int maxK, int[] rN, int rnStartIdx, RandomNumberProvider rand, Rbinom rbinom) { /* * This calculation is sensitive to exact values, so we try to ensure that the calculations * are as accurate as possible so different platforms are more likely to give the same @@ -52,7 +53,7 @@ public final class RMultinom { */ /* LDOUBLE */double pTot = 0.; for (int k = 0; k < maxK; k++) { - double pp = prob[k]; + double pp = prob.getDataAt(k); if (!Double.isFinite(pp) || pp < 0. || pp > 1.) { rN[rnStartIdx + k] = RRuntime.INT_NA; return false; @@ -75,7 +76,7 @@ public final class RMultinom { /* Generate the first K-1 obs. via binomials */ for (int k = 0; k < maxK - 1; k++) { /* (p_tot, n) are for "remaining binomial" */ - /* LDOUBLE */double probK = prob[k]; + /* LDOUBLE */double probK = prob.getDataAt(k); if (probK != 0.) { double pp = probK / pTot; // System.out.printf("[%d] %.17f\n", k + 1, pp); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/AccessVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/AccessVector.java deleted file mode 100644 index 13fc7233e5c65c11440bb48b60d27cb906d18509..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ops/AccessVector.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2017, 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.runtime.ops; - -import static com.oracle.truffle.r.runtime.RRuntime.isNA; - -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.nodes.Node; -import com.oracle.truffle.api.profiles.BranchProfile; -import com.oracle.truffle.r.runtime.RError; -import com.oracle.truffle.r.runtime.RRuntime; -import com.oracle.truffle.r.runtime.context.RContext; -import com.oracle.truffle.r.runtime.data.RComplex; -import com.oracle.truffle.r.runtime.data.RDataFactory; -import com.oracle.truffle.r.runtime.data.RNull; -import com.oracle.truffle.r.runtime.data.model.RAbstractContainer; -import com.oracle.truffle.r.runtime.data.model.RAbstractDoubleVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractIntVector; -import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; - -public abstract class AccessVector { - - public static final class Int<T extends RAbstractIntVector, S> extends Node { - - @SuppressWarnings("unchecked") - public S init(T vector) { - return (S) vector; - } - - @SuppressWarnings("unchecked") - public int getInt(S store, int index) { - return ((T) store).getDataAt(index); - } - } -} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java index 954b4408215496c42ecfb13cedfdc609bcdd657f..42e5cfb447cd6341ed564e3e7a6ca09c4b874fde 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java @@ -35,9 +35,7 @@ import com.oracle.truffle.r.runtime.rng.user.UserRNG; * The fact that the R programmer can set {@code .Random.seed} explicitly, as opposed to the * recommended approach of calling {@code set.seed}, is something of a pain as it changes the * {@link Kind}, the {@link NormKind} and the actual seeds all in one go and in a totally - * uncontrolled way, which then has to be checked. Currently we do not support reading it, although - * we do create/update it when the seed/kind is changed, primarily as a debugging aid. N.B. GnuR - * updates it on <i>every</i> random number generation! + * uncontrolled way, which then has to be checked. * * Important note: make sure to invoke {@link #getRNGState()} before invoking any other methods from * this class and to invoke {@link #putRNGState()} when done witch random number generation. @@ -387,9 +385,13 @@ public class RRNG { seeds = new int[]{(int) seedsObj}; } else if (seedsObj instanceof RIntVector) { RIntVector seedsVec = (RIntVector) seedsObj; - seeds = seedsVec.getDataWithoutCopying(); + seeds = seedsVec.getReadonlyData(); if (seeds == currentGenerator().getSeeds()) { - // no change of the .Random.seed variable + // Optimization: if the array instance has not changed, then the .Random.seed + // variable was not changed, nor materialized to a native mirror, we still hold + // the same reference to its underlying data. Note: setISeed is potentially + // doing some clean-up of the data, so it may not be O(1) operation and it's + // good to avoid it. return; } } else if (seedsObj instanceof int[]) { diff --git a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd index 2ea30d34d29ec665df649be69ddc218e38fb8d9f..c5ca498a5561545c0c5c5df8a5d02982dc945eb3 100644 --- a/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd +++ b/com.oracle.truffle.r.test.native/packages/testrffi/testrffi/man/testrffi-package.Rd @@ -1,8 +1,8 @@ +\title{Tests the R FFI interface} \name{testrffi-package} \alias{testrffi-package} \alias{testrffi} \docType{package} -\title{Tests the R FFI interface} \description{Tests the R FFI interface via a collection of R functions that call down to native code using .Call which then typically make R FFI upcalls to test the individual functions. The set of tests is not comprehensive. diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/runtime/data/RPairListTests.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/runtime/data/RPairListTests.java index d63388c943f734cb04d2a5c63bab81209d790252..04ecbe3bd7112ff3e75835fd90ad3820cbb48a41 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/runtime/data/RPairListTests.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/runtime/data/RPairListTests.java @@ -49,7 +49,7 @@ public class RPairListTests { public void testToList() { RPairList pairList = RDataFactory.createPairList(1, RDataFactory.createPairList(2, RNull.instance, "name2"), "name1"); RList result = pairList.toRList(); - assertArrayEquals(new String[]{"name1", "name2"}, result.getNames().getDataWithoutCopying()); + assertArrayEquals(new String[]{"name1", "name2"}, result.getNames().getReadonlyData()); assertArrayEquals(new Object[]{1, 2}, result.getDataWithoutCopying()); } }