From 1118567889cd6f635dec218ff05613d86b567d7e Mon Sep 17 00:00:00 2001 From: Mick Jordan <mick.jordan@oracle.com> Date: Wed, 26 Jul 2017 15:43:19 -0700 Subject: [PATCH] Changes for Truffle Polyglot rev 12 --- .../com/oracle/truffle/r/engine/REngine.java | 5 ++ .../truffle/r/engine/shell/REmbedded.java | 15 ++-- .../oracle/truffle/r/launcher/Launcher.java | 18 +---- .../oracle/truffle/r/launcher/RCommand.java | 8 +- .../r/nodes/builtin/fastr/FastRContext.java | 41 ++++++---- .../truffle/r/runtime/FastROptions.java | 1 + ...ContextInfo.java => ChildContextInfo.java} | 42 ++++++++--- .../truffle/r/runtime/context/Engine.java | 6 ++ .../truffle/r/runtime/context/EvalThread.java | 75 ++++++++++++++++--- .../truffle/r/runtime/context/RContext.java | 28 ++++--- .../env/frame/FrameSlotChangeMonitor.java | 6 +- .../com/oracle/truffle/r/test/TestBase.java | 6 +- .../truffle/r/test/generate/FastRSession.java | 16 ++-- .../r/test/generate/GnuROneShotRSession.java | 4 +- .../truffle/r/test/generate/RSession.java | 4 +- .../truffle/r/test/tck/FastRDebugTest.java | 4 +- mx.fastr/suite.py | 2 +- 17 files changed, 189 insertions(+), 92 deletions(-) rename com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/{ContextInfo.java => ChildContextInfo.java} (75%) 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 80b3c4825c..50d3fb27c9 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 @@ -234,6 +234,11 @@ final class REngine implements Engine, Engine.Timings { return this; } + @Override + public MaterializedFrame getGlobalFrame() { + return globalFrame; + } + @Override public long elapsedTimeInNanos() { return System.nanoTime() - startTime; 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 39a0b3a60a..a05716cad3 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 @@ -34,7 +34,7 @@ import com.oracle.truffle.r.launcher.RStartParams; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource.Internal; import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.ChildContextInfo; import com.oracle.truffle.r.runtime.context.RContext; /** @@ -54,12 +54,13 @@ import com.oracle.truffle.r.runtime.context.RContext; * </pre> * * {@code Rf_initialize_R} invokes {@link #initializeR(String[])}. This creates an - * {@link RStartParams} object in {@code embedded} mode that is recorded in the {@link ContextInfo} - * 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()} and then {@link #runRmainloop()}, - * which will complete the FastR initialization and enter the read-eval-print loop. + * {@link RStartParams} object in {@code embedded} mode that is recorded in the + * {@link ChildContextInfo} 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()} and then + * {@link #runRmainloop()}, which will complete the FastR initialization and enter the + * read-eval-print loop. */ public class REmbedded { diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/Launcher.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/Launcher.java index c95b28a240..15052181a4 100644 --- a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/Launcher.java +++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/Launcher.java @@ -333,9 +333,9 @@ public abstract class Launcher { default: Engine engine = getTempEngine(); if (engine.getLanguages().containsKey(group)) { - descriptors = engine.getLanguage(group).getOptions(); + descriptors = engine.getLanguages().get(group).getOptions(); } else if (engine.getInstruments().containsKey(group)) { - descriptors = engine.getInstrument(group).getOptions(); + descriptors = engine.getInstruments().get(group).getOptions(); } break; } @@ -460,30 +460,18 @@ public abstract class Launcher { System.out.println(" Installed Languages:"); List<Language> languages = new ArrayList<>(engine.getLanguages().size()); int nameLength = 0; - boolean hasHost = false; for (Language language : engine.getLanguages().values()) { languages.add(language); nameLength = max(nameLength, language.getName().length()); - hasHost |= language.isHost(); } languages.sort(Comparator.comparing(Language::getId)); String langFormat = " %-" + nameLength + "s%s version %s%n"; for (Language language : languages) { - String host; - if (hasHost) { - if (language.isHost()) { - host = " (Host)"; - } else { - host = " "; - } - } else { - host = ""; - } String version = language.getVersion(); if (version == null || version.length() == 0) { version = ""; } - System.out.printf(langFormat, language.getName().isEmpty() ? "Unnamed" : language.getName(), host, version); + System.out.printf(langFormat, language.getName().isEmpty() ? "Unnamed" : language.getName(), version); } } } diff --git a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java index a173a08ec6..fc99b4772b 100644 --- a/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java +++ b/com.oracle.truffle.r.launcher/src/com/oracle/truffle/r/launcher/RCommand.java @@ -129,7 +129,11 @@ public class RCommand { } } if (addArg) { - argsList.add(1, "--interactive"); + if (argsList.size() == 0) { + argsList.add("--interactive"); + } else { + argsList.add(1, "--interactive"); + } } } @@ -145,7 +149,7 @@ public class RCommand { return 0; } RCmdOptions options = RCmdOptions.parseArguments(Client.R, argsList.toArray(new String[argsList.size()]), false); - assert env == null : "re-enable setting environments"; + assert env == null || env.length == 0 : "re-enable setting environments"; ConsoleHandler consoleHandler = createConsoleHandler(options, false, inStream, outStream); try (Context context = Context.newBuilder().options(polyglotOptions).arguments("R", options.getArguments()).in(consoleHandler.createInputStream()).out(outStream).err(errStream).build()) { consoleHandler.setContext(context); diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java index 930598b4ff..5fad15577e 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRContext.java @@ -34,6 +34,7 @@ import static com.oracle.truffle.r.runtime.builtins.RBehavior.READS_STATE; import static com.oracle.truffle.r.runtime.builtins.RBuiltinKind.PRIMITIVE; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.interop.TruffleObject; @@ -48,7 +49,7 @@ import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RRuntime; import com.oracle.truffle.r.runtime.RSource; import com.oracle.truffle.r.runtime.builtins.RBuiltin; -import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.ChildContextInfo; import com.oracle.truffle.r.runtime.context.EvalThread; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.ConsoleIO; @@ -100,7 +101,7 @@ public class FastRContext { if (contextKind == ContextKind.SHARE_ALL && EvalThread.threadCnt.get() == 0) { RContext current = RContext.getInstance(); if (EvalThread.threadCnt.get() == 0 && (current.isInitial() || current.getKind() == ContextKind.SHARE_PARENT_RW)) { - ContextInfo.resetMultiSlotIndexGenerator(); + ChildContextInfo.resetMultiSlotIndexGenerator(); } else { throw RError.error(RError.NO_CALLER, RError.Message.GENERIC, "Shared contexts can be created only if no other child contexts exist"); } @@ -140,8 +141,12 @@ public class FastRContext { int[] data = new int[length]; int[] multiSlotIndices = new int[length]; for (int i = 0; i < length; i++) { - ContextInfo info = createContextInfo(contextKind); - threads[i] = new EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); + ChildContextInfo info = createContextInfo(contextKind); + if (FastROptions.SpawnUsesPloyglot.getBooleanValue()) { + threads[i] = new EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL), true); + } else { + threads[i] = new EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); + } data[i] = info.getId(); multiSlotIndices[i] = info.getMultiSlotInd(); } @@ -234,19 +239,15 @@ public class FastRContext { int length = exprs.getLength(); Object[] results = new Object[length]; if (length == 1) { - ContextInfo info = createContextInfo(contextKind); - PolyglotEngine vm = info.createVM(); - try { - results[0] = EvalThread.run(vm, info, RSource.fromTextInternalInvisible(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL)); - } finally { - vm.dispose(); - } + ChildContextInfo info = createContextInfo(contextKind); + TruffleContext truffleContext = info.createTruffleContext(); + results[0] = EvalThread.run(truffleContext, info, RSource.fromTextInternalInvisible(exprs.getDataAt(0), RSource.Internal.CONTEXT_EVAL)); } else { // separate threads that run in parallel; invoking thread waits for completion EvalThread[] threads = new EvalThread[length]; int[] multiSlotIndices = new int[length]; for (int i = 0; i < length; i++) { - ContextInfo info = createContextInfo(contextKind); + ChildContextInfo info = createContextInfo(contextKind); threads[i] = new EvalThread(info, RSource.fromTextInternalInvisible(exprs.getDataAt(i % exprs.getLength()), RSource.Internal.CONTEXT_EVAL)); multiSlotIndices[i] = info.getMultiSlotInd(); } @@ -291,7 +292,7 @@ public class FastRContext { @Specialization @TruffleBoundary protected Object r(RAbstractStringVector args, RAbstractStringVector env, boolean intern) { - Object rc = RContext.getRRuntimeASTAccess().rcommandMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern); + Object rc = RContext.getRRuntimeASTAccess().rcommandMain(prependCommand(args, "R"), env.materialize().getDataCopy(), intern); return rc; } @@ -327,7 +328,7 @@ public class FastRContext { @Specialization @TruffleBoundary protected Object rscript(RAbstractStringVector args, RAbstractStringVector env, boolean intern) { - return RContext.getRRuntimeASTAccess().rscriptMain(args.materialize().getDataCopy(), env.materialize().getDataCopy(), intern); + return RContext.getRRuntimeASTAccess().rscriptMain(prependCommand(args, "Rscript"), env.materialize().getDataCopy(), intern); } @Specialization @@ -337,10 +338,18 @@ public class FastRContext { } } - private static ContextInfo createContextInfo(RContext.ContextKind contextKind) { + private static String[] prependCommand(RAbstractStringVector argsVec, String command) { + String[] argsVecArgs = argsVec.materialize().getDataCopy(); + String[] result = new String[argsVecArgs.length + 1]; + result[0] = command; + System.arraycopy(argsVecArgs, 0, result, 1, argsVecArgs.length); + return result; + } + + private static ChildContextInfo createContextInfo(RContext.ContextKind contextKind) { RContext context = RContext.getInstance(); ConsoleIO console = context.getConsole(); - return ContextInfo.createNoRestore(Client.RSCRIPT, null, contextKind, context, console.getStdin(), console.getStdout(), console.getStderr()); + return ChildContextInfo.createNoRestore(Client.RSCRIPT, null, contextKind, context, console.getStdin(), console.getStdout(), console.getStderr()); } @RBuiltin(name = ".fastr.channel.create", kind = PRIMITIVE, parameterNames = {"key"}, behavior = COMPLEX) diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java index a3bac44785..935d7b6995 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/FastROptions.java @@ -60,6 +60,7 @@ public enum FastROptions { EmitTmpSource("Write deparsed source code to temporary files for better debugging.", true), EmitTmpDir("The directory where to allocate temporary files with deparsed source code.", null, true), EmitTmpHashed("Use an SHA-256 hash as file name to reduce temporary file creation.", true), + SpawnUsesPloyglot("use PolyglotEngine for .fastr.context.spwan", true), // Promises optimizations EagerEval("If enabled, overrides all other EagerEval switches (see EagerEvalHelper)", false), 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/ChildContextInfo.java similarity index 75% rename from com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ContextInfo.java rename to com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/ChildContextInfo.java index 57d153738c..bdcd6c61d3 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/ChildContextInfo.java @@ -30,6 +30,7 @@ import java.util.concurrent.Executor; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; +import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.api.vm.PolyglotEngine.Builder; import com.oracle.truffle.r.launcher.RCmdOptions; @@ -54,12 +55,16 @@ final class ConsoleHandlerOutputStream extends OutputStream { } /** - * Represents custom initialization state for an R instance. + * Represents custom initialization state for a "spawned" R instance, that is one created by, e.g., + * {@code .fastr.context.eval} and test contexts. In particular there is no {@link ChildContextInfo} + * for the initial context, whether created by the {@code R/RScript} command or whether invoked from + * another language. + * + * There are some legacy functions that still use {@link PolyglotEngine} but the new way is to use + * {@link TruffleContext}. * - * Use {@link #createVM()} to apply this information to a newly-built {@link PolyglotEngine} - * instance (it will be stored in the "fastrContextInfo" global symbol). */ -public final class ContextInfo { +public final class ChildContextInfo { static final String CONFIG_KEY = "fastrContextInfo"; static final AtomicInteger contextInfoIds = new AtomicInteger(); @@ -80,10 +85,11 @@ public final class ContextInfo { private final OutputStream stderr; private final int id; private final int multiSlotInd; + private TruffleContext truffleContext; private PolyglotEngine vm; public Executor executor; - private ContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr, TimeZone systemTimeZone, int id, + private ChildContextInfo(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr, TimeZone systemTimeZone, int id, int multiSlotInd) { this.startParams = startParams; this.env = env; @@ -109,6 +115,16 @@ public final class ContextInfo { multiSlotInds.set(0); // to account for primordial context } + public TruffleContext createTruffleContext() { + this.truffleContext = RContext.getInstance().getEnv().newContextBuilder().config("parentContext", parent.getVM()).config(CONFIG_KEY, this).build(); + return this.truffleContext; + } + + public TruffleContext createVM(ChildContextInfo childContextInfo) { + this.truffleContext = RContext.getInstance().getEnv().newContextBuilder().config("parentContext", parent.getVM()).config(CONFIG_KEY, this).build(); + return this.truffleContext; + } + public PolyglotEngine createVM() { Builder builder = PolyglotEngine.newBuilder(); if (startParams.isInteractive()) { @@ -129,13 +145,14 @@ public final class ContextInfo { /** * Create a context configuration object. * - * @param startParams the start parameters passed this R session + * @param startParams the start parameters passed this spawned R session * @param kind defines the degree to which this context shares base and package environments * with its parent * @param parent if non-null {@code null}, the parent creating the context * @param systemTimeZone the system's time zone */ - public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr, TimeZone systemTimeZone) { + public static ChildContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr, + TimeZone systemTimeZone) { int id = contextInfoIds.incrementAndGet(); int multiSlotInd = multiSlotInds.get(); if (kind == ContextKind.SHARE_ALL || kind == ContextKind.SHARE_NOTHING) { @@ -147,10 +164,10 @@ public final class ContextInfo { throw RInternalError.shouldNotReachHere(); } assert kind != ContextKind.SHARE_PARENT_RW || (kind == ContextKind.SHARE_PARENT_RW && parent.getKind() == ContextKind.SHARE_NOTHING && parent.getMultiSlotInd() == 0); - return new ContextInfo(startParams, env, kind, parent, stdin, stdout, stderr, systemTimeZone, id, kind == ContextKind.SHARE_PARENT_RW ? 0 : multiSlotInd); + return new ChildContextInfo(startParams, env, kind, parent, stdin, stdout, stderr, systemTimeZone, id, kind == ContextKind.SHARE_PARENT_RW ? 0 : multiSlotInd); } - public static ContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr) { + public static ChildContextInfo create(RStartParams startParams, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr) { return create(startParams, env, kind, parent, stdin, stdout, stderr, TimeZone.getDefault()); } @@ -163,7 +180,7 @@ public final class ContextInfo { * with its parent * @param parent if non-null {@code null}, the parent creating the context */ - public static ContextInfo createNoRestore(Client client, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr) { + public static ChildContextInfo createNoRestore(Client client, String[] env, ContextKind kind, RContext parent, InputStream stdin, OutputStream stdout, OutputStream stderr) { RStartParams params = new RStartParams(RCmdOptions.parseArguments(client, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false); return create(params, env, kind, parent, stdin, stdout, stderr); } @@ -196,6 +213,11 @@ public final class ContextInfo { return multiSlotInd; } + public TruffleContext getTruffleContext() { + return truffleContext; + } + + @Deprecated public PolyglotEngine getVM() { return vm; } 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 104c27b4a7..8ad26ae5a0 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 @@ -237,4 +237,10 @@ public interface Engine { * Essentially this is equivalent to {@link #evalFunction} using the {@code "print"} function. */ void printResult(Object value); + + /** + * Return the "global" frame for this {@link Engine}, aka {@code globalEnv}. + * + */ + MaterializedFrame getGlobalFrame(); } diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java index ac0107b5f7..d515b1d63d 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/context/EvalThread.java @@ -28,10 +28,12 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.atomic.AtomicInteger; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.r.runtime.ExitException; +import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RRuntime; @@ -46,7 +48,9 @@ import com.oracle.truffle.r.runtime.data.RNull; public class EvalThread extends Thread { private final Source source; - private final ContextInfo info; + private final ChildContextInfo info; + private final TruffleContext truffleContext; + private final boolean usePolyglot; private RList evalResult; private Semaphore init = new Semaphore(0); @@ -58,22 +62,37 @@ public class EvalThread extends Thread { /** We use a separate counter for threads since ConcurrentHashMap.size() is not reliable. */ public static final AtomicInteger threadCnt = new AtomicInteger(0); - public EvalThread(ContextInfo info, Source source) { + public EvalThread(ChildContextInfo info, Source source) { this.info = info; this.source = source; threadCnt.incrementAndGet(); threads.put(info.getId(), this); idToMultiSlotTable.put(info.getId(), info.getMultiSlotInd()); + truffleContext = info.createTruffleContext(); + usePolyglot = false; + } + + public EvalThread(ChildContextInfo info, Source source, boolean usePolyglot) { + this.info = info; + this.source = source; + threadCnt.incrementAndGet(); + threads.put(info.getId(), this); + idToMultiSlotTable.put(info.getId(), info.getMultiSlotInd()); + this.usePolyglot = true; + truffleContext = null; } @Override public void run() { - PolyglotEngine vm = info.createVM(PolyglotEngine.newBuilder()); init.release(); try { - evalResult = run(vm, info, source); + if (usePolyglot) { + PolyglotEngine vm = info.createVM(PolyglotEngine.newBuilder()); + evalResult = run(vm, info, source); + } else { + evalResult = run(truffleContext, info, source); + } } finally { - vm.dispose(); threads.remove(info.getId()); threadCnt.decrementAndGet(); } @@ -94,11 +113,40 @@ public class EvalThread extends Thread { /** * Convenience method for {@code .fastr.context.eval} in same thread. */ - public static RList run(PolyglotEngine vm, ContextInfo info, Source source) { + public static RList run(TruffleContext truffleContext, ChildContextInfo info, Source source) { + RList result = null; + Object parent = null; + try { + parent = truffleContext.enter(); + // this is the engine for the new child context + Engine rEngine = RContext.getEngine(); + Object evalResult = rEngine.parseAndEval(source, rEngine.getGlobalFrame(), false); + result = createEvalResult(evalResult, false); + } catch (ParseException e) { + e.report(info.getStdout()); + result = createErrorResult(e.getMessage()); + } catch (ExitException e) { + // termination, treat this as "success" + result = RDataFactory.createList(new Object[]{e.getStatus()}); + } catch (RError e) { + // nothing to do + result = RDataFactory.createList(new Object[]{RNull.instance}); + } catch (Throwable t) { + // some internal error + RInternalError.reportErrorAndConsoleLog(t, info.getId()); + result = createErrorResult(t.getClass().getSimpleName()); + } finally { + truffleContext.leave(parent); + truffleContext.close(); + } + return result; + } + + public static RList run(PolyglotEngine vm, ChildContextInfo info, Source source) { RList evalResult; try { PolyglotEngine.Value resultValue = vm.eval(source); - evalResult = createEvalResult(resultValue); + evalResult = createEvalResult(resultValue, true); } catch (ParseException e) { e.report(info.getStdout()); evalResult = createErrorResult(e.getMessage()); @@ -112,6 +160,8 @@ public class EvalThread extends Thread { // some internal error RInternalError.reportErrorAndConsoleLog(t, info.getId()); evalResult = createErrorResult(t.getClass().getSimpleName()); + // } finally { + // vm.close(); } return evalResult; } @@ -121,8 +171,7 @@ public class EvalThread extends Thread { * resulted in an error. */ @TruffleBoundary - private static RList createEvalResult(PolyglotEngine.Value resultValue) { - Object result = resultValue.get(); + private static RList createEvalResult(Object result, boolean usePolyglot) { Object listResult = result; String error = null; if (result == null) { @@ -130,7 +179,11 @@ public class EvalThread extends Thread { listResult = RRuntime.LOGICAL_NA; error = "R error"; } else if (result instanceof TruffleObject) { - listResult = resultValue.as(Object.class); + if (usePolyglot) { + listResult = ((PolyglotEngine.Value) result).as(Object.class); + } else { + throw RInternalError.unimplemented(); + } } else { listResult = result; } @@ -153,7 +206,7 @@ public class EvalThread extends Thread { return evalResult; } - public ContextInfo getContextInfo() { + public ChildContextInfo getContextInfo() { return info; } } 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 d9f72a3fe2..b6d94d8d5c 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 @@ -52,6 +52,7 @@ import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.RootCallTarget; import com.oracle.truffle.api.Truffle; +import com.oracle.truffle.api.TruffleContext; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.TruffleLanguage.Env; import com.oracle.truffle.api.instrumentation.AllocationReporter; @@ -106,7 +107,7 @@ import com.oracle.truffle.r.runtime.rng.RRNG; * * Contexts are created during construction of the {@link PolyglotEngine} instance. In case a * context needs to be configured, the PolyglotEngine needs to be created via the - * {@code RContextFactory} class, which takes a {@link ContextInfo} object for configuration. + * {@code RContextFactory} class, which takes a {@link ChildContextInfo} object for configuration. * * The context provides a so-called {@link Engine} (accessed via {@link #getEngine()}), which * provides basic parsing and execution functionality . @@ -242,7 +243,9 @@ public final class RContext implements RTruffleObject { private final RContext parentContext; private final int id; private final int multiSlotIndex; - private PolyglotEngine polyglotEngine; + private TruffleContext truffleContext; + private PolyglotEngine vm; + public Executor executor; private final InputStream stdin; @@ -379,11 +382,11 @@ public final class RContext implements RTruffleObject { args = env.getApplicationArguments(); } - Object initialInfo = env.getConfig().get(ContextInfo.CONFIG_KEY); + Object initialInfo = env.getConfig().get(ChildContextInfo.CONFIG_KEY); if (initialInfo == null) { /* - * This implies that FastR is being invoked initially from another Truffle language and - * not via RCommand/RscriptCommand. In this case, we also assume that no previously + * This implies that FastR is being invoked initially from another Truffle language or + * via RCommand/RscriptCommand. TODO How to deciden if session state is to be restored * stored session should be restored. */ this.cmdOptions = RCmdOptions.parseArguments(Client.R, args, true); @@ -392,12 +395,13 @@ public final class RContext implements RTruffleObject { this.contextKind = ContextKind.SHARE_NOTHING; this.systemTimeZone = TimeZone.getDefault(); this.parentContext = null; - this.id = ContextInfo.contextInfoIds.incrementAndGet(); + this.id = ChildContextInfo.contextInfoIds.incrementAndGet(); this.multiSlotIndex = 0; - this.polyglotEngine = null; + this.truffleContext = null; // TODO this.executor = null; } else { - ContextInfo info = (ContextInfo) initialInfo; + // child spawned explicitly by R + ChildContextInfo info = (ChildContextInfo) initialInfo; this.cmdOptions = RCmdOptions.parseArguments(Client.R, args, true); this.startParameters = info.getStartParams(); this.environment = info.getEnv(); @@ -406,7 +410,7 @@ public final class RContext implements RTruffleObject { this.parentContext = info.getParent(); this.id = info.getId(); this.multiSlotIndex = info.getMultiSlotInd(); - this.polyglotEngine = info.getVM(); + this.truffleContext = info.getTruffleContext(); this.executor = info.executor; } @@ -752,8 +756,12 @@ public final class RContext implements RTruffleObject { return stateRFFI; } + public TruffleContext getTruffleContext() { + return truffleContext; + } + public PolyglotEngine getVM() { - return polyglotEngine; + return vm; } public boolean isInitial() { diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java index 5f055784b2..a4c446d704 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/env/frame/FrameSlotChangeMonitor.java @@ -49,7 +49,7 @@ import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RArguments; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.StableValue; -import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.ChildContextInfo; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.data.RPromise; @@ -463,11 +463,11 @@ public final class FrameSlotChangeMonitor { private final Object[] data; public MultiSlotData(MultiSlotData prevValue) { - data = Arrays.copyOf(prevValue.data, ContextInfo.contextNum()); + data = Arrays.copyOf(prevValue.data, ChildContextInfo.contextNum()); } public MultiSlotData() { - data = new Object[ContextInfo.contextNum()]; + data = new Object[ChildContextInfo.contextNum()]; } public Object get(int ind) { diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java index 7244ad0a29..3e8c47797a 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/TestBase.java @@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.FastROptions; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.ResourceHandlerFactory; import com.oracle.truffle.r.runtime.Utils; -import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.ChildContextInfo; import com.oracle.truffle.r.runtime.context.RContext; import com.oracle.truffle.r.runtime.context.RContext.ContextKind; import com.oracle.truffle.r.test.generate.FastRSession; @@ -630,7 +630,7 @@ public class TestBase { private boolean evalAndCompare(String[] inputs, TestTrait... traitsList) { WhiteList[] whiteLists = TestTrait.collect(traitsList, WhiteList.class); TestTraitsSet traits = new TestTraitsSet(traitsList); - ContextInfo contextInfo = traits.context.contains(Context.NonShared) ? fastROutputManager.fastRSession.createContextInfo(ContextKind.SHARE_NOTHING) : null; + ChildContextInfo contextInfo = traits.context.contains(Context.NonShared) ? fastROutputManager.fastRSession.createContextInfo(ContextKind.SHARE_NOTHING) : null; int index = 1; boolean allOk = true; boolean skipFastREval = traits.isIgnored || generatingExpected(); @@ -972,7 +972,7 @@ public class TestBase { * Evaluate {@code input} in FastR, returning all (virtual) console output that was produced. If * {@code nonShared} then this must evaluate in a new, non-shared, {@link RContext}. */ - protected String fastREval(String input, ContextInfo contextInfo, boolean longTimeout) { + protected String fastREval(String input, ChildContextInfo contextInfo, boolean longTimeout) { microTestInfo.expression = input; String result; try { diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java index 2b3cf0a5fb..4770f9db91 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/FastRSession.java @@ -47,7 +47,7 @@ import com.oracle.truffle.r.runtime.JumpToTopLevelException; import com.oracle.truffle.r.runtime.RError; import com.oracle.truffle.r.runtime.RInternalError; import com.oracle.truffle.r.runtime.RSource; -import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.ChildContextInfo; 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; @@ -98,9 +98,9 @@ public final class FastRSession implements RSession { public static final Source GET_CONTEXT = RSource.fromTextInternal("invisible(.fastr.context.get())", RSource.Internal.GET_CONTEXT); - public ContextInfo checkContext(ContextInfo contextInfoArg) { + public ChildContextInfo checkContext(ChildContextInfo contextInfoArg) { create(); - ContextInfo contextInfo; + ChildContextInfo contextInfo; if (contextInfoArg == null) { contextInfo = createContextInfo(ContextKind.SHARE_PARENT_RW); } else { @@ -109,9 +109,9 @@ public final class FastRSession implements RSession { return contextInfo; } - public ContextInfo createContextInfo(ContextKind contextKind) { + public ChildContextInfo createContextInfo(ContextKind contextKind) { RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false); - return ContextInfo.create(params, null, contextKind, mainContext, input, output, output, TimeZone.getTimeZone("GMT")); + return ChildContextInfo.create(params, null, contextKind, mainContext, input, output, output, TimeZone.getTimeZone("GMT")); } private FastRSession() { @@ -128,7 +128,7 @@ public final class FastRSession implements RSession { } try { RStartParams params = new RStartParams(RCmdOptions.parseArguments(Client.R, new String[]{"R", "--vanilla", "--slave", "--silent", "--no-restore"}, false), false); - ContextInfo info = ContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, input, output, output); + ChildContextInfo info = ChildContextInfo.create(params, null, ContextKind.SHARE_NOTHING, null, input, output, output); main = info.createVM(); mainContext = main.eval(GET_CONTEXT).as(RContext.class); } finally { @@ -181,12 +181,12 @@ public final class FastRSession implements RSession { } @Override - public String eval(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable { + public String eval(TestBase testClass, String expression, ChildContextInfo contextInfo, boolean longTimeout) throws Throwable { Timer timer = null; output.reset(); input.setContents(expression); try { - ContextInfo actualContextInfo = checkContext(contextInfo); + ChildContextInfo actualContextInfo = checkContext(contextInfo); // set up some interop objects used by fastr-specific tests: PolyglotEngine.Builder builder = PolyglotEngine.newBuilder(); if (testClass != null) { diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java index d80b8dd069..8c6ba569e2 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/GnuROneShotRSession.java @@ -32,7 +32,7 @@ import java.util.concurrent.TimeUnit; import com.oracle.truffle.r.launcher.RVersionNumber; import com.oracle.truffle.r.runtime.ProcessOutputManager; import com.oracle.truffle.r.runtime.REnvVars; -import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.ChildContextInfo; import com.oracle.truffle.r.test.TestBase; /** @@ -93,7 +93,7 @@ public class GnuROneShotRSession implements RSession { } @Override - public String eval(TestBase testBase, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable { + public String eval(TestBase testBase, String expression, ChildContextInfo contextInfo, boolean longTimeout) throws Throwable { if (expression.contains("library(") && !TestBase.generatingExpected()) { System.out.println("=============================================="); System.out.println("LIBRARY LOADING WHEN NOT GENERATING EXPECTED OUTPUT"); diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java index 40e96af850..6783accf75 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/generate/RSession.java @@ -22,7 +22,7 @@ */ package com.oracle.truffle.r.test.generate; -import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.ChildContextInfo; import com.oracle.truffle.r.test.TestBase; /** @@ -42,7 +42,7 @@ public interface RSession { * This result will always be non-null or an exception will be thrown in, say, a timeout * occurring. */ - String eval(TestBase testClass, String expression, ContextInfo contextInfo, boolean longTimeout) throws Throwable; + String eval(TestBase testClass, String expression, ChildContextInfo contextInfo, boolean longTimeout) throws Throwable; /** * A name to identify the session. diff --git a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java index 4a25a0082b..a419f8ff22 100644 --- a/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java +++ b/com.oracle.truffle.r.test/src/com/oracle/truffle/r/test/tck/FastRDebugTest.java @@ -54,7 +54,7 @@ import com.oracle.truffle.api.vm.PolyglotEngine; import com.oracle.truffle.api.vm.PolyglotEngine.Value; import com.oracle.truffle.r.launcher.RCmdOptions.Client; import com.oracle.truffle.r.runtime.RSource; -import com.oracle.truffle.r.runtime.context.ContextInfo; +import com.oracle.truffle.r.runtime.context.ChildContextInfo; import com.oracle.truffle.r.runtime.context.RContext.ContextKind; import com.oracle.truffle.r.runtime.data.RPromise.EagerPromise; import com.oracle.truffle.r.runtime.env.REnvironment; @@ -74,7 +74,7 @@ public class FastRDebugTest { public void before() { suspendedEvent = null; - ContextInfo info = ContextInfo.createNoRestore(Client.R, null, ContextKind.SHARE_NOTHING, null, System.in, out, err); + ChildContextInfo info = ChildContextInfo.createNoRestore(Client.R, null, ContextKind.SHARE_NOTHING, null, System.in, out, err); engine = info.createVM(PolyglotEngine.newBuilder().setOut(out).setErr(err)); debugger = Debugger.find(engine); debuggerSession = debugger.startSession(event -> { diff --git a/mx.fastr/suite.py b/mx.fastr/suite.py index adb4b56741..ce442915dc 100644 --- a/mx.fastr/suite.py +++ b/mx.fastr/suite.py @@ -29,7 +29,7 @@ suite = { { "name" : "truffle", "subdir" : True, - "version" : "b7848be486a979673f6f695b9b0ca78b2e0d9164", + "version" : "554cf703833b2665da613da0fac4972abd293fbd", "urls" : [ {"url" : "https://github.com/graalvm/graal", "kind" : "git"}, {"url" : "https://curio.ssw.jku.at/nexus/content/repositories/snapshots", "kind" : "binary"}, -- GitLab