diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
index 004ef00391e0417bea13374007b7cf7421d7806b..80b3c4825c488fbe72a1871538349bae34b237c6 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/REngine.java
@@ -22,8 +22,6 @@
  */
 package com.oracle.truffle.r.engine;
 
-import java.io.PrintStream;
-import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -365,9 +363,7 @@ final class REngine implements Engine, Engine.Timings {
         @Override
         @ExplodeLoop
         public Object execute(VirtualFrame frame) {
-            RContext oldContext = RContext.getThreadLocalInstance();
-            RContext newContext = contextReference.get();
-            RContext.setThreadLocalInstance(newContext);
+            Object actualFrame = executionFrame != null ? executionFrame : contextReference.get().stateREnvironment.getGlobalFrame();
             try {
                 Object lastValue = RNull.instance;
                 for (int i = 0; i < calls.length; i++) {
@@ -376,7 +372,7 @@ final class REngine implements Engine, Engine.Timings {
                         RSyntaxNode node = statements.get(i);
                         calls[i] = insert(Truffle.getRuntime().createDirectCallNode(doMakeCallTarget(node.asRNode(), RSource.Internal.REPL_WRAPPER.string, printResult, true)));
                     }
-                    lastValue = calls[i].call(new Object[]{executionFrame != null ? executionFrame : newContext.stateREnvironment.getGlobalFrame()});
+                    lastValue = calls[i].call(new Object[]{actualFrame});
                 }
                 return r2Foreign.execute(lastValue);
             } catch (ReturnException ex) {
@@ -392,8 +388,6 @@ final class REngine implements Engine, Engine.Timings {
                 // other errors didn't produce an output yet
                 RInternalError.reportError(t);
                 throw t;
-            } finally {
-                RContext.setThreadLocalInstance(oldContext);
             }
         }
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
index bc856523e38aec4a9c68afcbb73dbd27f968fffa..986d0bebe7fae527b2c137e375148ddde6287f69 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/RRuntimeASTAccessImpl.java
@@ -735,4 +735,9 @@ class RRuntimeASTAccessImpl implements RRuntimeASTAccess {
     public RAbstractStringVector getClassHierarchy(RAttributable value) {
         return ClassHierarchyNode.getClassHierarchy(value);
     }
+
+    @Override
+    public RContext getCurrentContext() {
+        return TruffleRLanguageImpl.getCurrentContext();
+    }
 }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
index 79b5ec7640fd6c94afff6e6c916ddada9236641f..a5d4ef1cf9be2b54b94d33b42e619386e88ca2e6 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguageImpl.java
@@ -27,17 +27,13 @@ import java.util.Locale;
 
 import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerAsserts;
-import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.frame.Frame;
-import com.oracle.truffle.api.frame.FrameDescriptor;
-import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
 import com.oracle.truffle.api.instrumentation.ProvidedTags;
 import com.oracle.truffle.api.instrumentation.StandardTags;
 import com.oracle.truffle.api.metadata.ScopeProvider;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.api.nodes.RootNode;
 import com.oracle.truffle.api.source.SourceSection;
 import com.oracle.truffle.r.engine.interop.RForeignAccessFactoryImpl;
 import com.oracle.truffle.r.nodes.RASTBuilder;
@@ -48,13 +44,11 @@ import com.oracle.truffle.r.runtime.ExitException;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RAccuracyInfo;
 import com.oracle.truffle.r.runtime.RDeparse;
-import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.Engine.IncompleteSourceException;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.context.TruffleRLanguage;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RPromise;
@@ -64,7 +58,6 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
 import com.oracle.truffle.r.runtime.interop.R2Foreign;
 import com.oracle.truffle.r.runtime.interop.R2ForeignNodeGen;
 import com.oracle.truffle.r.runtime.nodes.RBaseNode;
-import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
 @TruffleLanguage.Registration(name = "R", id = "R", version = "3.3.2", mimeType = {RRuntime.R_APP_MIME, RRuntime.R_TEXT_MIME}, interactive = true)
 @ProvidedTags({StandardTags.CallTag.class, StandardTags.StatementTag.class, StandardTags.RootTag.class, RSyntaxTags.LoopTag.class})
@@ -197,39 +190,14 @@ public final class TruffleRLanguageImpl extends TruffleRLanguage implements Scop
     }
 
     @Override
-    @SuppressWarnings("try")
     protected CallTarget parse(ParsingRequest request) throws Exception {
         CompilerAsserts.neverPartOfCompilation();
-        try (RCloseable c = RContext.withinContext(getCurrentContext())) {
-            try {
-                return RContext.getEngine().parseToCallTarget(request.getSource(), request.getFrame());
-            } catch (IncompleteSourceException e) {
-                throw e;
-            } catch (ParseException e) {
-                return Truffle.getRuntime().createCallTarget(new RootNode(this, new FrameDescriptor()) {
-                    @Override
-                    public SourceSection getSourceSection() {
-                        return RSyntaxNode.INTERNAL;
-                    }
-
-                    @Override
-                    public Object execute(VirtualFrame frame) {
-                        throw e.throwAsRError();
-                    }
-                });
-            } catch (RError e) {
-                return Truffle.getRuntime().createCallTarget(new RootNode(this, new FrameDescriptor()) {
-                    @Override
-                    public SourceSection getSourceSection() {
-                        return RSyntaxNode.INTERNAL;
-                    }
-
-                    @Override
-                    public Object execute(VirtualFrame frame) {
-                        throw e;
-                    }
-                });
-            }
+        try {
+            return RContext.getEngine().parseToCallTarget(request.getSource(), request.getFrame());
+        } catch (IncompleteSourceException e) {
+            throw e;
+        } catch (ParseException e) {
+            throw e.throwAsRError();
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
index ef205296b94a58d1cd5781c99e1179cd2bf6fd2a..7ea156016dc9d6352903d006d7200915237019de 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ActiveBindingMR.java
@@ -27,9 +27,6 @@ import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.env.frame.ActiveBinding;
 
 @MessageResolution(receiverType = ActiveBinding.class)
@@ -58,11 +55,8 @@ public class ActiveBindingMR {
     @Resolve(message = "UNBOX")
     public abstract static class ActiveBindingUnboxNode extends Node {
 
-        @SuppressWarnings("try")
         protected Object access(ActiveBinding receiver) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                return receiver.readValue();
-            }
+            return receiver.readValue();
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
index b21cd2e4105233b5361eeb97df5505c7a8f6b970..8453af22c21ab96832e32b20759ab70f81d90a5f 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RAbstractVectorAccessFactory.java
@@ -38,8 +38,6 @@ import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
 import com.oracle.truffle.r.nodes.control.RLengthNode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.model.RAbstractVector;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
@@ -74,13 +72,10 @@ public final class RAbstractVectorAccessFactory implements Factory26 {
         @Child private RLengthNode lengthNode = RLengthNode.create();
 
         @Override
-        @SuppressWarnings("try")
         public final Object execute(VirtualFrame frame) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                Object label = ForeignAccess.getArguments(frame).get(0);
-                Object receiver = ForeignAccess.getReceiver(frame);
-                return execute(frame, receiver, label);
-            }
+            Object label = ForeignAccess.getArguments(frame).get(0);
+            Object receiver = ForeignAccess.getReceiver(frame);
+            return execute(frame, receiver, label);
         }
 
         protected abstract Object execute(VirtualFrame frame, Object reciever, Object label);
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 15c38d4b1af3c79cb3e101a46cbb75d6efe584d1..9105faed06c9f63a1c6fdc75757ddb25c049e8d8 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
@@ -26,17 +26,16 @@ import static com.oracle.truffle.r.engine.interop.Utils.javaToRPrimitive;
 
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.KeyInfo;
+import com.oracle.truffle.api.interop.KeyInfo.Builder;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 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.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 
 @MessageResolution(receiverType = REnvironment.class)
@@ -75,11 +74,8 @@ public class REnvironmentMR {
     public abstract static class REnvironmentReadNode extends Node {
         @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
 
-        @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, REnvironment receiver, String field) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                return extract.applyAccessField(frame, receiver, field);
-            }
+            return extract.applyAccessField(frame, receiver, field);
         }
     }
 
@@ -87,13 +83,9 @@ public class REnvironmentMR {
     public abstract static class REnvironmentWriteNode extends Node {
         @Child private ReplaceVectorNode extract = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
 
-        @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, REnvironment receiver, String field, Object valueObj) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                Object value = javaToRPrimitive(valueObj);
-                Object x = extract.apply(frame, receiver, new Object[]{field}, value);
-                return x;
-            }
+            Object value = javaToRPrimitive(valueObj);
+            return extract.apply(frame, receiver, new Object[]{field}, value);
         }
     }
 
