diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
index 84d164a23a5ab3c62cd9473e71a32fa5955e93cf..16ba409614756338d6683f0af586e408ccc5eff2 100644
--- a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/function/RCallNode.java
@@ -69,6 +69,8 @@ import com.oracle.truffle.r.nodes.function.call.CallRFunctionNode;
 import com.oracle.truffle.r.nodes.function.call.PrepareArguments;
 import com.oracle.truffle.r.nodes.function.visibility.SetVisibilityNode;
 import com.oracle.truffle.r.nodes.helpers.AccessListField;
+import com.oracle.truffle.r.nodes.helpers.GetFromEnvironment;
+import com.oracle.truffle.r.nodes.helpers.GetFromEnvironmentNodeGen;
 import com.oracle.truffle.r.nodes.profile.TruffleBoundaryNode;
 import com.oracle.truffle.r.nodes.profile.VectorLengthProfile;
 import com.oracle.truffle.r.runtime.Arguments;
@@ -154,7 +156,26 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
 
     // needed for INTERNAL_GENERIC calls:
     @Child private FunctionDispatch internalDispatchCall;
-    @Child private AccessListField accessListField;
+    @Child private GetBasicFunction getBasicFunction;
+
+    private static final class GetBasicFunction extends RBaseNode {
+        @Child private AccessListField accessListField = AccessListField.create();
+        @Child private GetFromEnvironment getMethods = GetFromEnvironmentNodeGen.create();
+        @Child private GetFromEnvironment getBasicFunsList = GetFromEnvironmentNodeGen.create();
+
+        Object execute(VirtualFrame frame, String functionName) {
+            REnvironment namespaceRegistry = REnvironment.getNamespaceRegistry();
+            Object methods = getMethods.execute(frame, namespaceRegistry, "methods");
+            if (!(methods instanceof REnvironment)) {
+                throw error(RError.Message.GENERIC, "methods namespace not found on search list");
+            }
+            Object basicFunsList = getBasicFunsList.execute(frame, (REnvironment) methods, ".BasicFunsList");
+            if (!(basicFunsList instanceof RList)) {
+                throw error(RError.Message.GENERIC, ".BasicFunsList not found in methods namespace");
+            }
+            return accessListField.execute((RList) basicFunsList, functionName);
+        }
+    }
 
     protected RCaller createCaller(VirtualFrame frame, RFunction function) {
         if (explicitArgs == null) {
@@ -287,8 +308,7 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
                     @Cached("createBinaryProfile()") ConditionProfile isAttributableProfile,
                     @Cached("createBinaryProfile()") ConditionProfile resultIsBuiltinProfile,
                     @Cached("create()") GetBaseEnvFrameNode getBaseEnvFrameNode,
-                    @Cached("createBinaryProfile()") ConditionProfile isS4Profile,
-                    @Cached("new()") PromiseCheckHelperNode promiseHelper) {
+                    @Cached("createBinaryProfile()") ConditionProfile isS4Profile) {
 
         RBuiltinDescriptor builtin = builtinProfile.profile(function.getRBuiltin());
         Object dispatchObject = dispatchArgument.execute(frame);
@@ -305,12 +325,11 @@ public abstract class RCallNode extends RCallBaseNode implements RSyntaxNode, RS
             }
 
             if (isAttributableProfile.profile(dispatchObject instanceof RAttributeStorage) && isS4Profile.profile(((RAttributeStorage) dispatchObject).isS4())) {
-                RList list = (RList) promiseHelper.checkEvaluate(frame, REnvironment.getRegisteredNamespace("methods").get(".BasicFunsList"));
-                if (accessListField == null) {
+                if (getBasicFunction == null) {
                     CompilerDirectives.transferToInterpreterAndInvalidate();
-                    accessListField = insert(AccessListField.create());
+                    getBasicFunction = insert(new GetBasicFunction());
                 }
-                Object basicFun = accessListField.execute(list, builtin.getName());
+                Object basicFun = getBasicFunction.execute(frame, builtin.getName());
                 if (basicFun != null) {
                     Object result = internalDispatchCall.execute(frame, (RFunction) basicFun, lookupVarArgs(frame), null, null);
                     if (result != RRuntime.DEFERRED_DEFAULT_MARKER) {
diff --git a/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/GetFromEnvironment.java b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/GetFromEnvironment.java
new file mode 100644
index 0000000000000000000000000000000000000000..f1d2f0e0adda4fd5ed246fa0d24f8a9671610405
--- /dev/null
+++ b/com.oracle.truffle.r.nodes/src/com/oracle/truffle/r/nodes/helpers/GetFromEnvironment.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 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
+ * 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.nodes.helpers;
+
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.frame.FrameDescriptor;
+import com.oracle.truffle.api.frame.VirtualFrame;
+import com.oracle.truffle.api.profiles.ValueProfile;
+import com.oracle.truffle.r.nodes.access.variables.LocalReadVariableNode;
+import com.oracle.truffle.r.nodes.access.variables.ReadVariableNode;
+import com.oracle.truffle.r.nodes.function.PromiseHelperNode;
+import com.oracle.truffle.r.runtime.data.RPromise;
+import com.oracle.truffle.r.runtime.env.REnvironment;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
+
+public abstract class GetFromEnvironment extends RBaseNode {
+
+    public static GetFromEnvironment create() {
+        return GetFromEnvironmentNodeGen.create();
+    }
+
+    protected final ValueProfile frameAccessProfile = ValueProfile.createClassProfile();
+    protected final ValueProfile frameProfile = ValueProfile.createClassProfile();
+
+    @Child private PromiseHelperNode promiseHelper;
+
+    @CompilationFinal private boolean firstExecution = true;
+
+    protected Object checkPromise(VirtualFrame frame, Object r, String identifier) {
+        if (r instanceof RPromise) {
+            if (firstExecution) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                firstExecution = false;
+                return ReadVariableNode.evalPromiseSlowPathWithName(identifier, frame, (RPromise) r);
+            }
+            if (promiseHelper == null) {
+                CompilerDirectives.transferToInterpreterAndInvalidate();
+                promiseHelper = insert(new PromiseHelperNode());
+            }
+            return promiseHelper.evaluate(frame, (RPromise) r);
+        } else {
+            return r;
+        }
+    }
+
+    public abstract Object execute(VirtualFrame frame, REnvironment env, String name);
+
+    protected static LocalReadVariableNode createRead(String name) {
+        return LocalReadVariableNode.create(name, true);
+    }
+
+    protected FrameDescriptor getFrameDescriptor(REnvironment env) {
+        return frameProfile.profile(env.getFrame(frameAccessProfile)).getFrameDescriptor();
+    }
+
+    @Specialization(guards = {"getFrameDescriptor(env) == envDesc", "read.getIdentifier().equals(name)"})
+    protected Object getCached(VirtualFrame frame, REnvironment env, @SuppressWarnings("unused") String name,
+                    @Cached("env.getFrame().getFrameDescriptor()") @SuppressWarnings("unused") FrameDescriptor envDesc,
+                    @Cached("createRead(name)") LocalReadVariableNode read) {
+        return read.execute(frame, frameProfile.profile(env.getFrame(frameAccessProfile)));
+    }
+
+    @Specialization(replaces = "getCached")
+    protected Object get(VirtualFrame frame, REnvironment env, String name) {
+        return checkPromise(frame, env.get(name), name);
+    }
+}