diff --git a/com.oracle.truffle.r.native/gnur/Makefile.gnur b/com.oracle.truffle.r.native/gnur/Makefile.gnur index 76eb523030ffa5275c1111b968117073b6311ec0..238eb6c3e5a21fa21ec597b8d78257f57b055d68 100644 --- a/com.oracle.truffle.r.native/gnur/Makefile.gnur +++ b/com.oracle.truffle.r.native/gnur/Makefile.gnur @@ -116,7 +116,7 @@ endif $(GNUR_HOME)/Makefile: ed $(GNUR_HOME)/src/extra/xz/Makefile.in < patchXzMakefile - (cd $(GNUR_HOME); ./configure --with-x=no --without-recommended-packages $(GNUR_CONFIG_FLAGS) > gnur_configure.log 2>&1) + (cd $(GNUR_HOME); ./configure --with-x=no --without-recommended-packages --enable-memory-profiling $(GNUR_CONFIG_FLAGS) > gnur_configure.log 2>&1) build: $(GNUR_HOME)/bin/R diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java index 407c046347ac9264859cef58520cb7afb5f8ffc9..aa0b4bacc234e8d706393cefa5c5d644c7481f02 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/BasePackage.java @@ -580,6 +580,7 @@ public class BasePackage extends RBuiltinPackage { add(TraceFunctions.PrimTrace.class, TraceFunctionsFactory.PrimTraceNodeGen::create); add(TraceFunctions.PrimUnTrace.class, TraceFunctionsFactory.PrimUnTraceNodeGen::create); add(TraceFunctions.TraceOnOff.class, TraceFunctionsFactory.TraceOnOffNodeGen::create); + add(TraceFunctions.Tracemem.class, TraceFunctionsFactory.TracememNodeGen::create); add(Transpose.class, TransposeNodeGen::create); add(TrigExpFunctions.Acos.class, TrigExpFunctionsFactory.AcosNodeGen::create); add(TrigExpFunctions.Acosh.class, TrigExpFunctionsFactory.AcoshNodeGen::create); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java index 341a599ab3100966d00a8cae5e0d361e6d1cf630..c32d2e369e9fffa66730b7ddf5688d68bb3f9697 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/TraceFunctions.java @@ -22,6 +22,9 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +import java.io.IOException; +import java.util.HashSet; + import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.dsl.Specialization; @@ -35,10 +38,13 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RType; import com.oracle.truffle.r.runtime.RVisibility; +import com.oracle.truffle.r.runtime.conn.StdConnections; import com.oracle.truffle.r.runtime.context.RContext; +import com.oracle.truffle.r.runtime.data.MemoryTracer; import com.oracle.truffle.r.runtime.data.RFunction; import com.oracle.truffle.r.runtime.data.RNull; import com.oracle.truffle.r.runtime.data.model.RAbstractStringVector; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; public class TraceFunctions { @@ -111,4 +117,36 @@ public class TraceFunctions { return RRuntime.asLogical(RContext.getInstance().stateInstrumentation.getTracingState()); } } + + @RBuiltin(name = "tracemem", kind = RBuiltinKind.PRIMITIVE, parameterNames = "x") + public abstract static class Tracemem extends RBuiltinNode { + + static { + MemoryTracer.setListener(new TracememListener()); + } + + @Specialization + protected String execute(Object x) { + getTracedObjects().add(x); + MemoryTracer.reportEvents(); + return String.format("<0x%x>", x.hashCode()); + } + + private static HashSet<Object> getTracedObjects() { + return RContext.getInstance().getInstrumentationState().getTracemem().getTracedObjects(); + } + + private static final class TracememListener implements MemoryTracer.Listener { + public void reportCopying(RAbstractVector src, RAbstractVector dest) { + if (getTracedObjects().contains(src)) { + String msg = String.format("tracemem[0x%x -> 0x%x]", src.hashCode(), dest.hashCode()); + try { + StdConnections.getStdout().writeString(msg, true); + } catch (IOException ex) { + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, ex.getMessage()); + } + } + } + } + } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java index d91d4a8fbbe67167fb4ef437b99865e6abca9fe0..8c67c523f28176fe28445d8b3b5cd24ab0d73260 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateDimNames.java @@ -163,7 +163,7 @@ public abstract class UpdateDimNames extends RBuiltinNode { RList resDimNames = newDimNames; if (newDimNamesLength < dimensions.length) { // resize the array and fill the missing entries with NULL-s - resDimNames = resDimNames.copyResized(dimensions.length, true); + resDimNames = (RList) resDimNames.copyResized(dimensions.length, true); resDimNames.setAttributes(newDimNames); for (int i = newDimNamesLength; i < dimensions.length; i++) { resDimNames.updateDataAt(i, RNull.instance, null); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java index d192337e3792cb3a2d984f9081c02eaf12713e9d..317ce79c47937da8c3668727093dd086aeb21372 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/UpdateNames.java @@ -72,7 +72,7 @@ public abstract class UpdateNames extends RBuiltinNode { } RAbstractContainer result = (RAbstractContainer) container.getNonShared(); if (stringVector.getLength() < result.getLength()) { - stringVector = stringVector.copyResized(result.getLength(), true); + stringVector = (RStringVector) stringVector.copyResized(result.getLength(), true); } else if (stringVector.getLength() > result.getLength()) { throw RError.error(this, Message.NAMES_LONGER, stringVector.getLength(), result.getLength()); } else if (stringVector == container) { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryTracer.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryTracer.java new file mode 100644 index 0000000000000000000000000000000000000000..e8f271a92d7e62c6ce3f8347d3e8fd7f55cc9cbf --- /dev/null +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/MemoryTracer.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.truffle.r.runtime.data; + +import com.oracle.truffle.api.Assumption; +import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.r.runtime.data.model.RAbstractVector; + +/** + * Helper for tracing memory related events. All implementors of {@link RAbstractVector} are + * expected to report to {@link MemoryTracer} and othes can listen to them through {@link Listener} + * interface. Use method {@link #reportEvents()} to start the tracing. + */ +public final class MemoryTracer { + private static Listener listener; + private static final Assumption noMemoryTracingAssumption = Truffle.getRuntime().createAssumption(); + + private MemoryTracer() { + // only static methods + } + + /** + * Sets the listener of memory tracing events. For the time being there can only be one + * listener. This can be extended to an array should we need more listeners. + */ + public static void setListener(Listener newListener) { + listener = newListener; + } + + /** + * After calling this method memory related events will be reported to the listener. This + * invalidates global assumption and should be used with caution. + */ + public static void reportEvents() { + noMemoryTracingAssumption.invalidate(); + } + + /** + * Reports copy event to the listener. If there are no traced objects, this should turn into + * no-op. + */ + public static void reportCopying(RAbstractVector source, RAbstractVector dest) { + if (!noMemoryTracingAssumption.isValid() && listener != null) { + listener.reportCopying(source, dest); + } + } + + public interface Listener { + void reportCopying(RAbstractVector source, RAbstractVector dest); + } +} diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java index a3d7858c77f15957b42b902e19e6a6d2a4707d1d..1bfe70252de40c3162543da9ef30c416b27154b2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RComplex.java @@ -67,7 +67,9 @@ public final class RComplex extends RScalarVector implements RAbstractComplexVec @Override public RComplexVector materialize() { - return RDataFactory.createComplexVectorFromScalar(this); + RComplexVector result = RDataFactory.createComplexVectorFromScalar(this); + MemoryTracer.reportCopying(this, result); + return result; } @Override 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 530b0796a9308505f41a7194f8b702ffb35b88f7..e94bd445cc3b6d629053f86da551dbab6deea2bf 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 @@ -198,7 +198,7 @@ public final class RComplexVector extends RVector implements RAbstractComplexVec } @Override - public RComplexVector copyResized(int size, boolean fillNA) { + protected RComplexVector internalCopyResized(int size, boolean fillNA) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); return RDataFactory.createComplexVector(copyResizedData(size, fillNA), isComplete); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java index b31722d76e5a1b49c4774fc3ed16079908c5b775..096356c36aaf5031ea8b85166e820cfbd7d960b5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDouble.java @@ -89,7 +89,9 @@ public final class RDouble extends RScalarVector implements RAbstractDoubleVecto @Override public RDoubleVector materialize() { - return RDataFactory.createDoubleVectorFromScalar(getValue()); + RDoubleVector result = RDataFactory.createDoubleVectorFromScalar(getValue()); + MemoryTracer.reportCopying(this, result); + return result; } @Override 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 a3be26975816e8a310f72bf77f809fdd84c72146..c542875fa7f26d8e6b64219f65df90db26b6db82 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 @@ -211,7 +211,7 @@ public final class RDoubleVector extends RVector implements RAbstractDoubleVecto } @Override - public RDoubleVector copyResized(int size, boolean fillNA) { + protected RDoubleVector internalCopyResized(int size, boolean fillNA) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); return RDataFactory.createDoubleVector(copyResizedData(size, fillNA), isComplete); } 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 6a672cdbace2b30459625d2caa289cce155ffd4d..74e182b9cee2de064c08e037eea0ad49440e66dd 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 @@ -208,7 +208,7 @@ public final class RIntVector extends RVector implements RAbstractIntVector { } @Override - public RIntVector copyResized(int size, boolean fillNA) { + protected RIntVector internalCopyResized(int size, boolean fillNA) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); return RDataFactory.createIntVector(copyResizedData(size, fillNA), isComplete); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java index 0df0f556e1b7226069b7e983910c8cbabaf6e25d..075d9ee51126ff8bd297ebffb5b11bed48055b13 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RInteger.java @@ -87,7 +87,9 @@ public final class RInteger extends RScalarVector implements RAbstractIntVector @Override public RIntVector materialize() { - return RDataFactory.createIntVectorFromScalar(value); + RIntVector result = RDataFactory.createIntVectorFromScalar(value); + MemoryTracer.reportCopying(this, result); + return result; } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java index cb0496f25de6cc7d472d396e7a04a1736a142b25..c97e5a73d88d9290e5597a439ec0b73d82d13a7e 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RList.java @@ -72,7 +72,7 @@ public final class RList extends RListBase { } @Override - public RList copyResized(int size, boolean fillNA) { + protected RList internalCopyResized(int size, boolean fillNA) { return RDataFactory.createList(copyResizedData(size, fillNA)); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java index 65f0ad784fd53bec3301152b834b74c3e4efc5b2..05d0e6d1b1d642a39fc13b620d15a3727a3c130d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RLogical.java @@ -93,7 +93,9 @@ public final class RLogical extends RScalarVector implements RAbstractLogicalVec @Override public RLogicalVector materialize() { - return RDataFactory.createLogicalVectorFromScalar(value); + RLogicalVector result = RDataFactory.createLogicalVectorFromScalar(value); + MemoryTracer.reportCopying(this, result); + return result; } @Override 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 4d3068841936b172d547b8cad3a69073785ff11d..a492093eb77cf75441f3b9218fb7b370fb9fe891 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 @@ -169,7 +169,7 @@ public final class RLogicalVector extends RVector implements RAbstractLogicalVec } @Override - public RLogicalVector copyResized(int size, boolean fillNA) { + protected RLogicalVector internalCopyResized(int size, boolean fillNA) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); return RDataFactory.createLogicalVector(copyResizedData(size, fillNA), isComplete); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java index bb93e20a576774f9b6697cdc6b0e47f6b5467417..d843cacfb937a8518c91151e91e7e33b3c553076 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RRaw.java @@ -64,7 +64,9 @@ public final class RRaw extends RScalarVector implements RAbstractRawVector { @Override public RRawVector materialize() { - return RDataFactory.createRawVector(new byte[]{value}); + RRawVector result = RDataFactory.createRawVector(new byte[]{value}); + MemoryTracer.reportCopying(this, result); + return result; } @Override 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 fdadc7cd66a1a41c9d046a33e0872ce52827e0a7..01ef62b132ffb705df18b6646b7ca419a06e3da9 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 @@ -187,7 +187,7 @@ public final class RRawVector extends RVector implements RAbstractRawVector { } @Override - public RRawVector copyResized(int size, boolean fillNA) { + protected RRawVector internalCopyResized(int size, boolean fillNA) { return RDataFactory.createRawVector(copyResizedData(size, fillNA)); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java index 6d7ddced925c96d8bebedfbb4b98892d18dba52f..6e4a7ca5d9590b16c937b8bb62608c6f25ef8cd7 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RScalarVector.java @@ -142,22 +142,30 @@ public abstract class RScalarVector extends RScalar implements RAbstractVector { @Override public RVector copyResized(int size, boolean fillNA) { - return materialize().copyResized(size, fillNA); + RVector result = materialize().copyResized(size, fillNA); + MemoryTracer.reportCopying(this, result); + return result; } @Override public RAbstractVector copyWithNewDimensions(int[] newDimensions) { - return materialize().copyWithNewDimensions(newDimensions); + RAbstractVector result = materialize().copyWithNewDimensions(newDimensions); + MemoryTracer.reportCopying(this, result); + return result; } @Override public RVector copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { - return materialize().copyResizedWithDimensions(newDimensions, fillNA); + RVector result = materialize().copyResizedWithDimensions(newDimensions, fillNA); + MemoryTracer.reportCopying(this, result); + return result; } @Override public RAbstractVector copyDropAttributes() { - return materialize().copyDropAttributes(); + RVector result = materialize().copyDropAttributes(); + MemoryTracer.reportCopying(this, result); + return result; } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java index df3204230ada99193b5ba8a0003154bd26105c0f..3dcc48a783d72896755c68f58238721596a0d86c 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RSequence.java @@ -80,7 +80,9 @@ public abstract class RSequence implements RAbstractVector { } public final RVector createVector() { - return internalCreateVector(); + RVector result = internalCreateVector(); + MemoryTracer.reportCopying(this, result); + return result; } protected abstract RVector internalCreateVector(); diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java index 03edef949b3c7b03135e912ab175d2079c023b25..764f4c4b4ba2c88556989eb83461fdf4b8409bc5 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RString.java @@ -73,7 +73,9 @@ public final class RString extends RScalarVector implements RAbstractStringVecto @Override public RStringVector materialize() { - return RDataFactory.createStringVector(new String[]{getValue()}, isComplete()); + RStringVector result = RDataFactory.createStringVector(new String[]{getValue()}, isComplete()); + MemoryTracer.reportCopying(this, result); + return result; } @Override 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 85a263b13b224a23a06cfcbb5bdc50eec83f417e..53f6667432c8ca54341247372fbab98b5a38f82f 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 @@ -190,7 +190,7 @@ public final class RStringVector extends RVector implements RAbstractStringVecto } @Override - public RStringVector copyResized(int size, boolean fillNA) { + protected RStringVector internalCopyResized(int size, boolean fillNA) { boolean isComplete = isComplete() && ((data.length >= size) || !fillNA); return RDataFactory.createStringVector(copyResizedData(size, fillNA ? RRuntime.STRING_NA : null), isComplete); } 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 2c7e3e715317addc7183cab2c3f8b6ac78bb4cd0..159addc3e228b3bda6e2e3bbcc9e9504544c5987 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 @@ -410,7 +410,7 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare RList resDimNames = newDimNames; if (newDimNamesLength < dimensions.length) { // resize the array and fill the missing entries with NULL-s - resDimNames = resDimNames.copyResized(dimensions.length, true); + resDimNames = (RList) resDimNames.copyResized(dimensions.length, true); resDimNames.setAttributes(newDimNames); for (int i = newDimNamesLength; i < dimensions.length; i++) { resDimNames.updateDataAt(i, RNull.instance, null); @@ -547,9 +547,11 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare } } + // public interface *copy* methods are final and delegate to *internalCopyAndReport* methods + @Override public final RVector copy() { - RVector result = internalCopy(); + RVector result = internalCopyAndReport(); setAttributes(result); incCopyCount(); result.setTypedValueInfo(getTypedValueInfo()); @@ -558,21 +560,55 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare @Override public final RVector copyDropAttributes() { - return internalCopy(); + RVector result = internalCopyAndReport(); + return result; } @Override - public RVector deepCopy() { - RVector result = internalDeepCopy(); + public final RVector deepCopy() { + RVector result = internalDeepCopyAndReport(); setAttributes(result); return result; } + @Override + public final RVector copyResized(int size, boolean fillNA) { + return internalCopyResizedAndReport(size, fillNA); + } + + // *internalCopyAndReport* methods do just the copy and report it to MemoryTracer. These should + // be used if additional logic in public interface *copy* method is not desired. + + protected final RVector internalCopyAndReport() { + RVector result = internalCopy(); + MemoryTracer.reportCopying(this, result); + return result; + } + + protected final RVector internalDeepCopyAndReport() { + RVector result = internalDeepCopy(); + MemoryTracer.reportCopying(this, result); + return result; + } + + protected final RVector internalCopyResizedAndReport(int size, boolean fillNA) { + RVector result = internalCopyResized(size, fillNA); + MemoryTracer.reportCopying(this, result); + return result; + } + + // *internalCopy* methods should only be overridden, but never invoked from anywhere but + // *internalCopyAndReport* + + protected abstract RVector internalCopyResized(int size, boolean fillNA); + // to be overridden by recursive structures protected RVector internalDeepCopy() { return internalCopy(); } + protected abstract RVector internalCopy(); + @Override public RVector copyResizedWithDimensions(int[] newDimensions, boolean fillNA) { // TODO support for higher dimensions @@ -588,8 +624,6 @@ public abstract class RVector extends RSharingAttributeStorage implements RShare protected abstract String getDataAtAsString(int index); - protected abstract RVector internalCopy(); - protected abstract boolean internalVerify(); /** diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java index a0a74fcdcb3df189eb2397dee4f99d42ed18306d..0fe0baccfc90e7e0bb0b1a374322b1d431b37cc2 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/closures/RToVectorClosure.java @@ -22,6 +22,7 @@ */ package com.oracle.truffle.r.runtime.data.closures; +import com.oracle.truffle.r.runtime.data.MemoryTracer; import com.oracle.truffle.r.runtime.data.RAttributeProfiles; import com.oracle.truffle.r.runtime.data.RAttributes; import com.oracle.truffle.r.runtime.data.RList; @@ -127,12 +128,16 @@ abstract class RToVectorClosure implements RAbstractVector { @Override public final RAbstractVector copy() { - return vector.copy(); + RAbstractVector result = vector.copy(); + MemoryTracer.reportCopying(this, result); + return result; } @Override public final RVector copyResized(int size, boolean fillNA) { - return vector.copyResized(size, fillNA); + RVector result = vector.copyResized(size, fillNA); + MemoryTracer.reportCopying(this, result); + return result; } @Override @@ -146,7 +151,9 @@ abstract class RToVectorClosure implements RAbstractVector { @Override public final RAbstractVector copyDropAttributes() { - return vector.copyDropAttributes(); + RAbstractVector result = vector.copyDropAttributes(); + MemoryTracer.reportCopying(this, result); + return result; } @Override diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java index b0f2d25be47dfeb42fb3d7d4cc7eaadea0f5fcc7..a2ae57288b474717f66033b2bacd43a882e5e899 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/model/RAbstractVector.java @@ -24,8 +24,12 @@ package com.oracle.truffle.r.runtime.data.model; import com.oracle.truffle.api.profiles.ConditionProfile; import com.oracle.truffle.r.runtime.RType; +import com.oracle.truffle.r.runtime.data.MemoryTracer; import com.oracle.truffle.r.runtime.data.RVector; +/** + * When implementing, make sure to invoke related {@link MemoryTracer} methods. + */ public interface RAbstractVector extends RAbstractContainer { /** @@ -76,5 +80,4 @@ public interface RAbstractVector extends RAbstractContainer { void setComplete(boolean complete); void setNA(Object store, int index); - } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java index 87b3341dae1bdc444b1f3e64b7657a8835905597..2dc42bdcf7f4c67f1cc213e80de1214088238767 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java @@ -23,6 +23,7 @@ package com.oracle.truffle.r.runtime.instrument; import java.io.PrintWriter; +import java.util.HashSet; import java.util.WeakHashMap; import com.oracle.truffle.api.instrumentation.EventBinding; @@ -58,21 +59,33 @@ public final class InstrumentationState implements RContext.ContextState { private final RprofState rprofState; + private final TracememContext tracememContext; + + /** + * State used by the {@code tracemem} built-in. + */ + public static final class TracememContext { + private HashSet<Object> tracedObjects; + + public HashSet<Object> getTracedObjects() { + if (tracedObjects == null) { + tracedObjects = new HashSet<>(); + } + return tracedObjects; + } + } + /** * State used by {@code Rprof}. * */ - public static class RprofState { + public static final class RprofState { private PrintWriter out; private Thread profileThread; private ExecutionEventListener statementListener; private long intervalInMillis; private boolean lineProfiling; - public static RprofState newContext(@SuppressWarnings("unused") RContext context) { - return new RprofState(); - } - public void initialize(PrintWriter outA, Thread profileThreadA, ExecutionEventListener statementListenerA, long intervalInMillisA, boolean lineProfilingA) { this.out = outA; @@ -107,6 +120,7 @@ public final class InstrumentationState implements RContext.ContextState { private InstrumentationState(Instrumenter instrumenter) { this.instrumenter = instrumenter; this.rprofState = new RprofState(); + this.tracememContext = new TracememContext(); } public void putTraceBinding(SourceSection ss, EventBinding<?> binding) { @@ -158,6 +172,10 @@ public final class InstrumentationState implements RContext.ContextState { return rprofState; } + public TracememContext getTracemem() { + return tracememContext; + } + public static InstrumentationState newContext(@SuppressWarnings("unused") RContext context, Instrumenter instrumenter) { return new InstrumentationState(instrumenter); } diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test index 478ac346fb42ee04ab52e6b90a6cdbed069428ef..3a285e948547d4cb29445245e3eaf160adc50bb6 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/ExpectedTestOutput.test @@ -48821,6 +48821,10 @@ character(0) #argv <- structure(list(x = c('na', NA, 'banana')), .Names = 'x');do.call('toupper', argv) [1] "NA" NA "BANANA" +##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.basicTests +#v <- c(1,10); addr<-tracemem(v); f<-function(x) x[[1]]<-42; out<-capture.output(f(v)); addr<-sub('>','',sub('<','',addr)); grep(paste0('tracemem[', addr), out, fixed=TRUE) +[1] 1 + ##com.oracle.truffle.r.test.builtins.TestBuiltin_trigamma.testtrigamma1 #argv <- list(structure(c(9.16602362697115, 1.16602362697115, 3.16602362697115, 6.16602362697115, 6.16602362697115, 2.16602362697115, 8.16602362697115, 1.16602362697115, 7.16602362697115, 19.1660236269712, 2.16602362697115), .Names = c('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11')));trigamma(argv[[1]]); 1 2 3 4 5 6 7 diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java new file mode 100644 index 0000000000000000000000000000000000000000..ecf20b6ec0a226252b35dc5eeb90d6316af29bdf --- /dev/null +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_tracemem.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.oracle.truffle.r.test.builtins; + +import org.junit.Test; + +import com.oracle.truffle.r.test.TestBase; + +public class TestBuiltin_tracemem extends TestBase { + @Test + public void basicTests() { + // tracemem returns the hash in form of "<0x0fa0abcd>", we get rid of the "<" and ">" to + // match it against the output that is produced by copying 'v', which should be in the form + // of "tracemem[0x0fa0abcd->someotherhash]". + assertEval("v <- c(1,10); addr<-tracemem(v); f<-function(x) x[[1]]<-42; out<-capture.output(f(v)); addr<-sub('>','',sub('<','',addr)); grep(paste0('tracemem[', addr), out, fixed=TRUE)"); + } +}