From 531dcf9e61573635a2a63d207a885a7dabaecabd Mon Sep 17 00:00:00 2001
From: Mick Jordan <mick.jordan@oracle.com>
Date: Wed, 31 Aug 2016 07:12:25 -0700
Subject: [PATCH] refactor context creation/initialization to match
 TruffleLanguage createContext/initializeContext

---
 .../truffle/r/engine/TruffleRLanguage.java    | 20 +++--
 .../r/runtime/ffi/jnr/JNR_RFFIFactory.java    |  2 +-
 .../oracle/truffle/r/runtime/LazyDBCache.java |  2 +-
 .../oracle/truffle/r/runtime/REnvVars.java    | 11 ++-
 .../truffle/r/runtime/RErrorHandling.java     |  2 +-
 .../truffle/r/runtime/RInternalCode.java      |  2 +-
 .../oracle/truffle/r/runtime/ROptions.java    | 13 ++-
 .../oracle/truffle/r/runtime/RProfile.java    | 18 ++--
 .../oracle/truffle/r/runtime/RSerialize.java  |  2 +-
 .../r/runtime/conn/ConnectionSupport.java     |  2 +-
 .../r/runtime/conn/StdConnections.java        | 20 +++--
 .../truffle/r/runtime/context/RContext.java   | 89 ++++++++++++++-----
 .../truffle/r/runtime/env/REnvironment.java   | 42 +++++----
 .../runtime/ffi/RFFIContextStateFactory.java  |  4 +-
 .../truffle/r/runtime/ffi/RFFIFactory.java    |  4 +-
 .../instrument/InstrumentationState.java      |  2 +-
 .../oracle/truffle/r/runtime/rng/RRNG.java    | 21 +++--
 17 files changed, 173 insertions(+), 83 deletions(-)

diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
index 7a04b504b1..4a5c2c8f91 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/TruffleRLanguage.java
@@ -77,13 +77,13 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
             RVersionInfo.initialize();
             TempPathName.initialize();
             RPackageSource.initialize();
-            RContext.initialize(new RASTBuilder(), new RRuntimeASTAccessImpl(), RBuiltinPackages.getInstance(), new RForeignAccessFactoryImpl());
+
         } catch (Throwable t) {
             Utils.rSuicide("error during R language initialization");
         }
     }
 
-    private static boolean initialized;
+    private static boolean systemInitialized;
 
     public static final TruffleRLanguage INSTANCE = new TruffleRLanguage();
 
@@ -98,12 +98,20 @@ public final class TruffleRLanguage extends TruffleLanguage<RContext> {
     }
 
     @Override
