From ccf9068d3a0668f693de002194993986a28dde3d Mon Sep 17 00:00:00 2001
From: stepan <stepan.sindelar@oracle.com>
Date: Mon, 22 Jan 2018 14:23:42 +0100
Subject: [PATCH] Do not cache CallTargets in static fields

---
 .../r/ffi/impl/nfi/TruffleNFI_Context.java    |  6 ++--
 .../truffle/r/library/graphics/RGraphics.java |  6 ++--
 .../truffle/r/runtime/RCompression.java       |  7 ++--
 .../r/runtime/conn/NativeConnections.java     | 20 ++++++-----
 .../truffle/r/runtime/context/RContext.java   | 12 +++----
 .../truffle/r/runtime/ffi/CallRFFI.java       | 31 +++++++----------
 .../com/oracle/truffle/r/runtime/ffi/DLL.java | 27 +++++++--------
 .../oracle/truffle/r/runtime/ffi/DLLRFFI.java | 34 +++++++------------
 .../oracle/truffle/r/runtime/ffi/ZipRFFI.java | 30 ++++++----------
 .../truffle/r/runtime/rng/user/UserRNG.java   |  4 +--
 10 files changed, 77 insertions(+), 100 deletions(-)

diff --git a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
index 0c2e4e6184..bf3dd59779 100644
--- a/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
+++ b/com.oracle.truffle.r.ffi.impl/src/com/oracle/truffle/r/ffi/impl/nfi/TruffleNFI_Context.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * 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
@@ -123,7 +123,7 @@ final class TruffleNFI_Context extends RFFIContext {
             if (function.getLibrary() == NativeFunction.baseLibrary()) {
                 dllInfo = TruffleNFI_Context.getInstance().defaultLibrary;
             } else if (function.getLibrary() == NativeFunction.anyLibrary()) {
-                DLLInfo lib = DLL.findLibraryContainingSymbol(function.getCallName());
+                DLLInfo lib = DLL.findLibraryContainingSymbol(RContext.getInstance(), function.getCallName());
                 if (lib == null) {
                     throw RInternalError.shouldNotReachHere("Could not find library containing symbol " + function.getCallName());
                 }
@@ -292,7 +292,7 @@ final class TruffleNFI_Context extends RFFIContext {
                 case SHARE_ALL:
                     // new thread, initialize properly
                     assert defaultLibrary == null && rlibDLLInfo == null;
-                    rlibDLLInfo = DLL.findLibraryContainingSymbol("dot_call0");
+                    rlibDLLInfo = DLL.findLibraryContainingSymbol(context, "dot_call0");
                     defaultLibrary = (TruffleObject) RContext.getInstance().getEnv().parse(Source.newBuilder("default").name("(load default)").mimeType("application/x-native").build()).call();
                     initCallbacks(context);
                     break;
diff --git a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
index edb375298a..16282d9461 100644
--- a/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
+++ b/com.oracle.truffle.r.library/src/com/oracle/truffle/r/library/graphics/RGraphics.java
@@ -8,7 +8,7 @@
  * Copyright (c) 1998--2014, The R Core Team
  * Copyright (c) 2002--2010, The R Foundation
  * Copyright (C) 2005--2006, Morten Welinder
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -37,10 +37,10 @@ public class RGraphics {
                 RGridGraphicsAdapter.initialize();
             }
         } else if (initialized.compareAndSet(false, true) && FastROptions.LoadPackagesNativeCode.getBooleanValue()) {
-            DLL.DLLInfo dllInfo = DLL.findLibraryContainingSymbol("InitGraphics");
+            DLL.DLLInfo dllInfo = DLL.findLibraryContainingSymbol(context, "InitGraphics");
             DLL.SymbolHandle symbolHandle = DLL.findSymbol("InitGraphics", dllInfo);
             assert symbolHandle != DLL.SYMBOL_NOT_FOUND;
-            CallRFFI.InvokeVoidCallRootNode.create().getCallTarget().call(new NativeCallInfo("InitGraphics", symbolHandle, dllInfo), new Object[0]);
+            CallRFFI.InvokeVoidCallRootNode.create(context).call(new NativeCallInfo("InitGraphics", symbolHandle, dllInfo), new Object[0]);
         }
         context.internalGraphicsInitialized = true;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
index b80c2f0d91..d95a86df37 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RCompression.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -37,6 +37,7 @@ import java.util.zip.GZIPInputStream;
 
 import org.tukaani.xz.LZMA2InputStream;
 
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.ZipRFFI;
 
 /**
@@ -148,12 +149,12 @@ public class RCompression {
     }
 
     private static boolean gzipCompress(byte[] udata, byte[] cdata) {
-        int rc = (int) ZipRFFI.CompressRootNode.create().getCallTarget().call(cdata, udata);
+        int rc = (int) ZipRFFI.CompressRootNode.create(RContext.getInstance()).call(cdata, udata);
         return rc == 0;
     }
 
     private static boolean gzipUncompress(byte[] udata, byte[] data) {
-        int rc = (int) ZipRFFI.UncompressRootNode.create().getCallTarget().call(udata, data);
+        int rc = (int) ZipRFFI.UncompressRootNode.create(RContext.getInstance()).call(udata, data);
         return rc == 0;
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java
index 7d18153e4a..ab5a0b28db 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/NativeConnections.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -29,13 +29,14 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.Objects;
 
-import com.oracle.truffle.api.RootCallTarget;
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.AbstractOpenMode;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.BaseRConnection;
 import com.oracle.truffle.r.runtime.conn.ConnectionSupport.ConnectionClass;
 import com.oracle.truffle.r.runtime.conn.RConnection.SeekMode;
+import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RDoubleVector;
 import com.oracle.truffle.r.runtime.data.RExternalPtr;
@@ -43,6 +44,7 @@ import com.oracle.truffle.r.runtime.data.RIntVector;
 import com.oracle.truffle.r.runtime.data.RLogicalVector;
 import com.oracle.truffle.r.runtime.data.RRawVector;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI;
+import com.oracle.truffle.r.runtime.ffi.CallRFFI.InvokeCallRootNode;
 import com.oracle.truffle.r.runtime.ffi.DLL;
 import com.oracle.truffle.r.runtime.ffi.DLL.DLLInfo;
 import com.oracle.truffle.r.runtime.ffi.DLL.SymbolHandle;
@@ -66,7 +68,7 @@ public class NativeConnections {
     private static NativeCallInfo getNativeFunctionInfo(String name) {
         NativeCallInfo nativeCallInfo = callInfoTable.get(name);
         if (nativeCallInfo == null) {
-            DLLInfo findLibraryContainingSymbol = DLL.findLibraryContainingSymbol(name);
+            DLLInfo findLibraryContainingSymbol = DLL.findLibraryContainingSymbol(RContext.getInstance(), name);
             SymbolHandle findSymbol = DLL.findSymbol(name, findLibraryContainingSymbol);
             nativeCallInfo = new NativeCallInfo(name, findSymbol, findLibraryContainingSymbol);
             callInfoTable.put(name, nativeCallInfo);
@@ -135,7 +137,7 @@ public class NativeConnections {
 
         public boolean getFlag(String name) {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(GET_FLAG_NATIVE_CONNECTION);
-            RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
+            CallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create(RContext.getInstance());
 
             Object result = nativeCallTarget.call(ni, new Object[]{addr, name});
             if (result instanceof RLogicalVector) {
@@ -172,7 +174,7 @@ public class NativeConnections {
         RIntVector rwCode = RDataFactory.createIntVectorFromScalar(rw);
 
         NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(SEEK_NATIVE_CONNECTION);
-        RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
+        CallTarget nativeCallTarget = InvokeCallRootNode.create(RContext.getInstance());
         Object result = nativeCallTarget.call(ni, new Object[]{addr, where, seekCode, rwCode});
         if (result instanceof RDoubleVector) {
             return (long) ((RDoubleVector) result).getDataAt(0);
@@ -288,7 +290,7 @@ public class NativeConnections {
 
     private static void openNative(RExternalPtr addr) throws IOException {
         NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(OPEN_NATIVE_CONNECTION);
-        RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
+        CallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create(RContext.getInstance());
 
         Object result = nativeCallTarget.call(ni, new Object[]{addr});
         if (!(result instanceof RLogicalVector && ((RLogicalVector) result).getDataAt(0) == RRuntime.LOGICAL_TRUE)) {
@@ -315,7 +317,7 @@ public class NativeConnections {
         @Override
         public int read(ByteBuffer dst) throws IOException {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(READ_NATIVE_CONNECTION);
-            RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
+            CallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create(RContext.getInstance());
             RRawVector bufferVec = RDataFactory.createRawVector(dst.remaining());
             Object call = nativeCallTarget.call(ni, new Object[]{base.addr, bufferVec, dst.remaining()});
             if (!(call instanceof RIntVector)) {
@@ -339,14 +341,14 @@ public class NativeConnections {
         @Override
         public void close() throws IOException {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(CLOSE_NATIVE_CONNECTION);
-            RootCallTarget nativeCallTarget = CallRFFI.InvokeVoidCallRootNode.create().getCallTarget();
+            CallTarget nativeCallTarget = CallRFFI.InvokeVoidCallRootNode.create(RContext.getInstance());
             nativeCallTarget.call(ni, new Object[]{base.addr});
         }
 
         @Override
         public int write(ByteBuffer src) throws IOException {
             NativeCallInfo ni = NativeConnections.getNativeFunctionInfo(WRITE_NATIVE_CONNECTION);
-            RootCallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create().getCallTarget();
+            CallTarget nativeCallTarget = CallRFFI.InvokeCallRootNode.create(RContext.getInstance());
             ByteBuffer slice = src;
             if (src.position() > 0) {
                 slice = src.slice();
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 28c057b810..fc5772bad6 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
@@ -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
@@ -230,13 +230,13 @@ public final class RContext {
     private final RStartParams startParameters;
     private final RCmdOptions cmdOptions;
     private final RContext.ContextKind contextKind;
-    public final Map<Class<?>, RootCallTarget> nativeCallTargets = new HashMap<>();
+    public final Map<Class<?>, RootCallTarget> cachedCallTagets = new HashMap<>();
 
-    public RootCallTarget getOrCreateNativeCallTarget(Class<?> clazz, Supplier<RootCallTarget> creatFunction) {
-        RootCallTarget result = nativeCallTargets.get(clazz);
+    public RootCallTarget getOrCreateCachedCallTarget(Class<?> clazz, Supplier<RootCallTarget> createFunction) {
+        RootCallTarget result = cachedCallTagets.get(clazz);
         if (result == null) {
-            result = creatFunction.get();
-            nativeCallTargets.put(clazz, result);
+            result = createFunction.get();
+            cachedCallTagets.put(clazz, result);
         }
         return result;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
index 849daaf12b..6d0419ab92 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/CallRFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -22,6 +22,7 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.NodeInterface;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -83,10 +84,8 @@ public interface CallRFFI {
     HandleUpCallExceptionNode createHandleUpCallExceptionNode();
 
     final class InvokeCallRootNode extends RFFIRootNode<InvokeCallNode> {
-        private static InvokeCallRootNode invokeCallRootNode;
-
-        private InvokeCallRootNode() {
-            super(RFFIFactory.getCallRFFI().createInvokeCallNode());
+        protected InvokeCallRootNode(InvokeCallNode baseRFFINode) {
+            super(baseRFFINode);
         }
 
         @Override
@@ -95,19 +94,15 @@ public interface CallRFFI {
             return rffiNode.dispatch((NativeCallInfo) args[0], (Object[]) args[1]);
         }
 
-        public static InvokeCallRootNode create() {
-            if (invokeCallRootNode == null) {
-                invokeCallRootNode = new InvokeCallRootNode();
-            }
-            return invokeCallRootNode;
+        public static CallTarget create(RContext context) {
+            CallRFFI callRFFI = context.getRFFI().callRFFI;
+            return context.getOrCreateCachedCallTarget(InvokeCallRootNode.class, () -> new InvokeCallRootNode(callRFFI.createInvokeCallNode()).getCallTarget());
         }
     }
 
     final class InvokeVoidCallRootNode extends RFFIRootNode<InvokeVoidCallNode> {
-        private static InvokeVoidCallRootNode InvokeVoidCallRootNode;
-
-        private InvokeVoidCallRootNode() {
-            super(RFFIFactory.getCallRFFI().createInvokeVoidCallNode());
+        protected InvokeVoidCallRootNode(InvokeVoidCallNode wrapper) {
+            super(wrapper);
         }
 
         @Override
@@ -117,11 +112,9 @@ public interface CallRFFI {
             return RNull.instance; // unused
         }
 
-        public static InvokeVoidCallRootNode create() {
-            if (InvokeVoidCallRootNode == null) {
-                InvokeVoidCallRootNode = new InvokeVoidCallRootNode();
-            }
-            return InvokeVoidCallRootNode;
+        public static CallTarget create(RContext context) {
+            CallRFFI callRFFI = context.getRFFI().callRFFI;
+            return context.getOrCreateCachedCallTarget(InvokeVoidCallNode.class, () -> new InvokeVoidCallRootNode(callRFFI.createInvokeVoidCallNode()).getCallTarget());
         }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
index 6c9a027c49..f65913a8cd 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLL.java
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1995-2012, The R Core Team
  * Copyright (c) 2003, The R Foundation
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates
+ * Copyright (c) 2015, 2018, Oracle and/or its affiliates
  *
  * All rights reserved.
  */
@@ -16,9 +16,11 @@ import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.CompilerAsserts;
 import com.oracle.truffle.api.CompilerDirectives;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.RootCallTarget;
 import com.oracle.truffle.api.Truffle;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
@@ -45,6 +47,7 @@ import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.data.RSymbol;
 import com.oracle.truffle.r.runtime.data.RTruffleObject;
 import com.oracle.truffle.r.runtime.ffi.CallRFFI.InvokeVoidCallNode;
+import com.oracle.truffle.r.runtime.ffi.DLLRFFI.DLCloseRootNode;
 import com.oracle.truffle.r.runtime.nodes.RSyntaxNode;
 import com.oracle.truffle.r.runtime.rng.user.UserRNG;
 
@@ -103,9 +106,10 @@ public class DLL {
         @Override
         public void beforeDispose(RContext contextArg) {
             if (!isShareDLLKind(context.getKind())) {
+                RootCallTarget closeCallTarget = DLCloseRootNode.create(contextArg);
                 for (int i = 1; i < list.size(); i++) {
                     DLLInfo dllInfo = list.get(i);
-                    DLLRFFI.DLCloseRootNode.create().getCallTarget().call(dllInfo.handle);
+                    closeCallTarget.call(dllInfo.handle);
                 }
             }
             list = null;
@@ -635,12 +639,11 @@ public class DLL {
     }
 
     private static final class RFindSymbolRootNode extends RootNode {
-        private static RFindSymbolRootNode findSymbolRootNode;
-
         @Child private RFindSymbolNode findSymbolNode = RFindSymbolNode.create();
 
         private RFindSymbolRootNode() {
             super(RContext.getInstance().getLanguage());
+            Truffle.getRuntime().createCallTarget(this);
         }
 
         @Override
@@ -654,12 +657,8 @@ public class DLL {
             return findSymbolNode.execute((String) args[0], (String) args[1], (RegisteredNativeSymbol) args[2]);
         }
 
-        private static synchronized RFindSymbolRootNode create() {
-            if (findSymbolRootNode == null) {
-                findSymbolRootNode = new RFindSymbolRootNode();
-                Truffle.getRuntime().createCallTarget(findSymbolRootNode);
-            }
-            return findSymbolRootNode;
+        private static CallTarget create(RContext context) {
+            return context.getOrCreateCachedCallTarget(RFindSymbolRootNode.class, () -> new RFindSymbolRootNode().getCallTarget());
         }
     }
 
@@ -714,9 +713,9 @@ public class DLL {
      * This is called by {@link UserRNG} because at the time the user-defined RNG is initialized it
      * is not known which library defines the RNG symbols.
      */
-    public static DLLInfo findLibraryContainingSymbol(String symbol) {
+    public static DLLInfo findLibraryContainingSymbol(RContext context, String symbol) {
         RegisteredNativeSymbol rns = RegisteredNativeSymbol.any();
-        SymbolHandle func = (SymbolHandle) RFindSymbolRootNode.create().getCallTarget().call(symbol, null, rns);
+        SymbolHandle func = (SymbolHandle) RFindSymbolRootNode.create(context).call(symbol, null, rns);
         if (func == SYMBOL_NOT_FOUND) {
             return null;
         } else {
@@ -746,9 +745,9 @@ public class DLL {
      */
     public static SymbolHandle findSymbol(String name, DLLInfo dllInfo) {
         if (dllInfo != null) {
-            return (SymbolHandle) DLLRFFI.DLSymRootNode.create().getCallTarget().call(dllInfo.handle, name);
+            return (SymbolHandle) DLLRFFI.DLSymRootNode.create(RContext.getInstance()).call(dllInfo.handle, name);
         } else {
-            return (SymbolHandle) RFindSymbolRootNode.create().getCallTarget().call(name, null, RegisteredNativeSymbol.any());
+            return (SymbolHandle) RFindSymbolRootNode.create(RContext.getInstance()).call(name, null, RegisteredNativeSymbol.any());
         }
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
index 5b9d61239f..687295d30f 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/DLLRFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -76,8 +76,8 @@ public interface DLLRFFI {
     // RootNodes
 
     final class DLOpenRootNode extends RFFIRootNode<DLOpenNode> {
-        private DLOpenRootNode() {
-            super(RFFIFactory.getDLLRFFI().createDLOpenNode());
+        private DLOpenRootNode(DLOpenNode wrapped) {
+            super(wrapped);
         }
 
         @Override
@@ -87,15 +87,13 @@ public interface DLLRFFI {
         }
 
         public static RootCallTarget create(RContext context) {
-            return context.getOrCreateNativeCallTarget(DLOpenRootNode.class, () -> new DLOpenRootNode().getCallTarget());
+            return context.getOrCreateCachedCallTarget(DLOpenRootNode.class, () -> new DLOpenRootNode(context.getRFFI().dllRFFI.createDLOpenNode()).getCallTarget());
         }
     }
 
     final class DLSymRootNode extends RFFIRootNode<DLSymNode> {
-        private static DLSymRootNode dlSymRootNode;
-
-        private DLSymRootNode() {
-            super(RFFIFactory.getDLLRFFI().createDLSymNode());
+        protected DLSymRootNode(DLSymNode wrapped) {
+            super(wrapped);
         }
 
         @Override
@@ -104,19 +102,14 @@ public interface DLLRFFI {
             return rffiNode.execute(args[0], (String) args[1]);
         }
 
-        public static DLSymRootNode create() {
-            if (dlSymRootNode == null) {
-                dlSymRootNode = new DLSymRootNode();
-            }
-            return dlSymRootNode;
+        public static RootCallTarget create(RContext context) {
+            return context.getOrCreateCachedCallTarget(DLSymRootNode.class, () -> new DLSymRootNode(context.getRFFI().dllRFFI.createDLSymNode()).getCallTarget());
         }
     }
 
     final class DLCloseRootNode extends RFFIRootNode<DLCloseNode> {
-        private static DLCloseRootNode dlCloseRootNode;
-
-        private DLCloseRootNode() {
-            super(RFFIFactory.getDLLRFFI().createDLCloseNode());
+        protected DLCloseRootNode(DLCloseNode wrapped) {
+            super(wrapped);
         }
 
         @Override
@@ -125,11 +118,8 @@ public interface DLLRFFI {
             return rffiNode.execute(args[0]);
         }
 
-        public static DLCloseRootNode create() {
-            if (dlCloseRootNode == null) {
-                dlCloseRootNode = new DLCloseRootNode();
-            }
-            return dlCloseRootNode;
+        public static RootCallTarget create(RContext context) {
+            return context.getOrCreateCachedCallTarget(DLCloseRootNode.class, () -> new DLCloseRootNode(context.getRFFI().dllRFFI.createDLCloseNode()).getCallTarget());
         }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
index d41187a6c1..b02f3fefda 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/ZipRFFI.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -22,8 +22,10 @@
  */
 package com.oracle.truffle.r.runtime.ffi;
 
+import com.oracle.truffle.api.CallTarget;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.nodes.NodeInterface;
+import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
  * zip compression/uncompression.
@@ -59,10 +61,8 @@ public interface ZipRFFI {
     // RootNodes for calling when not in Truffle context
 
     final class CompressRootNode extends RFFIRootNode<CompressNode> {
-        private static CompressRootNode compressRootNode;
-
-        private CompressRootNode() {
-            super(RFFIFactory.getZipRFFI().createCompressNode());
+        protected CompressRootNode(CompressNode wrapped) {
+            super(wrapped);
         }
 
         @Override
@@ -71,19 +71,14 @@ public interface ZipRFFI {
             return rffiNode.execute((byte[]) args[0], (byte[]) args[1]);
         }
 
-        public static CompressRootNode create() {
-            if (compressRootNode == null) {
-                compressRootNode = new CompressRootNode();
-            }
-            return compressRootNode;
+        public static CallTarget create(RContext context) {
+            return context.getOrCreateCachedCallTarget(CompressRootNode.class, () -> new CompressRootNode(context.getRFFI().zipRFFI.createCompressNode()).getCallTarget());
         }
     }
 
     final class UncompressRootNode extends RFFIRootNode<UncompressNode> {
-        private static UncompressRootNode uncompressRootNode;
-
-        private UncompressRootNode() {
-            super(RFFIFactory.getZipRFFI().createUncompressNode());
+        protected UncompressRootNode(UncompressNode wrapped) {
+            super(wrapped);
         }
 
         @Override
@@ -92,11 +87,8 @@ public interface ZipRFFI {
             return rffiNode.execute((byte[]) args[0], (byte[]) args[1]);
         }
 
-        public static UncompressRootNode create() {
-            if (uncompressRootNode == null) {
-                uncompressRootNode = new UncompressRootNode();
-            }
-            return uncompressRootNode;
+        public static CallTarget create(RContext context) {
+            return context.getOrCreateCachedCallTarget(UncompressRootNode.class, () -> new UncompressRootNode(context.getRFFI().zipRFFI.createUncompressNode()).getCallTarget());
         }
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
index 3e0cbf8fc8..4aa747dd92 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/user/UserRNG.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 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
@@ -131,7 +131,7 @@ public final class UserRNG implements RandomNumberGenerator {
     @Override
     @TruffleBoundary
     public void init(int seed) {
-        DLLInfo dllInfo = DLL.findLibraryContainingSymbol(Function.Rand.symbol);
+        DLLInfo dllInfo = DLL.findLibraryContainingSymbol(RContext.getInstance(), Function.Rand.symbol);
         callGeneric = Truffle.getRuntime().createCallTarget(new GenericUserRNGRootNode());
         if (dllInfo == null) {
             throw RError.error(RError.NO_CALLER, RError.Message.RNG_SYMBOL, Function.Rand.symbol);
-- 
GitLab