diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
index 61ef2ee9472073dba12db55e9b8179fd9b993188..78f86f0066f5b47ce4a1ce54572e851b6d8cb69b 100644
--- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
+++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/base/DoCall.java
@@ -68,6 +68,9 @@ import com.oracle.truffle.r.runtime.builtins.RBuiltin;
 import com.oracle.truffle.r.runtime.builtins.RBuiltinKind;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.Closure;
+import com.oracle.truffle.r.runtime.data.ClosureCache;
+import com.oracle.truffle.r.runtime.data.ClosureCache.RNodeClosureCache;
+import com.oracle.truffle.r.runtime.data.ClosureCache.SymbolClosureCache;
 import com.oracle.truffle.r.runtime.data.RArgsValuesAndNames;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.REmpty;
@@ -127,6 +130,8 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
         @Child private GetNamesAttributeNode getNamesNode;
         @Child private SetVisibilityNode setVisibilityNode;
         private final ValueProfile frameAccessProfile = ValueProfile.createClassProfile();
+        private final RNodeClosureCache languagesClosureCache = new RNodeClosureCache();
+        private final SymbolClosureCache symbolsClosureCache = new SymbolClosureCache();
 
         public static DoCallInternal create() {
             return DoCallInternalNodeGen.create();
@@ -217,10 +222,10 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
                         if (symbol.getName().isEmpty()) {
                             argValues[i] = REmpty.instance;
                         } else {
-                            argValues[i] = createLookupPromise(promiseFrame, symbol);
+                            argValues[i] = createLookupPromise(promiseFrame, symbol.getName());
                         }
                     } else if (arg instanceof RLanguage) {
-                        argValues[i] = RDataFactory.createPromise(PromiseState.Default, Closure.createPromiseClosure(((RLanguage) arg).getRep()), promiseFrame);
+                        argValues[i] = createLanguagePromise(promiseFrame, (RLanguage) arg);
                     }
                 }
             }
@@ -228,6 +233,18 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
             return new RArgsValuesAndNames(argValues, signature);
         }
 
+        @TruffleBoundary
+        private RPromise createLanguagePromise(MaterializedFrame promiseFrame, RLanguage arg) {
+            Closure closure = languagesClosureCache.getOrCreatePromiseClosure(arg.getRep());
+            return RDataFactory.createPromise(PromiseState.Default, closure, promiseFrame);
+        }
+
+        @TruffleBoundary
+        private RPromise createLookupPromise(MaterializedFrame callerFrame, String name) {
+            Closure closure = symbolsClosureCache.getOrCreatePromiseClosure(name);
+            return RDataFactory.createPromise(PromiseState.Supplied, closure, callerFrame);
+        }
+
         private void setVisibility(VirtualFrame frame, boolean value) {
             if (setVisibilityNode == null) {
                 CompilerDirectives.transferToInterpreterAndInvalidate();
@@ -245,12 +262,6 @@ public abstract class DoCall extends RBuiltinNode.Arg4 implements InternalRSynta
             return signature == null ? ArgumentsSignature.empty(argsAsList.getLength()) : signature;
         }
 
-        @TruffleBoundary
-        private static RPromise createLookupPromise(MaterializedFrame callerFrame, RSymbol symbol) {
-            Closure closure = Closure.createPromiseClosure(RContext.getASTBuilder().lookup(RSyntaxNode.SOURCE_UNAVAILABLE, symbol.getName(), false).asRNode());
-            return RDataFactory.createPromise(PromiseState.Supplied, closure, callerFrame);
-        }
-
         @TruffleBoundary
         private static boolean getVisibilitySlowPath(MaterializedFrame envFrame) {
             FrameSlot envVisibilitySlot = FrameSlotChangeMonitor.findOrAddFrameSlot(envFrame.getFrameDescriptor(), RFrameSlot.Visibility, FrameSlotKind.Boolean);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ClosureCache.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ClosureCache.java
index ef41f3c88e4d5422105bc6e8ac9ae520b4902c60..f84c8201bb212ca26897996401038fb899630543 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ClosureCache.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/data/ClosureCache.java
@@ -26,6 +26,7 @@ import java.util.concurrent.ConcurrentHashMap;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.r.runtime.context.RContext;
+import com.oracle.truffle.r.runtime.nodes.RBaseNode;
 import com.oracle.truffle.r.runtime.nodes.RNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 
@@ -50,7 +51,7 @@ public abstract class ClosureCache<K> {
         return getOrCreateClosure(Closure.LANGUAGE_CLOSURE_WRAPPER_NAME, key);
     }
 
-    protected abstract RNode keyToNode(K key);
+    protected abstract RBaseNode keyToNode(K key);
 
     @TruffleBoundary
     private Closure getOrCreateClosure(String name, K key) {
@@ -69,9 +70,9 @@ public abstract class ClosureCache<K> {
         }
     }
 
-    public static final class RNodeClosureCache extends ClosureCache<RNode> {
+    public static final class RNodeClosureCache extends ClosureCache<RBaseNode> {
         @Override
-        protected RNode keyToNode(RNode key) {
+        protected RBaseNode keyToNode(RBaseNode key) {
             return key;
         }
     }