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)");
+    }
+}