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 aa0b4bacc234e8d706393cefa5c5d644c7481f02..57b539b5cba18f93336be010442e9b081cc7d5d8 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 @@ -581,6 +581,8 @@ public class BasePackage extends RBuiltinPackage { add(TraceFunctions.PrimUnTrace.class, TraceFunctionsFactory.PrimUnTraceNodeGen::create); add(TraceFunctions.TraceOnOff.class, TraceFunctionsFactory.TraceOnOffNodeGen::create); add(TraceFunctions.Tracemem.class, TraceFunctionsFactory.TracememNodeGen::create); + add(TraceFunctions.Retracemem.class, TraceFunctionsFactory.RetracememNodeGen::create); + add(TraceFunctions.Untracemem.class, TraceFunctionsFactory.UntracememNodeGen::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 c32d2e369e9fffa66730b7ddf5688d68bb3f9697..28b9b86b15e00cc0372e18cfb545fb76868d7c81 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,19 +22,30 @@ */ package com.oracle.truffle.r.nodes.builtin.base; +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.stringValue; + 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.Truffle; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.Frame; +import com.oracle.truffle.api.frame.FrameInstance.FrameAccess; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.r.nodes.builtin.CastBuilder; import com.oracle.truffle.r.nodes.builtin.RBuiltinNode; import com.oracle.truffle.r.nodes.builtin.base.GetFunctionsFactory.GetNodeGen; import com.oracle.truffle.r.nodes.builtin.helpers.TraceHandling; +import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RBuiltin; import com.oracle.truffle.r.runtime.RBuiltinKind; +import com.oracle.truffle.r.runtime.RCaller; 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.RType; import com.oracle.truffle.r.runtime.RVisibility; @@ -42,6 +53,7 @@ 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.RMissing; 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; @@ -118,35 +130,126 @@ public class TraceFunctions { } } - @RBuiltin(name = "tracemem", kind = RBuiltinKind.PRIMITIVE, parameterNames = "x") - public abstract static class Tracemem extends RBuiltinNode { - + public abstract static class TracememBase extends RBuiltinNode { static { - MemoryTracer.setListener(new TracememListener()); + MemoryTracer.setListener(new TracememBase.TracememListener()); } - @Specialization - protected String execute(Object x) { + protected static HashSet<Object> getTracedObjects() { + return RContext.getInstance().getInstrumentationState().getTracemem().getTracedObjects(); + } + + protected static String formatHashCode(Object x) { + return String.format("<0x%x>", x.hashCode()); + } + + protected static void startTracing(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(); + protected static void printToStdout(String msg) { + try { + StdConnections.getStdout().writeString(msg, true); + } catch (IOException ex) { + throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, ex.getMessage()); + } + } + + @TruffleBoundary + protected static String getStackTrace() { + final StringBuffer result = new StringBuffer(); + Truffle.getRuntime().iterateFrames(frame -> { + Frame unwrapped = RArguments.unwrap(frame.getFrame(FrameAccess.READ_ONLY, true)); + if (RArguments.isRFrame(unwrapped)) { + RCaller call = RArguments.getCall(unwrapped); + if (call != null && call.isValidCaller()) { + result.append(RContext.getRRuntimeASTAccess().getCallerSource(call)); + result.append(' '); + } + } + return null; + }); + return result.toString(); } 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()); - } + printToStdout(String.format("tracemem[0x%x -> 0x%x]: %s", src.hashCode(), dest.hashCode(), getStackTrace())); } } } } + + /** + * Note: tracemem does not support scalars: these are stored in frame directly not wrapped in a + * vector class. When these are manipulated as 'vectors', they are wrapped temporarily, such + * temporary vector wrappers cannot be traced however. + */ + @RBuiltin(name = "tracemem", kind = RBuiltinKind.PRIMITIVE, parameterNames = "x") + public abstract static class Tracemem extends TracememBase { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("x").mustBe(nullValue().not(), Message.TRACEMEM_NOT_NULL); + } + + @Specialization + protected String execute(Object x) { + startTracing(x); + return formatHashCode(x); + } + } + + /** + * {@code retracemem} differences from {@code tracemem} are that it fails silently when R is not + * build with memory tracing support or x is NULL and it has additional parameter with an + * unclear meaning. + */ + @RBuiltin(name = "retracemem", kind = RBuiltinKind.PRIMITIVE, visibility = RVisibility.CUSTOM, parameterNames = {"x", "previous"}) + public abstract static class Retracemem extends TracememBase { + @Override + protected void createCasts(CastBuilder casts) { + casts.arg("previous").defaultError(Message.INVALID_ARGUMENT, "previous").mustBe(stringValue().or(missingValue())); + } + + @Specialization + protected Object execute(Object x, @SuppressWarnings("unused") RNull previous) { + return getResult(x); + } + + @Specialization + protected Object execute(Object x, @SuppressWarnings("unused") RMissing previous) { + return getResult(x); + } + + @Specialization + protected Object execute(Object x, String previous) { + Object result = getResult(x); + if (x != null && x != RNull.instance) { + startTracing(x); + printToStdout(String.format("tracemem[%s -> 0x%x]: %s", previous, x.hashCode(), getStackTrace())); + } + return result; + } + + private Object getResult(Object x) { + if (!isRNull(x) && getTracedObjects().contains(x)) { + RContext.getInstance().setVisible(true); + return formatHashCode(x); + } else { + RContext.getInstance().setVisible(false); + return RNull.instance; + } + } + } + + @RBuiltin(name = "untracemem", kind = RBuiltinKind.PRIMITIVE, visibility = RVisibility.OFF, parameterNames = "x") + public abstract static class Untracemem extends TracememBase { + @Specialization + protected RNull execute(Object x) { + getTracedObjects().remove(x); + return RNull.instance; + } + } } diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java index 66ac8ced4bcd2759534d469d1ee878725afa55aa..ab4d7f7aa168b40243a84301ffea87c404b6a355 100644 --- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java +++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/builtin/CastBuilder.java @@ -387,7 +387,7 @@ public final class CastBuilder { @Override public <T, R extends T> TypePredicateArgumentFilter<T, R> nullValue() { - return TypePredicateArgumentFilter.fromLambda(x -> x == RNull.instance || x == null); + return new TypePredicateArgumentFilter<>(x -> x == RNull.instance || x == null, true); } @Override 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 9c03b86cda3f4eaebdb99d8e69b6d5db469cc628..a8f59145f0f482a83e6843221d86805c11a89064 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 @@ -270,6 +270,7 @@ public final class RError extends RuntimeException { EMPTY_WHAT("empty 'what' specified"), LINE_ELEMENTS("line %d did not have %d elements"), ITEMS_NOT_MULTIPLE("number of items read is not a multiple of the number of columns"), + TRACEMEM_NOT_NULL("cannot trace NULL"), // below: GNU R gives also expression for the argument NOT_FUNCTION("'%s' is not a function, character or symbol"), NON_CHARACTER("non-character argument"), 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 3a285e948547d4cb29445245e3eaf160adc50bb6..6193f530100b87f5c340d8d9c5947519039398ad 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 @@ -40693,14 +40693,6 @@ logical(0) [145] NA 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 [163] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -##com.oracle.truffle.r.test.builtins.TestBuiltin_retracemem.testretracemem1 -#argv <- list(FALSE, FALSE);retracemem(argv[[1]],argv[[2]]); -Error in retracemem(argv[[1]], argv[[2]]) : invalid 'previous' argument - -##com.oracle.truffle.r.test.builtins.TestBuiltin_retracemem.testretracemem2 -#argv <- list(structure(3.14159265358979, class = structure('3.14159265358979', class = 'testit')), structure(3.14159265358979, class = structure('3.14159265358979', class = 'testit')));retracemem(argv[[1]],argv[[2]]); -Error in retracemem(argv[[1]], argv[[2]]) : invalid 'previous' argument - ##com.oracle.truffle.r.test.builtins.TestBuiltin_rev.testRev #{ rev(1:3) } [1] 3 2 1 @@ -48821,9 +48813,38 @@ 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_tracemem.argumentErrors +#retracemem(NULL) + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.argumentErrors +#retracemem(c(1,10,100), 1:10) +Error in retracemem(c(1, 10, 100), 1:10) : invalid 'previous' argument + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.argumentErrors +#tracemem(NULL) +Error in tracemem(NULL) : cannot trace NULL + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.list +#v <- list(1,10,100); tracemem(v); x <- v; x[[1]]<-42; +[1] "<0x112db18>" +tracemem[0x112db18 -> 0x1699c30]: + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.retracemem +#v <- c(1,10,100); tracemem(v); x <- v[-1]; retracemem(x, retracemem(v)); u <- x; u[[1]] <- 42; +[1] "<0x17f8b18>" +tracemem[<0x17f8b18> -> 0x251dd78]: +tracemem[0x251dd78 -> 0x251ddb0]: + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.vectors +#v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; untracemem(v); y[[2]] <- 84 +[1] "<0x1b8eb18>" +tracemem[0x1b8eb18 -> 0x20fabe8]: + +##com.oracle.truffle.r.test.builtins.TestBuiltin_tracemem.vectors +#v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; y[[2]] <- 84 +[1] "<0x24b2b18>" +tracemem[0x24b2b18 -> 0x2a1ebe8]: +tracemem[0x24b2b18 -> 0x2a1ea80]: ##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]]); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java index b002045656a8214a91587222a65aedb82e056adf..257566d7e83fdf6d15a746ff079664c03fdd5138 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java @@ -22,6 +22,7 @@ import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; +import java.util.HashMap; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; @@ -68,6 +69,7 @@ public class TestBase { IgnoreWarningContext, // the warning context is ignored MayIgnoreErrorContext, MayIgnoreWarningContext, + ContainsReferences, // replaces references in form of 0xbcdef1 for numbers IgnoreWhitespace; } @@ -353,6 +355,11 @@ public class TestBase { */ private static final boolean FULL_COMPARE_ERRORS = false; + /** + * To implement {@link Output#ContainsReferences}. + **/ + private static final Pattern REFERENCE_PATTERN = Pattern.compile("(?<id>(0x[0-9abcdefx]+))"); + /** * Test a given string with R source against expected output. This is (currently) an exact * match, so any warnings or errors will cause a failure until FastR matches GnuR in that @@ -459,6 +466,7 @@ public class TestBase { boolean mayContainError = TestTrait.contains(traits, Output.MayIgnoreErrorContext); boolean ambiguousError = TestTrait.contains(traits, Output.IgnoreErrorMessage); boolean ignoreWhitespace = TestTrait.contains(traits, Output.IgnoreWhitespace); + boolean containsReferences = TestTrait.contains(traits, Output.ContainsReferences); boolean nonSharedContext = TestTrait.contains(traits, Context.NonShared); boolean longTimeout = TestTrait.contains(traits, Context.LongTimeout); @@ -477,7 +485,7 @@ public class TestBase { result = result.replaceAll("\\s+", ""); } - CheckResult checkResult = checkResult(whiteLists, input, expected, result, containsWarning, mayContainWarning, containsError, mayContainError, ambiguousError); + CheckResult checkResult = checkResult(whiteLists, input, expected, result, containsWarning, mayContainWarning, containsError, mayContainError, ambiguousError, containsReferences); result = checkResult.result; expected = checkResult.expected; @@ -539,14 +547,18 @@ public class TestBase { } private CheckResult checkResult(WhiteList[] whiteLists, String input, String originalExpected, String originalResult, boolean containsWarning, boolean mayContainWarning, boolean containsError, - boolean mayContainError, boolean ambiguousError) { + boolean mayContainError, boolean ambiguousError, boolean convertReferences) { boolean ok; String result = originalResult; String expected = originalExpected; + if (convertReferences) { + result = convertReferencesInOutput(result); + expected = convertReferencesInOutput(expected); + } if (input.equals("c(1i,1i,1i)/(-(1/0))")) { System.console(); } - if (expected.equals(result) || searchWhiteLists(whiteLists, input, expected, result, containsWarning, mayContainWarning, containsError, mayContainError, ambiguousError)) { + if (expected.equals(result) || searchWhiteLists(whiteLists, input, expected, result, containsWarning, mayContainWarning, containsError, mayContainError, ambiguousError, convertReferences)) { ok = true; if (containsError && !ambiguousError) { System.out.println("unexpected correct error message: " + getTestContext()); @@ -575,8 +587,23 @@ public class TestBase { return new CheckResult(ok, result, expected); } + private static String convertReferencesInOutput(String result) { + Matcher matcher = REFERENCE_PATTERN.matcher(result); + HashMap<String, Integer> idsMap = new HashMap<>(); + int currentId = 1; + while (matcher.find()) { + if (idsMap.putIfAbsent(matcher.group("id"), currentId) == null) { + currentId++; + } + } + for (Entry<String, Integer> item : idsMap.entrySet()) { + result = result.replace(item.getKey(), item.getValue().toString()); + } + return result; + } + private boolean searchWhiteLists(WhiteList[] whiteLists, String input, String expected, String result, boolean containsWarning, boolean mayContainWarning, boolean containsError, - boolean mayContainError, boolean ambiguousError) { + boolean mayContainError, boolean ambiguousError, boolean convertReferences) { if (whiteLists == null) { return false; } @@ -584,13 +611,13 @@ public class TestBase { WhiteList.Results wlr = list.get(input); if (wlr != null) { // Sanity check that "expected" matches the entry in the WhiteList - CheckResult checkedResult = checkResult(null, input, wlr.expected, expected, containsWarning, mayContainWarning, containsError, mayContainError, ambiguousError); + CheckResult checkedResult = checkResult(null, input, wlr.expected, expected, containsWarning, mayContainWarning, containsError, mayContainError, ambiguousError, convertReferences); if (!checkedResult.ok) { System.out.println("expected output does not match: " + wlr.expected + " vs. " + expected); return false; } // Substitute the FastR output and try to match that - CheckResult fastRResult = checkResult(null, input, wlr.fastR, result, containsWarning, mayContainWarning, containsError, mayContainError, ambiguousError); + CheckResult fastRResult = checkResult(null, input, wlr.fastR, result, containsWarning, mayContainWarning, containsError, mayContainError, ambiguousError, convertReferences); if (fastRResult.ok) { list.markUsed(input); return true; diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_retracemem.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_retracemem.java deleted file mode 100644 index ae260d0e65b227cb5ccdee90bea38ccda0e052c8..0000000000000000000000000000000000000000 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_retracemem.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This material is distributed under the GNU General Public License - * Version 2. You may review the terms of this license at - * http://www.gnu.org/licenses/gpl-2.0.html - * - * Copyright (c) 2014, Purdue University - * Copyright (c) 2014, 2016, Oracle and/or its affiliates - * - * All rights reserved. - */ -package com.oracle.truffle.r.test.builtins; - -import org.junit.Test; - -import com.oracle.truffle.r.test.TestBase; - -// Checkstyle: stop line length check -public class TestBuiltin_retracemem extends TestBase { - - @Test - public void testretracemem1() { - assertEval(Ignored.Unknown, "argv <- list(FALSE, FALSE);retracemem(argv[[1]],argv[[2]]);"); - } - - @Test - public void testretracemem2() { - assertEval(Ignored.Unknown, - "argv <- list(structure(3.14159265358979, class = structure('3.14159265358979', class = 'testit')), structure(3.14159265358979, class = structure('3.14159265358979', class = 'testit')));retracemem(argv[[1]],argv[[2]]);"); - } -} 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 index ecf20b6ec0a226252b35dc5eeb90d6316af29bdf..7b4e4e6f413c56d80610c894335b45f40983ee96 100644 --- 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 @@ -27,12 +27,32 @@ import org.junit.Test; import com.oracle.truffle.r.test.TestBase; +/** + * Tests tracemem and related builtins. + */ 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)"); + public void argumentErrors() { + assertEval("tracemem(NULL)"); + assertEval("retracemem(NULL)"); + assertEval("retracemem(c(1,10,100), 1:10)"); + } + + @Test + public void vectors() { + assertEval(Output.ContainsReferences, "v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; y[[2]] <- 84"); + assertEval(Output.ContainsReferences, "v <- c(1,10,100); tracemem(v); x <- v; y <- v; x[[1]]<-42; untracemem(v); y[[2]] <- 84"); + } + + @Test + public void list() { + assertEval(Output.ContainsReferences, "v <- list(1,10,100); tracemem(v); x <- v; x[[1]]<-42;"); + } + + @Test + public void retracemem() { + // intended semantics of retracemem is not clear, this tests what is definitely intended: + // retracemem starts tracing of its first argument + assertEval(Output.ContainsReferences, "v <- c(1,10,100); tracemem(v); x <- v[-1]; retracemem(x, retracemem(v)); u <- x; u[[1]] <- 42;"); } } diff --git a/mx.fastr/copyrights/overrides b/mx.fastr/copyrights/overrides index d00961fd8b0f297a0227a0f693c8284c0eda0c20..d96749ae9fc4718ebdb10ce11c9e0a786bbbe931 100644 --- a/mx.fastr/copyrights/overrides +++ b/mx.fastr/copyrights/overrides @@ -566,7 +566,6 @@ com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_reg com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep_len.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rep.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_repint.java,purdue.copyright -com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_retracemem.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_rev.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_round.java,purdue.copyright com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/builtins/TestBuiltin_row.java,purdue.copyright