From d3bb25eb3fa57f8b581f4e20ed32316957b2a0bf Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Mon, 12 Dec 2016 13:05:04 +0100
Subject: [PATCH] change R context initialization to store ContextInfo in
 configuration instead of symbol

---
 .../com/oracle/truffle/r/engine/REngine.java  | 23 +++++++++++++++----
 .../interop/ffi/nfi/TruffleNFI_DLL.java       |  8 +++----
 .../interop/ffi/nfi/TruffleNFI_Utils.java     |  8 +++----
 .../truffle/r/engine/shell/RCommand.java      | 11 +++++----
 .../truffle/r/engine/shell/REmbedded.java     |  5 ++--
 .../r/runtime/context/ContextInfo.java        | 13 ++++-------
 .../truffle/r/runtime/context/Engine.java     |  3 +++
 .../truffle/r/runtime/context/RContext.java   | 18 +++++++--------
 .../truffle/r/test/tck/FastRTckTest.java      |  5 ++--
 9 files changed, 53 insertions(+), 41 deletions(-)

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 5245ffc126..8798c06e69 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -40,6 +40,7 @@ import com.oracle.truffle.api.frame.FrameDescriptor;
 import com.oracle.truffle.api.frame.MaterializedFrame;
 import com.oracle.truffle.api.frame.VirtualFrame;
 import com.oracle.truffle.api.interop.TruffleObject;
+import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.nodes.DirectCallNode;
 import com.oracle.truffle.api.nodes.ExplodeLoop;
 import com.oracle.truffle.api.nodes.Node;
@@ -142,8 +143,7 @@ final class REngine implements Engine, Engine.Timings {
     }
 
     static REngine create(RContext context) {
-        REngine engine = new REngine(context);
-        return engine;
+        return new REngine(context);
     }
 
     @Override
