From 895e82cfe641d452829e8f25932319355be786ba Mon Sep 17 00:00:00 2001
From: Lukas Stadler <lukas.stadler@oracle.com>
Date: Tue, 11 Apr 2017 15:41:34 +0200
Subject: [PATCH] minimize use of Java interop

---
 .../truffle/r/engine/shell/RCommand.java      | 20 +++++------
 .../truffle/r/engine/shell/REmbedded.java     | 34 +++++++++++--------
 .../r/engine/shell/RscriptCommand.java        |  6 ++--
 .../fficall/src/jni/Rembedded.c               | 14 ++++----
 4 files changed, 37 insertions(+), 37 deletions(-)

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 805e959e9a..44d6bba5c3 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, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2017, 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,7 +53,6 @@ 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;
@@ -78,8 +77,8 @@ public class RCommand {
     public static int doMain(String[] args, String[] env, boolean initial, InputStream inStream, OutputStream outStream) {
         RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, false);
         options.printHelpAndVersion();
-        PolyglotEngine vm = createPolyglotEngineFromCommandLine(options, false, initial, inStream, outStream, env);
-        return readEvalPrint(vm);
+        ContextInfo info = createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env);
+        return readEvalPrint(info.createVM(), info);
     }
 
     /**
@@ -89,7 +88,7 @@ public class RCommand {
         return input.replace("~+~", " ");
     }
 
-    static PolyglotEngine createPolyglotEngineFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) {
+    static ContextInfo createContextInfoFromCommandLine(RCmdOptions options, boolean embedded, boolean initial, InputStream inStream, OutputStream outStream, String[] env) {
         RStartParams rsp = new RStartParams(options, embedded);
 
         String fileArg = options.getString(FILE);
@@ -185,7 +184,7 @@ public class RCommand {
                 }
             }
         }
-        return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler).createVM();
+        return ContextInfo.create(rsp, env, ContextKind.SHARE_NOTHING, initial ? null : RContext.getInstance(), consoleHandler);
     }
 
     private static final Source GET_ECHO = RSource.fromTextInternal("invisible(getOption('echo'))", RSource.Internal.GET_ECHO);
@@ -202,10 +201,9 @@ public class RCommand {
      * In case 2, we must implicitly execute a {@code quit("default, 0L, TRUE} command before
      * exiting. So,in either case, we never return.
      */