-    protected RContext createContext(Env env) {
-        boolean initialContext = !initialized;
-        if (!initialized) {
+    protected void initializeContext(RContext context) throws Exception {
+        if (!systemInitialized) {
             FastROptions.initialize();
             initialize();
-            initialized = true;
+            systemInitialized = true;
+        }
+        context.initializeContext();
+    }
+
+    @Override
+    protected RContext createContext(Env env) {
+        boolean initialContext = !systemInitialized;
+        if (initialContext) {
+            RContext.initializeGlobalState(new RASTBuilder(), new RRuntimeASTAccessImpl(), RBuiltinPackages.getInstance(), new RForeignAccessFactoryImpl());
         }
         RContext result = RContext.create(env, env.lookup(Instrumenter.class), initialContext);
         return result;
diff --git a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java
index da24f27db4..05a093a010 100644
--- a/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime.ffi/src/com/oracle/truffle/r/runtime/ffi/jnr/JNR_RFFIFactory.java
@@ -83,7 +83,7 @@ public class JNR_RFFIFactory extends RFFIFactory implements RFFI {
     }
 
     @Override
-    public ContextState newContext(RContext context) {
+    public ContextState newContextState() {
         return new ContextStateImpl();
     }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyDBCache.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyDBCache.java
index ab4b19c7e0..6b742edcf9 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyDBCache.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/LazyDBCache.java
@@ -54,7 +54,7 @@ public class LazyDBCache {
             dbCache.remove(dbPath);
         }
 
-        public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) {
+        public static ContextStateImpl newContextState() {
             return new ContextStateImpl();
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
index e8d6869206..de47b4ddec 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/REnvVars.java
@@ -45,7 +45,11 @@ public final class REnvVars implements RContext.ContextState {
 
     private final Map<String, String> envVars = new HashMap<>(System.getenv());
 
-    private REnvVars(RContext context) {
+    private REnvVars() {
+    }
+
+    @Override
+    public RContext.ContextState initialize(RContext context) {
         // set the standard vars defined by R
         String rHome = System.getenv("R_HOME");
         // Always read the system file
@@ -101,10 +105,11 @@ public final class REnvVars implements RContext.ContextState {
                 System.setProperty("http.proxyPort", port);
             }
         }
+        return this;
     }
 
-    public static REnvVars newContext(RContext context) {
-        return new REnvVars(context);
+    public static REnvVars newContextState() {
+        return new REnvVars();
     }
 
     private String getEitherCase(String var) {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
index 74aff0e660..99b9a1969d 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RErrorHandling.java
@@ -145,7 +145,7 @@ public class RErrorHandling {
             return dotSignalSimpleWarning;
         }
 
-        public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) {
+        public static ContextStateImpl newContextState() {
             return new ContextStateImpl();
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
index 7c13688fa1..05c5cfbc2c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RInternalCode.java
@@ -104,7 +104,7 @@ public final class RInternalCode {
             codes.put(source, code);
         }
 
-        public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) {
+        public static ContextStateImpl newContextState() {
             return new ContextStateImpl();
         }
 
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
index 997c7ea869..05c614c25a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ROptions.java
@@ -51,9 +51,11 @@ public class ROptions {
          * The current values for a given context.
          */
         private final HashMap<String, Object> map;
+        private final REnvVars envVars;
 
-        private ContextStateImpl(HashMap<String, Object> map) {
+        private ContextStateImpl(HashMap<String, Object> map, REnvVars envVars) {
             this.map = map;
+            this.envVars = envVars;
             // cannot call updateDotOptions here
         }
 
@@ -95,14 +97,19 @@ public class ROptions {
         }
 
         @TruffleBoundary
-        public static ContextStateImpl newContext(RContext context, REnvVars envVars) {
+        public static ContextStateImpl newContextState(REnvVars envVars) {
             HashMap<String, Object> map = new HashMap<>();
+            return new ContextStateImpl(map, envVars);
+        }
+
+        @Override
+        public RContext.ContextState initialize(RContext context) {
             if (context.getKind() == ContextKind.SHARE_NOTHING) {
                 applyDefaults(map, context.getStartParams(), envVars);
             } else {
                 map.putAll(context.getParent().stateROptions.map);
             }
-            return new ContextStateImpl(map);
+            return this;
         }
 
         /**
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
index 2522a7fbee..3af2daa50e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RProfile.java
@@ -38,7 +38,14 @@ import com.oracle.truffle.r.runtime.ffi.RFFIFactory;
  */
 public final class RProfile implements RContext.ContextState {
 
-    private RProfile(RContext context, REnvVars envVars) {
+    private final REnvVars envVars;
+
+    private RProfile(REnvVars envVars) {
+        this.envVars = envVars;
+    }
+
+    @Override
+    public RContext.ContextState initialize(RContext context) {
         String rHome = REnvVars.rHome();
         FileSystem fileSystem = FileSystems.getDefault();
         Source newSiteProfile = null;
@@ -77,10 +84,11 @@ public final class RProfile implements RContext.ContextState {
         }
         siteProfile = newSiteProfile;
         userProfile = newUserProfile;
+        return this;
     }
 
-    private final Source siteProfile;
-    private final Source userProfile;
+    private Source siteProfile;
+    private Source userProfile;
 
     public static Source systemProfile() {
         Path path = FileSystems.getDefault().getPath(REnvVars.rHome(), "library", "base", "R", "Rprofile");
@@ -108,7 +116,7 @@ public final class RProfile implements RContext.ContextState {
         }
     }
 
-    public static RProfile newContext(RContext context, REnvVars envVars) {
-        return new RProfile(context, envVars);
+    public static RProfile newContextState(REnvVars envVars) {
+        return new RProfile(envVars);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
index ea78607cbe..8b542782ab 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RSerialize.java
@@ -201,7 +201,7 @@ public class RSerialize {
             return dotDotFindNamespace;
         }
 
-        public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) {
+        public static ContextStateImpl newContextState() {
             return new ContextStateImpl();
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
index 58a135e705..94bbb2c406 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/ConnectionSupport.java
@@ -179,7 +179,7 @@ public class ConnectionSupport {
             }
         }
 
-        public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) {
+        public static ContextStateImpl newContextState() {
             return new ContextStateImpl();
         }
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
index a8436ff49f..22f8ca5d23 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/conn/StdConnections.java
@@ -51,25 +51,27 @@ public class StdConnections {
     }
 
     public static final class ContextStateImpl implements RContext.ContextState {
-        private final StdinConnection stdin;
-        private final StdoutConnection stdout;
-        private final StderrConnection stderr;
+        private StdinConnection stdin;
+        private StdoutConnection stdout;
+        private StderrConnection stderr;
         private final Diversion[] diversions = new Diversion[20];
         private int top = -1;
 
-        private ContextStateImpl(StdinConnection stdin, StdoutConnection stdout, StderrConnection stderr) {
-            this.stdin = stdin;
-            this.stdout = stdout;
-            this.stderr = stderr;
+        public static ContextStateImpl newContextState() {
+            return new ContextStateImpl();
         }
 
-        public static ContextStateImpl newContext(RContext context) {
+        @Override
+        public RContext.ContextState initialize(RContext context) {
             ConsoleHandler consoleHandler = context.getConsoleHandler();
             try {
-                return new ContextStateImpl(new StdinConnection(), new StdoutConnection(consoleHandler), new StderrConnection(consoleHandler));
+                stdin = new StdinConnection();
+                stdout = new StdoutConnection(consoleHandler);
+                stderr = new StderrConnection(consoleHandler);
             } catch (IOException ex) {
                 throw Utils.rSuicide("failed to open stdconnections:");
             }
+            return this;
         }
     }
 
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 80111d53d5..d6c5f4000b 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
@@ -33,6 +33,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal;
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
 import com.oracle.truffle.api.ExecutionContext;
 import com.oracle.truffle.api.Truffle;
+import com.oracle.truffle.api.TruffleLanguage;
 import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.instrumentation.Instrumenter;
 import com.oracle.truffle.api.interop.ForeignAccess;
@@ -143,6 +144,15 @@ public final class RContext extends ExecutionContext implements TruffleObject {
      * interface.
      */
     public interface ContextState {
+        /**
+         * Initialize the state. The initial creation should involve minimal computation; any
+         * significant computation should be handled in this method.
+         */
+        @SuppressWarnings("unused")
+        default ContextState initialize(RContext context) {
+            return this;
+        }
+
         /**
          * Called in response to the {@link RContext#destroy} method. Provides a hook for finalizing
          * any state before the context is destroyed.
@@ -333,7 +343,7 @@ public final class RContext extends ExecutionContext implements TruffleObject {
     /**
      * Initialize VM-wide static values.
      */
-    public static void initialize(RCodeBuilder<RSyntaxNode> rAstBuilder, RRuntimeASTAccess rRuntimeASTAccess, RBuiltinLookup rBuiltinLookup, RForeignAccessFactory rForeignAccessFactory) {
+    public static void initializeGlobalState(RCodeBuilder<RSyntaxNode> rAstBuilder, RRuntimeASTAccess rRuntimeASTAccess, RBuiltinLookup rBuiltinLookup, RForeignAccessFactory rForeignAccessFactory) {
         RContext.astBuilder = rAstBuilder;
         RContext.runtimeASTAccess = rRuntimeASTAccess;
         RContext.builtinLookup = rBuiltinLookup;
@@ -368,19 +378,23 @@ public final class RContext extends ExecutionContext implements TruffleObject {
      * could do this more dynamically with a registration process, perhaps driven by an annotation
      * processor, but the set is relatively small, so we just enumerate them here.
      */
-    public REnvVars stateREnvVars;
-    public RProfile stateRProfile;
-    public ROptions.ContextStateImpl stateROptions;
+    public final REnvVars stateREnvVars;
+    public final RProfile stateRProfile;
+    public final StdConnections.ContextStateImpl stateStdConnections;
+    public final ROptions.ContextStateImpl stateROptions;
     public final REnvironment.ContextStateImpl stateREnvironment;
     public final RErrorHandling.ContextStateImpl stateRErrorHandling;
     public final ConnectionSupport.ContextStateImpl stateRConnection;
-    public final StdConnections.ContextStateImpl stateStdConnections;
     public final RRNG.ContextStateImpl stateRNG;
-    public final ContextState stateRFFI;
     public final RSerialize.ContextStateImpl stateRSerialize;
     public final LazyDBCache.ContextStateImpl stateLazyDBCache;
     public final InstrumentationState stateInstrumentation;
     public final ContextStateImpl stateInternalCode;
+    /**
+     * RFFI implementation state. Cannot be final as choice of FFI implementation is not made at the
+     * time the constructor is called.
+     */
+    private ContextState stateRFFI;
 
     private ContextState[] contextStates() {
         return new ContextState[]{stateREnvVars, stateRProfile, stateROptions, stateREnvironment, stateRErrorHandling, stateRConnection, stateStdConnections, stateRNG, stateRFFI, stateRSerialize,
@@ -395,6 +409,13 @@ public final class RContext extends ExecutionContext implements TruffleObject {
         return embedded;
     }
 
+    /**
+     * Sets the fields that do not depend on complex initialization.
+     *
+     * @param env values passed from {@link TruffleLanguage#createContext}
+     * @param instrumenter value passed from {@link TruffleLanguage#createContext}
+     * @param isInitial {@code true} if this is the initial (primordial) context.
+     */
     private RContext(Env env, Instrumenter instrumenter, boolean isInitial) {
         ContextInfo initialInfo = (ContextInfo) env.importSymbol(ContextInfo.GLOBAL_SYMBOL);
         if (initialInfo == null) {
@@ -408,7 +429,27 @@ public final class RContext extends ExecutionContext implements TruffleObject {
             this.info = initialInfo;
         }
         this.initial = isInitial;
+        this.env = env;
+        this.stateREnvVars = REnvVars.newContextState();
+        this.stateROptions = ROptions.ContextStateImpl.newContextState(stateREnvVars);
+        this.stateRProfile = RProfile.newContextState(stateREnvVars);
+        this.stateStdConnections = StdConnections.ContextStateImpl.newContextState();
+        this.stateREnvironment = REnvironment.ContextStateImpl.newContextState();
+        this.stateRErrorHandling = RErrorHandling.ContextStateImpl.newContextState();
+        this.stateRConnection = ConnectionSupport.ContextStateImpl.newContextState();
+        this.stateRNG = RRNG.ContextStateImpl.newContextState();
+        this.stateRSerialize = RSerialize.ContextStateImpl.newContextState();
+        this.stateLazyDBCache = LazyDBCache.ContextStateImpl.newContextState();
+        this.stateInstrumentation = InstrumentationState.newContextState(instrumenter);
+        this.stateInternalCode = ContextStateImpl.newContextState();
+        this.engine = RContext.getRRuntimeASTAccess().createEngine(this);
+    }
 
+    /**
+     * Performs the real initialization of the context, invoked from
+     * {@link TruffleLanguage#initializeContext}.
+     */
+    public RContext initializeContext() {
         // this must happen before engine activation in the code below
         if (info.getKind() == ContextKind.SHARE_NOTHING) {
             if (info.getParent() == null) {
@@ -423,7 +464,6 @@ public final class RContext extends ExecutionContext implements TruffleObject {
             }
         }
 
-        this.env = env;
         if (info.getConsoleHandler() == null) {
             throw Utils.rSuicide("no console handler set");
         }
@@ -436,7 +476,6 @@ public final class RContext extends ExecutionContext implements TruffleObject {
                 singleContextAssumption.invalidate();
             }
         }
-        engine = RContext.getRRuntimeASTAccess().createEngine(this);
 
         /*
          * Activate the context by attaching the current thread and initializing the {@link
@@ -453,16 +492,19 @@ public final class RContext extends ExecutionContext implements TruffleObject {
         if (!embedded) {
             doEnvOptionsProfileInitialization();
         }
-        stateREnvironment = REnvironment.ContextStateImpl.newContext(this);
-        stateRErrorHandling = RErrorHandling.ContextStateImpl.newContext(this);
-        stateRConnection = ConnectionSupport.ContextStateImpl.newContext(this);
-        stateStdConnections = StdConnections.ContextStateImpl.newContext(this);
-        stateRNG = RRNG.ContextStateImpl.newContext(this);
-        stateRFFI = RFFIContextStateFactory.newContext(this);
-        stateRSerialize = RSerialize.ContextStateImpl.newContext(this);
-        stateLazyDBCache = LazyDBCache.ContextStateImpl.newContext(this);
-        stateInstrumentation = InstrumentationState.newContext(this, instrumenter);
-        stateInternalCode = ContextStateImpl.newContext(this);
+
+        stateREnvironment.initialize(this);
+        stateRErrorHandling.initialize(this);
+        stateRConnection.initialize(this);
+        stateStdConnections.initialize(this);
+        stateRNG.initialize(this);
+        this.stateRFFI = RFFIContextStateFactory.newContextState().initialize(this);
+
+        stateRFFI.initialize(this);
+        stateRSerialize.initialize(this);
+        stateLazyDBCache.initialize(this);
+        stateInstrumentation.initialize(this);
+        stateInternalCode.initialize(this);
 
         if (!embedded) {
             validateContextStates();
@@ -478,20 +520,21 @@ public final class RContext extends ExecutionContext implements TruffleObject {
             // that methods package is loaded
             this.methodTableDispatchOn = info.getParent().methodTableDispatchOn;
         }
-        if (isInitial && !embedded) {
+        if (initial && !embedded) {
             RFFIFactory.getRFFI().getCallRFFI().setInteractive(isInteractive());
             initialContextInitialized = true;
         }
+        return this;
     }
 
     /**
      * Factored out for embedded setup, where this initialization may be customized after the
-     * context is created but before VM really starts execution.
+     * context is initialized but before VM really starts execution.
      */
     private void doEnvOptionsProfileInitialization() {
-        stateREnvVars = REnvVars.newContext(this);
-        stateROptions = ROptions.ContextStateImpl.newContext(this, stateREnvVars);
-        stateRProfile = RProfile.newContext(this, stateREnvVars);
+        stateREnvVars.initialize(this);
+        stateROptions.initialize(this);
+        stateRProfile.initialize(this);
     }
 
     public void completeEmbeddedInitialization() {
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
index e66aef15b5..00915a63c5 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/REnvironment.java
@@ -100,7 +100,7 @@ import com.oracle.truffle.r.runtime.env.frame.REnvTruffleFrameAccess;
  * <p>
  * The logic for implementing the three different forms of
  * {@link com.oracle.truffle.r.runtime.context.RContext.ContextKind} is encapsulated in the
- * {@link #createContext} method.
+ * {@link #setupContext} method.
  */
 public abstract class REnvironment extends RAttributeStorage {
 
@@ -118,15 +118,18 @@ public abstract class REnvironment extends RAttributeStorage {
         private REnvironment namespaceRegistry;
         private MaterializedFrame parentGlobalFrame; // SHARED_PARENT_RW only
 
-        ContextStateImpl(MaterializedFrame globalFrame, SearchPath searchPath) {
+        private ContextStateImpl(MaterializedFrame globalFrame) {
             this.globalFrame = globalFrame;
-            this.searchPath = searchPath;
         }
 
-        ContextStateImpl(MaterializedFrame globalFrame, SearchPath searchPath, Base baseEnv, REnvironment namespaceRegistry) {
-            this(globalFrame, searchPath);
-            this.baseEnv = baseEnv;
-            this.namespaceRegistry = namespaceRegistry;
+        private void initialize(SearchPath searchPathA) {
+            this.searchPath = searchPathA;
+        }
+
+        private void initialize(SearchPath searchPathA, Base baseEnvA, REnvironment namespaceRegistryA) {
+            this.searchPath = searchPathA;
+            this.baseEnv = baseEnvA;
+            this.namespaceRegistry = namespaceRegistryA;
         }
 
         public REnvironment getGlobalEnv() {
@@ -165,13 +168,20 @@ public abstract class REnvironment extends RAttributeStorage {
             this.namespaceRegistry = namespaceRegistry;
         }
 
+        @Override
+        public RContext.ContextState initialize(RContext context) {
+            setupContext(this, context, globalFrame);
+            return this;
+
+        }
+
         @Override
         public void beforeDestroy(RContext context) {
             beforeDestroyContext(context, this);
         }
 
-        public static ContextStateImpl newContext(RContext context) {
-            return createContext(context, RRuntime.createNonFunctionFrame("global"));
+        public static ContextStateImpl newContextState() {
+            return new ContextStateImpl(RRuntime.createNonFunctionFrame("global"));
         }
     }
 
@@ -311,7 +321,7 @@ public abstract class REnvironment extends RAttributeStorage {
      * N.B. {@link RContext#stateREnvironment} accesses the new, as yet uninitialized
      * {@link ContextStateImpl} object
      */
-    private static ContextStateImpl createContext(RContext context, MaterializedFrame globalFrame) {
+    private static void setupContext(ContextStateImpl contextState, RContext context, MaterializedFrame globalFrame) {
         switch (context.getKind()) {
             case SHARE_PARENT_RW: {
                 /*
@@ -331,9 +341,9 @@ public abstract class REnvironment extends RAttributeStorage {
                 SearchPath searchPath = initSearchList(prevGlobalEnv);
                 searchPath.updateGlobal(newGlobalEnv);
                 parentState.getBaseEnv().safePut(".GlobalEnv", newGlobalEnv);
-                ContextStateImpl result = new ContextStateImpl(globalFrame, searchPath, parentBaseEnv, parentState.getNamespaceRegistry());
-                result.parentGlobalFrame = prevGlobalFrame;
-                return result;
+                contextState.initialize(searchPath, parentBaseEnv, parentState.getNamespaceRegistry());
+                contextState.parentGlobalFrame = prevGlobalFrame;
+                break;
             }
 
             case SHARE_PARENT_RO: {
@@ -359,12 +369,14 @@ public abstract class REnvironment extends RAttributeStorage {
                 newNamespaceRegistry.safePut("base", newBaseEnv.namespaceEnv);
                 newBaseEnv.safePut(".GlobalEnv", newGlobalEnv);
                 SearchPath newSearchPath = initSearchList(newGlobalEnv);
-                return new ContextStateImpl(globalFrame, newSearchPath, newBaseEnv, newNamespaceRegistry);
+                contextState.initialize(newSearchPath, newBaseEnv, newNamespaceRegistry);
+                break;
             }
 
             case SHARE_NOTHING: {
                 // SHARE_NOTHING: baseInitialize takes care of everything
-                return new ContextStateImpl(globalFrame, new SearchPath());
+                contextState.initialize(new SearchPath());
+                break;
             }
 
             default:
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContextStateFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContextStateFactory.java
index f18abc1221..934ad58e5e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContextStateFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIContextStateFactory.java
@@ -37,7 +37,7 @@ public class RFFIContextStateFactory {
         theFactory = factory;
     }
 
-    public static ContextState newContext(RContext context) {
-        return theFactory.newContext(context);
+    public static ContextState newContextState() {
+        return theFactory.newContextState();
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
index cdbe8d0b82..c20087b365 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/ffi/RFFIFactory.java
@@ -32,7 +32,7 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextState;
  * choice of factory is made by the R engine and set here by the call to {@link #setRFFIFactory}.
  *
  * The RFFI may need to do special things in the case of multiple contexts, hence any given factory
- * must support the {@link #newContext(RContext)} method. However, since we don't know exactly which
+ * must support the {@link #newContextState()} method. However, since we don't know exactly which
  * factory will be used, {@link RContext} references the {@link RFFIContextStateFactory} class.
  */
 public abstract class RFFIFactory {
@@ -110,5 +110,5 @@ public abstract class RFFIFactory {
         throw Utils.rSuicide(ffi + " FFI not implemented");
     }
 
-    public abstract ContextState newContext(RContext context);
+    public abstract ContextState newContextState();
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java
index b1a55172ce..4af3bde56a 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/instrument/InstrumentationState.java
@@ -278,7 +278,7 @@ public final class InstrumentationState implements RContext.ContextState {
         return debugGloballyDisabled;
     }
 
-    public static InstrumentationState newContext(@SuppressWarnings("unused") RContext context, Instrumenter instrumenter) {
+    public static InstrumentationState newContextState(Instrumenter instrumenter) {
         return new InstrumentationState(instrumenter);
     }
 }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
index e612d30596..88742c5191 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/rng/RRNG.java
@@ -128,11 +128,19 @@ public class RRNG {
         private final RandomNumberGenerator[] allGenerators;
         private NormKind currentNormKind;
 
-        private ContextStateImpl(RandomNumberGenerator rng, NormKind currentNormKind) {
-            this.currentGenerator = rng;
-            this.currentNormKind = currentNormKind;
+        private ContextStateImpl() {
+            this.currentNormKind = DEFAULT_NORM_KIND;
             this.allGenerators = new RandomNumberGenerator[Kind.VALUES.length];
+        }
+
+        @Override
+        public RContext.ContextState initialize(RContext context) {
+            int seed = timeToSeed();
+            RandomNumberGenerator rng = DEFAULT_KIND.create();
+            initGenerator(rng, seed);
+            this.currentGenerator = rng;
             this.allGenerators[rng.getKind().ordinal()] = rng;
+            return this;
         }
 
         /*
@@ -180,11 +188,8 @@ public class RRNG {
             }
         }
 
-        public static ContextStateImpl newContext(@SuppressWarnings("unused") RContext context) {
-            int seed = timeToSeed();
-            RandomNumberGenerator rng = DEFAULT_KIND.create();
-            initGenerator(rng, seed);
-            return new ContextStateImpl(rng, DEFAULT_NORM_KIND);
+        public static ContextStateImpl newContextState() {
+            return new ContextStateImpl();
         }
 
     }
-- 
GitLab