@@ -294,8 +294,21 @@ final class REngine implements Engine, Engine.Timings {
 
     @Override
     public CallTarget parseToCallTarget(Source source, MaterializedFrame executionFrame) throws ParseException {
-        List<RSyntaxNode> statements = parseImpl(source);
-        return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements, createSourceSection(source, statements), executionFrame));
+        if (source == Engine.GET_CONTEXT) {
+            /*
+             * The "get context" operations should be executed with as little influence on the
+             * actual engine as possible, therefore this special case takes care of it explicitly.
+             */
+            return Truffle.getRuntime().createCallTarget(new RootNode(TruffleRLanguage.class, source.createUnavailableSection(), new FrameDescriptor()) {
+                @Override
+                public Object execute(VirtualFrame frame) {
+                    return JavaInterop.asTruffleValue(context);
+                }
+            });
+        } else {
+            List<RSyntaxNode> statements = parseImpl(source);
+            return Truffle.getRuntime().createCallTarget(new PolyglotEngineRootNode(statements, createSourceSection(source, statements), executionFrame));
+        }
     }
 
     private static SourceSection createSourceSection(Source source, List<RSyntaxNode> statements) {
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
index 21ca2496f3..36cfaaa2d3 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_DLL.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2016, 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
@@ -23,6 +23,7 @@
 package com.oracle.truffle.r.engine.interop.ffi.nfi;
 
 import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
+import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
@@ -30,7 +31,6 @@ import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnknownIdentifierException;
 import com.oracle.truffle.api.nodes.Node;
 import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
 import com.oracle.truffle.r.runtime.ffi.DLL;
@@ -54,8 +54,8 @@ public class TruffleNFI_DLL implements DLLRFFI {
         @Override
         public Object execute(String path, boolean local, boolean now) {
             String libName = DLL.libName(path);
-            PolyglotEngine engine = RContext.getInstance().getVM();
-            TruffleObject libHandle = engine.eval(Source.newBuilder(prepareLibraryOpen(path, local, now)).name(path).mimeType("application/x-native").build()).as(TruffleObject.class);
+            Env env = RContext.getInstance().getEnv();
+            TruffleObject libHandle = (TruffleObject) env.parse(Source.newBuilder(prepareLibraryOpen(path, local, now)).name(path).mimeType("application/x-native").build()).call();
             return new NFIHandle(libName, libHandle);
         }
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
index df1edddf96..92a0e6dcb4 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/interop/ffi/nfi/TruffleNFI_Utils.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2016, 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
@@ -24,13 +24,13 @@ package com.oracle.truffle.r.engine.interop.ffi.nfi;
 
 import java.nio.charset.StandardCharsets;
 
+import com.oracle.truffle.api.TruffleLanguage.Env;
 import com.oracle.truffle.api.interop.ForeignAccess;
 import com.oracle.truffle.api.interop.InteropException;
 import com.oracle.truffle.api.interop.Message;
 import com.oracle.truffle.api.interop.TruffleObject;
 import com.oracle.truffle.api.interop.UnsupportedMessageException;
 import com.oracle.truffle.api.source.Source;
-import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.engine.interop.UnsafeAdapter;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.context.RContext;
@@ -59,8 +59,8 @@ public class TruffleNFI_Utils {
 
     private static void initDefaultLibrary() {
         if (defaultLibrary == null) {
-            PolyglotEngine engine = RContext.getInstance().getVM();
-            defaultLibrary = engine.eval(Source.newBuilder("default").name("(load default)").mimeType("application/x-native").build()).as(TruffleObject.class);
+            Env env = RContext.getInstance().getEnv();
+            defaultLibrary = (TruffleObject) env.parse(Source.newBuilder("default").name("(load default)").mimeType("application/x-native").build()).call();
         }
 
     }
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
index 53d4271bb1..805e959e9a 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RCommand.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -53,6 +53,7 @@ import com.oracle.truffle.r.runtime.Utils.DebugExitException;
 import com.oracle.truffle.r.runtime.context.ConsoleHandler;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
 import com.oracle.truffle.r.runtime.context.DefaultConsoleHandler;
+import com.oracle.truffle.r.runtime.context.Engine;
 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;
@@ -203,8 +204,8 @@ public class RCommand {
      */
     static int readEvalPrint(PolyglotEngine vm) {
         int lastStatus = 0;
-        ContextInfo contextInfo = ContextInfo.getContextInfo(vm);
-        ConsoleHandler consoleHandler = contextInfo.getConsoleHandler();
+        RContext context = vm.eval(Engine.GET_CONTEXT).as(RContext.class);
+        ConsoleHandler consoleHandler = context.getConsoleHandler();
         try {
             // console.println("initialize time: " + (System.currentTimeMillis() - start));
             REPL: for (;;) {
@@ -261,7 +262,7 @@ public class RCommand {
                         } catch (ExitException e) {
                             // usually from quit
                             int status = e.getStatus();
-                            if (contextInfo.getParent() == null) {
+                            if (context.getParent() == null) {
                                 vm.dispose();
                                 Utils.systemExit(status);
                             } else {
@@ -287,7 +288,7 @@ public class RCommand {
                 Utils.systemExit(0);
             } catch (ExitException e) {
                 // normal quit, but with exit code based on lastStatus
-                if (contextInfo.getParent() == null) {
+                if (context.getParent() == null) {
                     Utils.systemExit(lastStatus);
                 } else {
                     return lastStatus;
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 d0031dd9f6..9a6d8d9490 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
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2016, 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
@@ -31,6 +31,7 @@ import com.oracle.truffle.r.runtime.RSource.Internal;
 import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.Utils;
 import com.oracle.truffle.r.runtime.context.ContextInfo;
+import com.oracle.truffle.r.runtime.context.Engine;
 import com.oracle.truffle.r.runtime.context.RContext;
 
 /**
@@ -105,7 +106,7 @@ public class REmbedded {
      */
     public static void main(String[] args) {
         PolyglotEngine vm = initializeR(args);
-        RStartParams startParams = ContextInfo.getContextInfo(vm).getStartParams();
+        RStartParams startParams = vm.eval(Engine.GET_CONTEXT).as(RContext.class).getStartParams();
         startParams.setEmbedded();
         startParams.setLoadInitFile(false);
         startParams.setNoRenviron(true);
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
index d048d22828..c1d39f9b1e 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2016, 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
@@ -25,7 +25,6 @@ package com.oracle.truffle.r.runtime.context;
 import java.util.TimeZone;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RCmdOptions;
 import com.oracle.truffle.r.runtime.RCmdOptions.Client;
@@ -39,7 +38,7 @@ import com.oracle.truffle.r.runtime.context.RContext.ContextKind;
  * instance (it will be stored in the "fastrContextInfo" global symbol).
  */
 public final class ContextInfo {
-    public static final String GLOBAL_SYMBOL = "fastrContextInfo";
+    static final String CONFIG_KEY = "fastrContextInfo";
 
     private static final AtomicInteger contextInfoIds = new AtomicInteger();
 
@@ -68,13 +67,13 @@ public final class ContextInfo {
     }
 
     public PolyglotEngine createVM() {
-        PolyglotEngine newVM = PolyglotEngine.newBuilder().globalSymbol(GLOBAL_SYMBOL, JavaInterop.asTruffleObject(this)).build();
+        PolyglotEngine newVM = PolyglotEngine.newBuilder().config("application/x-r", CONFIG_KEY, this).build();
         this.vm = newVM;
         return newVM;
     }
 
     public PolyglotEngine createVM(PolyglotEngine.Builder builder) {
-        PolyglotEngine newVM = builder.globalSymbol(GLOBAL_SYMBOL, JavaInterop.asTruffleObject(this)).build();
+        PolyglotEngine newVM = builder.config("application/x-r", CONFIG_KEY, this).build();
         this.vm = newVM;
         return newVM;
     }
@@ -114,10 +113,6 @@ public final class ContextInfo {
         return create(params, env, kind, parent, consoleHandler);
     }
 
-    public static ContextInfo getContextInfo(PolyglotEngine vm) {
-        return vm.findGlobalSymbol(ContextInfo.GLOBAL_SYMBOL).as(ContextInfo.class);
-    }
-
     public RStartParams getStartParams() {
         return startParams;
     }
diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
index ac6079435a..6c7f7f692c 100644
--- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
+++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/Engine.java
@@ -30,6 +30,7 @@ import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RCaller;
 import com.oracle.truffle.r.runtime.RError;
+import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.data.RExpression;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RLanguage;
@@ -39,6 +40,8 @@ import com.oracle.truffle.r.runtime.nodes.RNode;
 
 public interface Engine {
 
+    Source GET_CONTEXT = RSource.fromTextInternal("<<<get_context>>>", RSource.Internal.GET_CONTEXT);
+
     class ParseException extends RuntimeException {
         private static final long serialVersionUID = 1L;
 
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 3e7f4875fc..64339a2fc5 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, 2016, 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
@@ -40,7 +40,6 @@ 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.TruffleObject;
-import com.oracle.truffle.api.interop.java.JavaInterop;
 import com.oracle.truffle.api.source.Source;
 import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.ExitException;
@@ -58,7 +57,6 @@ import com.oracle.truffle.r.runtime.RProfile;
 import com.oracle.truffle.r.runtime.RRuntime;
 import com.oracle.truffle.r.runtime.RRuntimeASTAccess;
 import com.oracle.truffle.r.runtime.RSerialize;
-import com.oracle.truffle.r.runtime.RSource;
 import com.oracle.truffle.r.runtime.RStartParams;
 import com.oracle.truffle.r.runtime.TempPathName;
 import com.oracle.truffle.r.runtime.Utils;
@@ -71,6 +69,7 @@ import com.oracle.truffle.r.runtime.context.Engine.ParseException;
 import com.oracle.truffle.r.runtime.data.RDataFactory;
 import com.oracle.truffle.r.runtime.data.RFunction;
 import com.oracle.truffle.r.runtime.data.RList;
+import com.oracle.truffle.r.runtime.data.RNull;
 import com.oracle.truffle.r.runtime.data.RStringVector;
 import com.oracle.truffle.r.runtime.env.REnvironment;
 import com.oracle.truffle.r.runtime.ffi.DLL;
@@ -215,8 +214,6 @@ public final class RContext extends ExecutionContext {
      */
     public static class EvalThread extends ContextThread {
 
-        private static final Source GET_CONTEXT = RSource.fromTextInternal("invisible(.fastr.context.get())", RSource.Internal.GET_CONTEXT);
-
         private final Source source;
         private final ContextInfo info;
         private RList evalResult;
@@ -232,9 +229,9 @@ public final class RContext extends ExecutionContext {
 
         @Override
         public void run() {
-            PolyglotEngine vm = info.createVM();
+            PolyglotEngine vm = info.createVM(PolyglotEngine.newBuilder());
             try {
-                setContext(vm.eval(GET_CONTEXT).as(RContext.class));
+                setContext(vm.eval(Engine.GET_CONTEXT).as(RContext.class));
             } catch (Throwable t) {
                 throw new RInternalError(t, "error while initializing eval thread");
             }
@@ -260,6 +257,9 @@ public final class RContext extends ExecutionContext {
             } catch (ExitException e) {
                 // termination, treat this as "success"
                 evalResult = RDataFactory.createList(new Object[]{e.getStatus()});
+            } catch (RError e) {
+                // nothing to do
+                evalResult = RDataFactory.createList(new Object[]{RNull.instance});
             } catch (Throwable t) {
                 // some internal error
                 RInternalError.reportErrorAndConsoleLog(t, info.getConsoleHandler(), info.getId());
@@ -445,7 +445,7 @@ public final class RContext extends ExecutionContext {
      * @param isInitial {@code true} if this is the initial (primordial) context.
      */
     private RContext(Env env, Instrumenter instrumenter, boolean isInitial) {
-        Object initialInfo = env.importSymbol(ContextInfo.GLOBAL_SYMBOL);
+        Object initialInfo = env.getConfig().get(ContextInfo.CONFIG_KEY);
         if (initialInfo == null) {
             /*
              * This implies that FastR is being invoked initially from another Truffle language and
@@ -455,7 +455,7 @@ public final class RContext extends ExecutionContext {
             this.info = ContextInfo.create(new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"--no-restore"}, false), false), null,
                             ContextKind.SHARE_NOTHING, null, new DefaultConsoleHandler(env.in(), env.out()));
         } else {
-            this.info = JavaInterop.asJavaObject(ContextInfo.class, (TruffleObject) initialInfo);
+            this.info = (ContextInfo) initialInfo;
         }
 
         this.initial = isInitial;
diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
index 1d79ee857f..48193aea07 100644
--- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
+++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRTckTest.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -40,8 +40,7 @@ import com.oracle.truffle.tck.TruffleTCK;
 public class FastRTckTest extends TruffleTCK {
     @Test
     public void testVerifyPresence() {
-        PolyglotEngine vm = PolyglotEngine.newBuilder().globalSymbol(ContextInfo.GLOBAL_SYMBOL,
-                        null).build();
+        PolyglotEngine vm = PolyglotEngine.newBuilder().build();
         assertTrue("Our language is present", vm.getLanguages().containsKey("text/x-r"));
     }
 
-- 
GitLab