@@ -108,21 +100,17 @@ public class REnvironmentMR {
     @Resolve(message = "KEY_INFO")
     public abstract static class REnvironmentKeyInfoNode extends Node {
 
-        private static final int EXISTS = 1 << 0;
-        private static final int READABLE = 1 << 1;
-        private static final int WRITABLE = 1 << 2;
-
-        protected Object access(@SuppressWarnings("unused") VirtualFrame frame, REnvironment receiver, String identifier) {
+        protected Object access(REnvironment receiver, String identifier) {
             Object val = receiver.get(identifier);
             if (val == null) {
                 return 0;
             }
-
-            int info = READABLE | EXISTS;
+            Builder builder = KeyInfo.newBuilder();
+            builder.setReadable(true);
             if (!receiver.isLocked() && !receiver.bindingIsLocked(identifier)) {
-                info += WRITABLE;
+                builder.setWritable(true);
             }
-            return info;
+            return builder.build();
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
index 1977e7fa47dfd980f0d4ef520281ab4c6cbf5c46..191e2ab1d193921a84a6671dcc5c7472f333bc34 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RFunctionMR.java
@@ -32,13 +32,10 @@ import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.nodes.function.RCallBaseNode;
 import com.oracle.truffle.r.nodes.function.RCallNode;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.RArguments;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.env.frame.FrameSlotChangeMonitor;
@@ -65,13 +62,12 @@ public class RFunctionMR {
 
         @Child private RCallBaseNode call = RCallNode.createExplicitCall(argsIdentifier);
 
-        @SuppressWarnings("try")
         protected Object access(RFunction receiver, Object[] arguments) {
             Object[] dummyFrameArgs = RArguments.createUnitialized();
             VirtualFrame dummyFrame = Truffle.getRuntime().createVirtualFrame(dummyFrameArgs, emptyFrameDescriptor);
 
             RArgsValuesAndNames actualArgs = new RArgsValuesAndNames(arguments, ArgumentsSignature.empty(arguments.length));
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
+            try {
                 FrameSlotChangeMonitor.setObject(dummyFrame, slot, actualArgs);
                 return call.execute(dummyFrame, receiver);
             } finally {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
index 27a0b494189c139fa256dbeb72d44024b204fe69..701d96249d63f209a1badcbea2db36949b3948f6 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RLanguageMR.java
@@ -30,11 +30,8 @@ import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.nodes.access.vector.ElementAccessMode;
 import com.oracle.truffle.r.nodes.access.vector.ExtractVectorNode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RLanguage;
 import com.oracle.truffle.r.runtime.data.RLogical;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -67,11 +64,8 @@ public class RLanguageMR {
     public abstract static class RLanguageReadNode extends Node {
         @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
 
-        @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, RLanguage receiver, int label) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                return extract.apply(frame, receiver, new Object[]{label + 1}, RLogical.TRUE, RLogical.TRUE);
-            }
+            return extract.apply(frame, receiver, new Object[]{label + 1}, RLogical.TRUE, RLogical.TRUE);
         }
     }
 
@@ -79,7 +73,7 @@ public class RLanguageMR {
     public abstract static class RLanguageWriteNode extends Node {
 
         @SuppressWarnings("unused")
-        protected Object access(VirtualFrame frame, RLanguage receiver, int label, Object valueObj) {
+        protected Object access(RLanguage receiver, int label, Object valueObj) {
             throw UnsupportedMessageException.raise(Message.WRITE);
         }
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
index afe4aa3f7e822ac7f7089dd8521cb300cbbdbcab..2501226929587783cc413eba72957ac64508654d 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RListMR.java
@@ -27,19 +27,18 @@ import static com.oracle.truffle.r.engine.interop.Utils.javaToRPrimitive;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.KeyInfo;
+import com.oracle.truffle.api.interop.KeyInfo.Builder;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.profiles.ConditionProfile;
-import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 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.attributes.SpecialAttributesFunctions.GetNamesAttributeNode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -73,11 +72,8 @@ public class RListMR {
     public abstract static class RListReadNode extends Node {
         @Child private ExtractVectorNode extract = ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
 
-        @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, RList receiver, String field) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                return extract.applyAccessField(frame, receiver, field);
-            }
+            return extract.applyAccessField(frame, receiver, field);
         }
     }
 
@@ -85,12 +81,9 @@ public class RListMR {
     public abstract static class RListWriteNode extends Node {
         @Child private ReplaceVectorNode replace = ReplaceVectorNode.create(ElementAccessMode.SUBSCRIPT, true);
 
-        @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, RList receiver, String field, Object valueObj) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                Object value = javaToRPrimitive(valueObj);
-                return replace.apply(frame, receiver, new Object[]{field}, value);
-            }
+            Object value = javaToRPrimitive(valueObj);
+            return replace.apply(frame, receiver, new Object[]{field}, value);
         }
     }
 
@@ -98,12 +91,9 @@ public class RListMR {
     public abstract static class RListKeysNode extends Node {
         @Child private GetNamesAttributeNode getNamesNode = GetNamesAttributeNode.create();
 
-        @SuppressWarnings("try")
         protected Object access(RList receiver) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                RStringVector names = getNamesNode.getNames(receiver);
-                return names != null ? names : RNull.instance;
-            }
+            RStringVector names = getNamesNode.getNames(receiver);
+            return names != null ? names : RNull.instance;
         }
     }
 
@@ -114,38 +104,28 @@ public class RListMR {
 
         private final ConditionProfile unknownIdentifier = ConditionProfile.createBinaryProfile();
 
-        private static final int EXISTS = 1 << 0;
-        private static final int READABLE = 1 << 1;
-        private static final int WRITABLE = 1 << 2;
-        private static final int INVOCABLE = 1 << 3;
-        @SuppressWarnings("unused") private static final int INTERNAL = 1 << 4;
-
-        @SuppressWarnings("try")
         protected Object access(VirtualFrame frame, RList receiver, String identifier) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                int info = 0;
-                RStringVector names = getNamesNode.getNames(receiver);
-                for (int i = 0; i < names.getLength(); i++) {
-                    if (identifier.equals(names.getDataAt(i))) {
-                        info = EXISTS;
-                        break;
-                    }
-                }
-                if (unknownIdentifier.profile(info == 0)) {
-                    return info;
+            RStringVector names = getNamesNode.getNames(receiver);
+            boolean exists = false;
+            for (int i = 0; i < names.getLength(); i++) {
+                if (identifier.equals(names.getDataAt(i))) {
+                    exists = true;
+                    break;
                 }
+            }
+            if (unknownIdentifier.profile(!exists)) {
+                return 0;
+            }
 
-                info = info + READABLE + WRITABLE;
-                if (extractNode == null) {
-                    CompilerDirectives.transferToInterpreterAndInvalidate();
-                    extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
-                }
-                Object value = extractNode.applyAccessField(frame, receiver, identifier);
-                if (value instanceof RFunction) {
-                    info = info + INVOCABLE;
-                }
-                return info;
+            Builder builder = KeyInfo.newBuilder();
+            builder.setReadable(true).setWritable(true);
+            if (extractNode == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                extractNode = insert(ExtractVectorNode.create(ElementAccessMode.SUBSCRIPT, true));
             }
+            Object value = extractNode.applyAccessField(frame, receiver, identifier);
+            builder.setInvocable(value instanceof RFunction);
+            return builder.build();
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
index f6c2d234a27174bb5413b1f749db5f229bd96f52..fc12c99c4c2c594a6c37042e634ebb678d18e814 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RPromiseMR.java
@@ -24,18 +24,16 @@ package com.oracle.truffle.r.engine.interop;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.interop.CanResolve;
+import com.oracle.truffle.api.interop.KeyInfo;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.interop.UnsupportedTypeException;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.ffi.impl.interop.NativePointer;
 import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
 import com.oracle.truffle.r.runtime.RRuntime;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RPromise;
@@ -64,13 +62,10 @@ public class RPromiseMR {
     @Resolve(message = "READ")
     public abstract static class RPromiseReadNode extends Node {
 
-        @SuppressWarnings("try")
         @TruffleBoundary
         protected Object access(RPromise receiver, String field) {
             if (PROP_EXPR.equals(field)) {
-                try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                    return RDataFactory.createLanguage(receiver.getRep());
-                }
+                return RDataFactory.createLanguage(receiver.getRep());
             }
             if (PROP_IS_EVALUATED.equals(field)) {
                 return RRuntime.asLogical(receiver.isEvaluated());
@@ -89,7 +84,6 @@ public class RPromiseMR {
     @Resolve(message = "WRITE")
     public abstract static class RPromiseWriteNode extends Node {
 
-        @SuppressWarnings("try")
         protected Object access(RPromise receiver, String field, Object valueObj) {
             if (PROP_IS_EVALUATED.equals(field)) {
                 if (!(valueObj instanceof Boolean)) {
@@ -97,16 +91,10 @@ public class RPromiseMR {
                 }
 
                 boolean newVal = (boolean) valueObj;
-
                 if (!receiver.isEvaluated() && newVal) {
-                    try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                        PromiseHelperNode.evaluateSlowPath(receiver);
-                    }
+                    PromiseHelperNode.evaluateSlowPath(receiver);
                 } else if (receiver.isEvaluated() && !newVal) {
-                    try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                        receiver.resetValue();
-                    }
-
+                    receiver.resetValue();
                 }
                 return RRuntime.asLogical(receiver.isEvaluated());
             }
@@ -125,19 +113,14 @@ public class RPromiseMR {
     @Resolve(message = "KEY_INFO")
     public abstract static class RPromiseKeyInfoNode extends Node {
 
-        private static final int EXISTS = 1 << 0;
-        private static final int READABLE = 1 << 1;
-        private static final int WRITABLE = 1 << 2;
-
         protected Object access(@SuppressWarnings("unused") RPromise receiver, String identifier) {
             if (PROP_EXPR.equals(identifier) || PROP_VALUE.equals(identifier)) {
-                return EXISTS + READABLE;
-            }
-
-            if (PROP_IS_EVALUATED.equals(identifier)) {
-                return EXISTS + READABLE + WRITABLE;
+                return KeyInfo.newBuilder().setReadable(true).build();
+            } else if (PROP_IS_EVALUATED.equals(identifier)) {
+                return KeyInfo.newBuilder().setReadable(true).setWritable(true).build();
+            } else {
+                return 0;
             }
-            return 0;
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
index cb43f9ecc2be4de4f8d0b92dfb5cafe28c706035..084b6d390d0d88da68bb959c763d3f235c81782d 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/RS4ObjectMR.java
@@ -27,12 +27,9 @@ import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.nodes.Node;
-import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.nodes.attributes.ArrayAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.GetAttributeNode;
 import com.oracle.truffle.r.nodes.attributes.SetAttributeNode;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RAttributesLayout.RAttribute;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RS4Object;
@@ -65,11 +62,8 @@ public class RS4ObjectMR {
     public abstract static class RS4ObjectReadNode extends Node {
         @Child private GetAttributeNode getAttributeNode = GetAttributeNode.create();
 
-        @SuppressWarnings("try")
         protected Object access(RS4Object receiver, String field) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                return getAttributeNode.execute(receiver, field);
-            }
+            return getAttributeNode.execute(receiver, field);
         }
     }
 
@@ -77,13 +71,10 @@ public class RS4ObjectMR {
     public abstract static class RS4ObjectWriteNode extends Node {
         @Child private SetAttributeNode setAttributeNode = SetAttributeNode.create();
 
-        @SuppressWarnings("try")
         protected Object access(RS4Object receiver, String field, Object valueObj) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                Object value = Utils.javaToRPrimitive(valueObj);
-                setAttributeNode.execute(receiver, field, value);
-                return value;
-            }
+            Object value = Utils.javaToRPrimitive(valueObj);
+            setAttributeNode.execute(receiver, field, value);
+            return value;
         }
     }
 
@@ -91,16 +82,13 @@ public class RS4ObjectMR {
     public abstract static class RS4ObjectKeysNode extends Node {
         @Child private ArrayAttributeNode arrayAttrAccess = ArrayAttributeNode.create();
 
-        @SuppressWarnings("try")
         protected Object access(RS4Object receiver) {
-            try (RCloseable c = RContext.withinContext(TruffleRLanguageImpl.getCurrentContext())) {
-                RAttribute[] attributes = arrayAttrAccess.execute(receiver.getAttributes());
-                String[] data = new String[attributes.length];
-                for (int i = 0; i < data.length; i++) {
-                    data[i] = attributes[i].getName();
-                }
-                return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
+            RAttribute[] attributes = arrayAttrAccess.execute(receiver.getAttributes());
+            String[] data = new String[attributes.length];
+            for (int i = 0; i < data.length; i++) {
+                data[i] = attributes[i].getName();
             }
+            return RDataFactory.createStringVector(data, RDataFactory.COMPLETE_VECTOR);
         }
     }
 
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
index 9169ded7d1bf42b99cecca439c26f1209f98b772..39a0b3a60a18f252a2eff6dd03659035ca427d31 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/REmbedded.java
@@ -24,6 +24,7 @@ package com.oracle.truffle.r.engine.shell;
 
 import org.graalvm.polyglot.Context;
 import org.graalvm.polyglot.Engine;
+import org.graalvm.polyglot.Source;
 
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.launcher.ConsoleHandler;
@@ -80,7 +81,7 @@ public class REmbedded {
         try (Context cntx = Context.newBuilder().arguments("R", options.getArguments()).in(consoleHandler.createInputStream()).out(System.out).err(System.err).build()) {
             context = cntx;
             consoleHandler.setContext(context);
-            context.eval("R", INIT);
+            context.eval(INIT);
         }
     }
 
@@ -89,7 +90,7 @@ public class REmbedded {
      * is evaluated the R builtins have not been installed, see {@link #initializeR}. The
      * suppression of printing is handled a a special case based on {@link Internal#INIT_EMBEDDED}.
      */
-    private static final String INIT = "1";
+    private static final Source INIT = Source.newBuilder("R", "1", "<embedded>").buildLiteral();
 
     /**
      * GnuR distinguishes {@code setup_Rmainloop} and {@code run_Rmainloop}. Currently we don't have
diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java
index b1c670fe8adcf88b98cd7d12d75f60dadda3c8e0..12888c364f4141f263e7fc476fd38cc9298c1874 100644
--- a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java
+++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/JLineConsoleCompleter.java
@@ -27,6 +27,7 @@ import java.util.Collections;
 import java.util.List;
 
 import org.graalvm.polyglot.Context;
+import org.graalvm.polyglot.Source;
 import org.graalvm.polyglot.Value;
 
 import jline.console.completer.Completer;
@@ -56,18 +57,17 @@ public class JLineConsoleCompleter implements Completer {
         }
     }
 
-    private static final String GET_COMPLETION_FUNCTION = "utils:::.completeToken";
-    private static final String GET_COMPLETION_ENV = "utils:::.CompletionEnv";
-    private static final String SET_FUNCTION = "`$<-`";
+    private static final Source GET_COMPLETION_FUNCTION = Source.newBuilder("R", "utils:::.completeToken", "<completion>").internal(true).buildLiteral();
+    private static final Source GET_COMPLETION_ENV = Source.newBuilder("R", "utils:::.CompletionEnv", "<completion>").internal(true).buildLiteral();
+    private static final Source SET_FUNCTION = Source.newBuilder("R", "`$<-`", "<completion>").internal(true).buildLiteral();
 
-    @SuppressWarnings("try")
     private int completeImpl(String buffer, int cursor, List<CharSequence> candidates) {
         if (buffer.isEmpty()) {
             return cursor;
         }
-        Value completionFunction = context.eval("R", GET_COMPLETION_FUNCTION);
-        Value completionEnv = context.eval("R", GET_COMPLETION_ENV);
-        Value setFunction = context.eval("R", SET_FUNCTION);
+        Value completionFunction = context.eval(GET_COMPLETION_FUNCTION);
+        Value completionEnv = context.eval(GET_COMPLETION_ENV);
+        Value setFunction = context.eval(SET_FUNCTION);
 
         int start = getStart(buffer, completionEnv, cursor);
         setFunction.execute(completionEnv, "start", start);
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
index 8b987fccbc9323da54508a8f38f45ec3fe0d584b..5c254881f4a0f3a4297d47eaa84b00e5b36427b0 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/SpecialCallTest.java
@@ -26,17 +26,15 @@ import org.junit.Assert;
 import org.junit.Test;
 
 import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.r.engine.TruffleRLanguageImpl;
 import com.oracle.truffle.r.runtime.ArgumentsSignature;
 import com.oracle.truffle.r.runtime.FastROptions;
 import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RootWithBody;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RLanguage;
-import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxCall;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxConstant;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxElement;
@@ -261,7 +259,6 @@ public class SpecialCallTest extends TestBase {
         assertCallCounts("{}", test, initialSpecialCount, initialNormalCount, finalSpecialCount, finalNormalCount);
     }
 
-    @SuppressWarnings("try")
     private static void assertCallCounts(String setup, String test, int initialSpecialCount, int initialNormalCount, int finalSpecialCount, int finalNormalCount) {
         if (!FastROptions.UseSpecials.getBooleanValue()) {
             return;
@@ -276,14 +273,15 @@ public class SpecialCallTest extends TestBase {
         RootCallTarget setupCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) setupExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test");
         RootCallTarget testCallTarget = testVMContext.getThisEngine().makePromiseCallTarget(((RLanguage) testExpression.getDataAt(0)).getRep().asRSyntaxNode().asRNode(), "test");
 
-        try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) {
+        try {
             CountCallsVisitor count1 = new CountCallsVisitor(testCallTarget);
             Assert.assertEquals("initial special call count '" + setup + "; " + test + "': ", initialSpecialCount, count1.special);
             Assert.assertEquals("initial normal call count '" + setup + "; " + test + "': ", initialNormalCount, count1.normal);
 
+            MaterializedFrame frame = TestBase.testVMContext.stateREnvironment.getGlobalFrame();
             try {
-                setupCallTarget.call(REnvironment.globalEnv().getFrame());
-                testCallTarget.call(REnvironment.globalEnv().getFrame());
+                setupCallTarget.call(frame);
+                testCallTarget.call(frame);
             } catch (RError e) {
                 // ignore
             }
@@ -293,8 +291,8 @@ public class SpecialCallTest extends TestBase {
             Assert.assertEquals("normal call count after first call '" + setup + "; " + test + "': ", finalNormalCount, count2.normal);
 
             try {
-                setupCallTarget.call(REnvironment.globalEnv().getFrame());
-                testCallTarget.call(REnvironment.globalEnv().getFrame());
+                setupCallTarget.call(frame);
+                testCallTarget.call(frame);
             } catch (RError e) {
                 // ignore
             }
diff --git a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
index 5f0f984f6338767b92c2dd43e71082c93c2573c0..8e376cf64bbe3e43a351374b045eeccc677c3649 100644
--- a/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
+++ b/com.oracle.truffle.r.nodes.test/src/com/oracle/truffle/r/nodes/test/TestUtilities.java
@@ -35,8 +35,6 @@ import com.oracle.truffle.r.runtime.RArguments;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RType;
 import com.oracle.truffle.r.runtime.ReturnException;
-import com.oracle.truffle.r.runtime.context.RContext;
-import com.oracle.truffle.r.runtime.context.RContext.RCloseable;
 import com.oracle.truffle.r.runtime.data.RComplex;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -160,11 +158,8 @@ public class TestUtilities {
      * Certain code needs to be run within valid RContext, e.g. copying, which tries to report to
      * memory tracer taken from RContext.
      */
-    @SuppressWarnings("try")
     public static <T> T withinTestContext(Supplier<T> action) {
-        try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) {
-            return action.get();
-        }
+        return action.get();
     }
 
     /**
@@ -198,11 +193,8 @@ public class TestUtilities {
             return ((TestRoot<T>) target.getRootNode()).node;
         }
 
-        @SuppressWarnings("try")
         public Object call(Object... args) {
-            try (RCloseable c = RContext.withinContext(TestBase.testVMContext)) {
-                return target.call(RArguments.createUnitialized((Object) args));
-            }
+            return target.call(RArguments.createUnitialized((Object) args));
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
index b1f6ab646e44b0907a59c040ccdd8e1de9f7fe2d..fe78327aeb55db9317feefacba162cdefeb53f8e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RRuntimeASTAccess.java
@@ -203,4 +203,6 @@ public interface RRuntimeASTAccess {
     void checkDebugRequest(RFunction func);
 
     RAbstractStringVector getClassHierarchy(RAttributable value);
+
+    RContext getCurrentContext();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java
index 61cab9d33c37f0f8f92fcc4fbc46cd1d35a178f6..ac0107b5f77a5248213598d9cfc57ff95e4583b4 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java
@@ -36,7 +36,6 @@ import com.oracle.truffle.r.runtime.RError;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.context.Engine.ParseException;
-import com.oracle.truffle.r.runtime.context.RContext.ContextThread;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RList;
 import com.oracle.truffle.r.runtime.data.RNull;
@@ -44,7 +43,7 @@ import com.oracle.truffle.r.runtime.data.RNull;
 /**
  * A thread for performing an evaluation (used by {@code .fastr} builtins).
  */
-public class EvalThread extends ContextThread {
+public class EvalThread extends Thread {
 
     private final Source source;
     private final ContextInfo info;
@@ -60,7 +59,6 @@ public class EvalThread extends ContextThread {
     public static final AtomicInteger threadCnt = new AtomicInteger(0);
 
     public EvalThread(ContextInfo info, Source source) {
-        super(null);
         this.info = info;
         this.source = source;
         threadCnt.incrementAndGet();
@@ -71,11 +69,6 @@ public class EvalThread extends ContextThread {
     @Override
     public void run() {
         PolyglotEngine vm = info.createVM(PolyglotEngine.newBuilder());
-        try {
-            setContext(vm.eval(Engine.GET_CONTEXT).as(RContext.class));
-        } catch (Throwable t) {
-            throw new RInternalError(t, "error while initializing eval thread");
-        }
         init.release();
         try {
             evalResult = run(vm, info, source);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
index a921bd0a56251c74bad87338690aadc9d1880957..d9f72a3fe20ca587b70955b045008845df1da253 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/RContext.java
@@ -24,7 +24,6 @@ package com.oracle.truffle.r.runtime.context;
 
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
-import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -49,7 +48,6 @@ import java.util.concurrent.Executor;
 import java.util.function.Supplier;
 
 import com.oracle.truffle.api.Assumption;
-import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.RootCallTarget;
@@ -221,21 +219,6 @@ public final class RContext implements RTruffleObject {
         }
     }
 
-    /**
-     * A thread that is explicitly associated with a context for efficient lookup.
-     */
-    public abstract static class ContextThread extends Thread {
-        protected RContext context;
-
-        public ContextThread(RContext context) {
-            this.context = context;
-        }
-
-        public void setContext(RContext context) {
-            this.context = context;
-        }
-    }
-
     private final RStartParams startParameters;
     private final RCmdOptions cmdOptions;
     private final String[] environment;
@@ -280,16 +263,6 @@ public final class RContext implements RTruffleObject {
      */
     private RContext sharedChild;
 
-    /**
-     * Typically there is a 1-1 relationship between an {@link RContext} and the thread that is
-     * performing the evaluation, so we can store the {@link RContext} in a {@link ThreadLocal}.
-     *
-     * When a context is first created no threads are attached, to allow contexts to be used as
-     * values in the experimental {@code fastr.context.xxx} functions. Additional threads can be
-     * added by the {@link #attachThread} method.
-     */
-    private static final ThreadLocal<RContext> threadLocalContext = new ThreadLocal<>();
-
     /**
      * Used by the MethodListDispatch class.
      */
@@ -335,21 +308,6 @@ public final class RContext implements RTruffleObject {
         RContext.foreignAccessFactory = rForeignAccessFactory;
     }
 
-    /**
-     * Associates this {@link RContext} with the current thread.
-     */
-    private void attachThread() {
-        Thread current = Thread.currentThread();
-        if (current instanceof ContextThread) {
-            ((ContextThread) current).setContext(this);
-        } else {
-            threadLocalContext.set(this);
-        }
-    }
-
-    private static final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("single RContext");
-    @CompilationFinal private static RContext singleContext;
-
     // need an additional flag as we don't want multi-slot processing to start until context
     // initialization is fully complete - singleContext flag is not good enough for that
     private static final Assumption isSingleContextAssumption = Truffle.getRuntime().createAssumption("is single RContext");
@@ -512,25 +470,9 @@ public final class RContext implements RTruffleObject {
             }
         }
 
-        if (singleContextAssumption.isValid()) {
-            if (singleContext == null) {
-                singleContext = this;
-            } else {
-                singleContext = null;
-                singleContextAssumption.invalidate();
-            }
-        }
-
         /*
-         * Activate the context by attaching the current thread and initializing the {@link
-         * ContextState} objects. Note that we attach the thread before creating the new context
-         * state. This means that code that accesses the state through this interface will receive a
-         * {@code null} value. Access to the parent state is available through the {@link RContext}
-         * argument passed to the newContext methods. It might be better to attach the thread after
-         * state creation but it is a finely balanced decision and risks incorrectly accessing the
-         * parent state.
+         * Activate the context by initializing the {@link ContextState} objects.
          */
-        attachThread();
         state.add(State.ATTACHED);
 
         stateDLL.initialize(this);
@@ -622,11 +564,6 @@ public final class RContext implements RTruffleObject {
             if (contextKind == ContextKind.SHARE_PARENT_RW) {
                 parentContext.sharedChild = null;
             }
-            if (parentContext == null) {
-                threadLocalContext.set(null);
-            } else {
-                threadLocalContext.set(parentContext);
-            }
             state = EnumSet.of(State.DESTROYED);
 
             this.allocationReporter.removePropertyChangeListener(ALLOCATION_ACTIVATION_LISTENER);
@@ -657,24 +594,6 @@ public final class RContext implements RTruffleObject {
         return multiSlotIndex;
     }
 
-    @TruffleBoundary
-    public static RContext getThreadLocalInstance() {
-        return threadLocalContext.get();
-    }
-
-    @TruffleBoundary
-    public static void setThreadLocalInstance(RContext context) {
-        threadLocalContext.set(context);
-    }
-
-    @TruffleBoundary
-    private static RContext getInstanceInternal() {
-        RContext result = threadLocalContext.get();
-        assert result != null;
-        assert result.state.contains(State.ATTACHED);
-        return result;
-    }
-
     public static boolean isSingle() {
         return isSingleContextAssumption.isValid();
     }
@@ -684,19 +603,7 @@ public final class RContext implements RTruffleObject {
     }
 
     public static RContext getInstance() {
-        RContext context = singleContext;
-        if (singleContextAssumption.isValid() && context != null) {
-            return context;
-        }
-
-        Thread current = Thread.currentThread();
-        if (current instanceof ContextThread) {
-            context = ((ContextThread) current).context;
-            assert context != null;
-            return context;
-        } else {
-            return getInstanceInternal();
-        }
+        return getRRuntimeASTAccess().getCurrentContext();
     }
 
     public boolean isInteractive() {
@@ -873,23 +780,6 @@ public final class RContext implements RTruffleObject {
         nameSpaceName = name;
     }
 
-    public interface RCloseable extends Closeable {
-        @Override
-        void close();
-    }
-
-    @TruffleBoundary
-    public static RCloseable withinContext(RContext context) {
-        RContext oldContext = RContext.threadLocalContext.get();
-        RContext.threadLocalContext.set(context);
-        return new RCloseable() {
-            @Override
-            public void close() {
-                RContext.threadLocalContext.set(oldContext);
-            }
-        };
-    }
-
     public static Class<? extends TruffleRLanguage> getTruffleRLanguage() {
         return getRRuntimeASTAccess().getTruffleRLanguage();
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
index 56ac7016f2aeca68bf68e7df478fa14287a4b246..a8732baf2dead304863c9507c6435c52e6a99226 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/RDataFactory.java
@@ -610,7 +610,7 @@ public final class RDataFactory {
     private static void reportDataCreated(Object data) {
         System.out.println("reportDataCreated " + listeners.size() + " " + allocationTracingEnabled);
         if (allocationTracingEnabled) {
-            RContext ctx = RContext.getThreadLocalInstance();
+            RContext ctx = RContext.getInstance();
             assert ctx != null;
             AllocationReporter allocationReporter = ctx.getAllocationReporter();
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
index 109ab37220eeaa8de066c384fe5a973e25e1fd4c..1a54cbda4f88dfb9e5187581e27d847291a1b39d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/RScope.java
@@ -26,6 +26,8 @@ import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.frame.Frame;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.interop.ForeignAccess;
+import com.oracle.truffle.api.interop.KeyInfo;
+import com.oracle.truffle.api.interop.KeyInfo.Builder;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.MessageResolution;
 import com.oracle.truffle.api.interop.Resolve;
@@ -220,22 +222,17 @@ public final class RScope extends AbstractScope {
             @Resolve(message = "KEY_INFO")
             public abstract static class VarMapsKeyInfoNode extends Node {
 
-                private static final int EXISTS = 1 << 0;
-                private static final int READABLE = 1 << 1;
-                private static final int WRITABLE = 1 << 2;
-                private static final int INVOCABLE = 1 << 3;
-
-                @SuppressWarnings("try")
                 protected Object access(VariablesObject receiver, String identifier) {
-                    int info = EXISTS + READABLE;
+                    Builder builder = KeyInfo.newBuilder();
+                    builder.setReadable(true);
 
                     if (!receiver.frameAccess.bindingIsLocked(identifier)) {
-                        info += WRITABLE;
+                        builder.setWritable(true);
                     }
                     if (receiver.frameAccess.get(identifier) instanceof RFunction) {
-                        info += INVOCABLE;
+                        builder.setInvocable(true);
                     }
-                    return info;
+                    return builder.build();
                 }
             }
 
@@ -373,8 +370,6 @@ public final class RScope extends AbstractScope {
                     }
                 }
             }
-
         }
     }
-
 }