diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
index f53da4a554de3776f26857d0dbc47ace227c45ba..81632089f04e3f910b51f984c761a6d3d5de4a5a 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/REnvironmentMR.java
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.engine.interop;
 
 import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.dsl.Cached;
 import com.oracle.truffle.api.dsl.Fallback;
 import com.oracle.truffle.api.dsl.Specialization;
@@ -39,10 +40,12 @@ import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
 import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentKeyInfoImplNodeGen;
 import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentReadImplNodeGen;
+import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentRemoveImplNodeGen;
 import com.oracle.truffle.r.engine.interop.REnvironmentMRFactory.REnvironmentWriteImplNodeGen;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.access.vector.ReplaceVectorNode;
+import com.oracle.truffle.r.nodes.builtin.base.Rm;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RObject;
 import com.oracle.truffle.r.runtime.env.REnvironment;
@@ -73,6 +76,15 @@ public class REnvironmentMR {
         }
     }
 
+    @Resolve(message = "REMOVE")
+    public abstract static class REnvironmentRemoveNode extends Node {
+        @Child private REnvironmentRemoveImplNode removeNode = REnvironmentRemoveImplNodeGen.create();
+
+        protected Object access(VirtualFrame frame, REnvironment receiver, Object identifier) {
+            return removeNode.execute(frame, receiver, identifier);
+        }
+    }
+
     @Resolve(message = "KEYS")
     public abstract static class REnvironmentKeysNode extends Node {
 
@@ -201,6 +213,41 @@ public class REnvironmentMR {
         }
     }
 
+    abstract static class REnvironmentRemoveImplNode extends Node {
+
+        private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
+
+        protected abstract Object execute(VirtualFrame frame, TruffleObject receiver, Object identifier);
+
+        @Specialization
+        protected Object access(VirtualFrame frame, REnvironment receiver, String identifier,
+                        @Cached("createKeyInfoNode()") REnvironmentKeyInfoImplNode keyInfo) {
+            int info = keyInfo.execute(receiver, identifier);
+            if (unknownIdentifier.profile(!KeyInfo.isExisting(info))) {
+                throw UnknownIdentifierException.raise("" + identifier);
+            }
+            return remove(receiver, identifier);
+        }
+
+        @TruffleBoundary
+        private boolean remove(REnvironment receiver, String identifier) {
+            try {
+                return Rm.removeFromEnv(receiver, identifier, true);
+            } catch (REnvironment.PutException ex) {
+                return false;
+            }
+        }
+
+        @Fallback
+        protected Object access(@SuppressWarnings("unused") TruffleObject receiver, Object identifier) {
+            throw UnknownIdentifierException.raise("" + identifier);
+        }
+
+        protected REnvironmentKeyInfoImplNode createKeyInfoNode() {
+            return REnvironmentKeyInfoImplNodeGen.create();
+        }
+    }
+
     abstract static class REnvironmentKeyInfoImplNode extends Node {
 
         protected abstract int execute(REnvironment receiver, Object identifier);
diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
index f7433458c16cbc4acddd19d78abe95026e7e0015..bcdcb01f5c980b569483a2761eb3c6875d8dbccd 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/Rm.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2018, 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
@@ -77,7 +77,7 @@ public abstract class Rm extends RBuiltinNode.Arg3 {
         return RNull.instance;
     }
 
-    private static boolean removeFromEnv(REnvironment envir, String key, boolean inherits) throws PutException {
+    public static boolean removeFromEnv(REnvironment envir, String key, boolean inherits) throws PutException {
         REnvironment curEnv = envir;
         while (curEnv != REnvironment.emptyEnv()) {
             try {
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REnvironmentMRTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REnvironmentMRTest.java
index 6c55cf3c64e699cd8112d8c844a23c29c1ec1098..7312f09e9032840b159cd9458d775fa77dcc2808 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REnvironmentMRTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/engine/interop/REnvironmentMRTest.java
@@ -128,6 +128,21 @@ public class REnvironmentMRTest extends AbstractMRTest {
         assertFalse(KeyInfo.isInternal(info));
     }
 
+    @Test
+    public void testRemove() throws Exception {
+        assertInteropException(() -> ForeignAccess.sendRemove(Message.REMOVE.createNode(), createEmptyTruffleObject(), "nnoonnee"), UnknownIdentifierException.class);
+
+        REnvironment e = (REnvironment) createTruffleObjects()[0];
+        assertInteropException(() -> ForeignAccess.sendRemove(Message.REMOVE.createNode(), e, "nnoonnee"), UnknownIdentifierException.class);
+
+        assertEquals("aaa", ForeignAccess.sendRead(Message.READ.createNode(), e, "s"));
+        assertEquals(true, ForeignAccess.sendRemove(Message.REMOVE.createNode(), e, "s"));
+        assertInteropException(() -> ForeignAccess.sendRead(Message.READ.createNode(), e, "s"), UnknownIdentifierException.class);
+
+        e.lock(true);
+        assertEquals(false, ForeignAccess.sendRemove(Message.REMOVE.createNode(), e, "i"));
+    }
+
     @Override
     protected TruffleObject[] createTruffleObjects() throws Exception {
         Source src = Source.newBuilder("R", "e <- new.env(); e$s <- 'aaa'; e$i <- 123L; e$d <- 123.1; e$b <- TRUE; e$fn <- function() {}; e$n <- NULL; e$l <- 666; lockBinding('l', e); e",
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
index a08bb5bcb29dee37e8d069f979b2041abbff924c..d6e9c827b8c1402b42d3cb2555870c936979928f 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java
@@ -361,7 +361,7 @@ public final class FastRSession implements RSession {
     }
 
     public static void execInContext(Context context, Callable<Object> c) {
-        execInContext(context, c, (Class<?>) null);
+        execInContext(context, c, (Class<?>[]) null);
     }
 
     // TODO: export/importSymbol