-    static int readEvalPrint(PolyglotEngine vm) {
+    static int readEvalPrint(PolyglotEngine vm, ContextInfo info) {
         int lastStatus = 0;
-        RContext context = vm.eval(Engine.GET_CONTEXT).as(RContext.class);
-        ConsoleHandler consoleHandler = context.getConsoleHandler();
+        ConsoleHandler consoleHandler = info.getConsoleHandler();
         try {
             // console.println("initialize time: " + (System.currentTimeMillis() - start));
             REPL: for (;;) {
@@ -262,7 +260,7 @@ public class RCommand {
                         } catch (ExitException e) {
                             // usually from quit
                             int status = e.getStatus();
-                            if (context.getParent() == null) {
+                            if (info.getParent() == null) {
                                 vm.dispose();
                                 Utils.systemExit(status);
                             } else {
@@ -288,7 +286,7 @@ public class RCommand {
                 Utils.systemExit(0);
             } catch (ExitException e) {
                 // normal quit, but with exit code based on lastStatus
-                if (context.getParent() == null) {
+                if (info.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 9a6d8d9490..d396a37419 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, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, 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,7 +31,6 @@ 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;
 
 /**
@@ -55,24 +54,28 @@ import com.oracle.truffle.r.runtime.context.RContext;
  * object which is itself stored as a global symbol in the associated {@link PolyglotEngine}
  * instance. The FastR {@link PolyglotEngine} is then partially initialized. The call to
  * {@code R_SetParams} will adjust the values stored in the {@link RStartParams} object and then
- * {@code Rf_mainloop}, which calls {@link #setupRmainloop(PolyglotEngine)} and then
- * {@link #runRmainloop(PolyglotEngine)}, which will complete the FastR initialization and enter the
- * read-eval-print loop.
+ * {@code Rf_mainloop}, which calls {@link #setupRmainloop()} and then {@link #runRmainloop()},
+ * which will complete the FastR initialization and enter the read-eval-print loop.
  */
 public class REmbedded {
 
+    private static ContextInfo info;
+    private static PolyglotEngine vm;
+
     /**
      * Creates the {@link PolyglotEngine} and initializes it. Called from native code when FastR is
      * embedded. Corresponds to FFI method {@code Rf_initialize_R}. N.B. This does not completely
      * initialize FastR as we cannot do that until the embedding system has had a chance to adjust
      * the {@link RStartParams}, which happens after this call returns.
      */
-    private static PolyglotEngine initializeR(String[] args) {
+    private static void initializeR(String[] args) {
+        assert vm == null;
+        assert info == null;
         RContext.setEmbedded();
         RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.R, args, true);
-        PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, true, true, System.in, System.out, null);
+        info = RCommand.createContextInfoFromCommandLine(options, true, true, System.in, System.out, null);
+        vm = info.createVM();
         vm.eval(INIT);
-        return vm;
     }
 
     /**
@@ -86,32 +89,33 @@ public class REmbedded {
      * GnuR distinguishes {@code setup_Rmainloop} and {@code run_Rmainloop}. Currently we don't have
      * the equivalent separation in FastR.
      */
-    private static void setupRmainloop(@SuppressWarnings("unused") PolyglotEngine vm) {
+    private static void setupRmainloop() {
+        // nothing to do
     }
 
     /**
      * This is where we can complete the initialization based on what modifications were made by the
      * native code after {@link #initializeR} returned.
      */
-    private static void runRmainloop(PolyglotEngine vm) {
+    private static void runRmainloop() {
         RContext.getInstance().completeEmbeddedInitialization();
         if (!RContext.getInstance().getStartParams().getQuiet()) {
             RContext.getInstance().getConsoleHandler().println(RRuntime.WELCOME_MESSAGE);
         }
-        RCommand.readEvalPrint(vm);
+        RCommand.readEvalPrint(vm, info);
     }
 
     /**
      * Testing vehicle, emulates a native upcall.
      */
     public static void main(String[] args) {
-        PolyglotEngine vm = initializeR(args);
-        RStartParams startParams = vm.eval(Engine.GET_CONTEXT).as(RContext.class).getStartParams();
+        initializeR(args);
+        RStartParams startParams = info.getStartParams();
         startParams.setEmbedded();
         startParams.setLoadInitFile(false);
         startParams.setNoRenviron(true);
-        setupRmainloop(vm);
-        runRmainloop(vm);
+        setupRmainloop();
+        runRmainloop();
     }
 
     // Checkstyle: stop method name check
diff --git a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
index 03ffb7af58..8e2be1e76a 100644
--- a/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
+++ b/com.oracle.truffle.r.engine/src/com/oracle/truffle/r/engine/shell/RscriptCommand.java
@@ -34,10 +34,10 @@ import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
 
-import com.oracle.truffle.api.vm.PolyglotEngine;
 import com.oracle.truffle.r.runtime.RCmdOptions;
 import com.oracle.truffle.r.runtime.RInternalError;
 import com.oracle.truffle.r.runtime.RVersionNumber;
+import com.oracle.truffle.r.runtime.context.ContextInfo;
 
 /**
  * Emulates the (Gnu)Rscript command as precisely as possible. in GnuR, Rscript is a genuine wrapper
@@ -117,8 +117,8 @@ public class RscriptCommand {
         // Handle --help and --version specially, as they exit.
         RCmdOptions options = RCmdOptions.parseArguments(RCmdOptions.Client.RSCRIPT, args, false);
         preprocessRScriptOptions(options);
-        PolyglotEngine vm = RCommand.createPolyglotEngineFromCommandLine(options, false, initial, inStream, outStream, env);
-        return RCommand.readEvalPrint(vm);
+        ContextInfo info = RCommand.createContextInfoFromCommandLine(options, false, initial, inStream, outStream, env);
+        return RCommand.readEvalPrint(info.createVM(), info);
 
     }
 
diff --git a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
index c9b70d1372..c38eab99ff 100644
--- a/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
+++ b/com.oracle.truffle.r.native/fficall/src/jni/Rembedded.c
@@ -20,7 +20,6 @@
 extern char **environ;
 
 static JavaVM *javaVM;
-static jobject engine;
 static int initialized = 0;
 static char *java_home;
 
@@ -163,15 +162,14 @@ int Rf_initialize_R(int argc, char *argv[]) {
 	rembeddedClass = checkFindClass(jniEnv, "com/oracle/truffle/r/engine/shell/REmbedded");
 	rStartParamsClass = checkFindClass(jniEnv, "com/oracle/truffle/r/runtime/RStartParams");
 	jclass stringClass = checkFindClass(jniEnv, "java/lang/String");
-	jmethodID initializeMethod = checkGetMethodID(jniEnv, rembeddedClass, "initializeR",
-			"([Ljava/lang/String;)Lcom/oracle/truffle/api/vm/PolyglotEngine;", 1);
+	jmethodID initializeMethod = checkGetMethodID(jniEnv, rembeddedClass, "initializeR", "([Ljava/lang/String;)V", 1);
 	jobjectArray argsArray = (*jniEnv)->NewObjectArray(jniEnv, argc, stringClass, NULL);
 	for (int i = 0; i < argc; i++) {
 		jstring arg = (*jniEnv)->NewStringUTF(jniEnv, argv[i]);
 		(*jniEnv)->SetObjectArrayElement(jniEnv, argsArray, i, arg);
 	}
 	// Can't TRACE this upcall as system not initialized
-	engine = checkRef(jniEnv, (*jniEnv)->CallStaticObjectMethod(jniEnv, rembeddedClass, initializeMethod, argsArray));
+	(*jniEnv)->CallStaticObjectMethod(jniEnv, rembeddedClass, initializeMethod, argsArray);
 	initialized++;
 	return 0;
 }
@@ -250,15 +248,15 @@ static void setupOverrides(void);
 
 void setup_Rmainloop(void) {
 	JNIEnv *jniEnv = getEnv();
-	jmethodID setupMethod = checkGetMethodID(jniEnv, rembeddedClass, "setupRmainloop", "(Lcom/oracle/truffle/api/vm/PolyglotEngine;)V", 1);
-	(*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, setupMethod, engine);
+	jmethodID setupMethod = checkGetMethodID(jniEnv, rembeddedClass, "setupRmainloop", "()V", 1);
+	(*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, setupMethod);
 }
 
 void run_Rmainloop(void) {
 	JNIEnv *jniEnv = getEnv();
 	setupOverrides();
-	jmethodID mainloopMethod = checkGetMethodID(jniEnv, rembeddedClass, "runRmainloop", "(Lcom/oracle/truffle/api/vm/PolyglotEngine;)V", 1);
-	(*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, mainloopMethod, engine);
+	jmethodID mainloopMethod = checkGetMethodID(jniEnv, rembeddedClass, "runRmainloop", "()V", 1);
+	(*jniEnv)->CallStaticVoidMethod(jniEnv, rembeddedClass, mainloopMethod);
 }
 
 void Rf_mainloop(void) {
-- 
GitLab