diff --git a/com.oracle.truffle.r.native/library/fastr/src/R/fastr.R b/com.oracle.truffle.r.native/library/fastr/src/R/fastr.R index e144580e27a84b4730638cc6f8cc3cece2e3e508..43f9187cebfade9b0f492e8cd0cc431297e65570 100644 --- a/com.oracle.truffle.r.native/library/fastr/src/R/fastr.R +++ b/com.oracle.truffle.r.native/library/fastr/src/R/fastr.R @@ -71,7 +71,7 @@ fastr.createpkgsource <- function(pkg, name) { fastr.comparefilesizes <- function(file1, file2) .FastR(.NAME="comparefilesizes", file1, file2) -fastr_context.create <- function(args, shared=FALSE) { +fastr_context.create <- function(args="", shared=FALSE) { context <- .FastR(.NAME="context.create", args, shared) class(context) <- "fastr_context" 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 78b65a786ad06b3b707e50554164e0bb8f54687f..ca6b7287811b2219c6a440a4e4aef3d84ab9d749 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 @@ -53,13 +53,31 @@ public class FastRContext { } } - static Object eval(int contextId, String expr) { - RContext context = checkContext(contextId); - try { - context.activate(); - return context.getThisEngine().parseAndEval(Source.fromText(expr, "<eval_input>"), true, false); - } finally { - context.destroy(); + static void eval(RIntVector contexts, RStringVector exprs) { + if (contexts.getLength() == 1) { + RContext context = checkContext(contexts.getDataAt(0)); + try { + context.activate(); + context.getThisEngine().parseAndEval(Source.fromText(exprs.getDataAt(0), "<eval_input>"), true, false); + } finally { + context.destroy(); + } + } else { + RContext.EvalThread[] threads = new RContext.EvalThread[contexts.getLength()]; + for (int i = 0; i < threads.length; i++) { + RContext context = checkContext(contexts.getDataAt(i)); + threads[i] = new RContext.EvalThread(context, Source.fromText(exprs.getDataAt(i % threads.length), "context_eval")); + } + for (int i = 0; i < threads.length; i++) { + threads[i].start(); + } + try { + for (int i = 0; i < threads.length; i++) { + threads[i].join(); + } + } catch (InterruptedException ex) { + + } } } diff --git a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionEntry.java b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionEntry.java index b35897c3bf140b699dc27147786bbbe18121f069..a432deedad7a94fbc6794b12d084cae0a20625b2 100644 --- a/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionEntry.java +++ b/com.oracle.truffle.r.nodes.builtin/src/com/oracle/truffle/r/nodes/builtin/fastr/FastRFunctionEntry.java @@ -73,7 +73,8 @@ public class FastRFunctionEntry { return RNull.instance; case "context.eval": - return FastRContext.eval(((RIntVector) RRuntime.asAbstractVector(arg0)).getDataAt(0), ((RStringVector) RRuntime.asAbstractVector(argValues[1])).getDataAt(0)); + FastRContext.eval((RIntVector) RRuntime.asAbstractVector(arg0), (RStringVector) RRuntime.asAbstractVector(argValues[1])); + return RNull.instance; default: // The remainder all take a func argument diff --git a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RContext.java b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RContext.java index c5d974fe2cda2cda32fd96f152249fae6fcfc275..ed983a04a514a92e8599749c40d15c75298d99fd 100644 --- a/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RContext.java +++ b/com.oracle.truffle.r.runtime/src/com/oracle/truffle/r/runtime/RContext.java @@ -360,6 +360,49 @@ public final class RContext extends ExecutionContext { } + /** + * A thread that is explicitly associated with a context for efficient lookup. + */ + public static class ContextThread extends Thread { + protected RContext context; + + public ContextThread(RContext context) { + this.context = context; + } + + protected ContextThread() { + + } + + public void setContext(RContext context) { + this.context = context; + } + + } + + /** + * A thread for performing an evaluation (used by {@code fastr} package. + */ + public static class EvalThread extends ContextThread { + private final Source source; + + public EvalThread(RContext context, Source source) { + super(context); + this.source = source; + } + + @Override + public void run() { + try { + context.activate(); + context.engine.parseAndEval(source, true, false); + } finally { + context.destroy(); + } + } + + } + /** * Builtin cache. Valid across all contexts. */ @@ -446,7 +489,12 @@ public final class RContext extends ExecutionContext { * Associates this {@link RContext} with the current thread. */ public void attachThread() { - threadLocalContext.set(this); + Thread current = Thread.currentThread(); + if (current instanceof ContextThread) { + ((ContextThread) current).setContext(this); + } else { + threadLocalContext.set(this); + } } private static final Assumption singleContextAssumption = Truffle.getRuntime().createAssumption("single RContext"); @@ -614,7 +662,16 @@ public final class RContext extends ExecutionContext { // fallback to slow case } } - return getInstanceInternal(); + + Thread current = Thread.currentThread(); + if (current instanceof ContextThread) { + context = ((ContextThread) current).context; + assert context != null; + return context; + } else { + return getInstanceInternal(); + } + } /** 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 d69fd5a192e5ca9a9bd36e1a0c6f4281f3f95f66..7d821aac4e836a6745b33745be9e75e1f3ee301c 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 @@ -147,7 +147,7 @@ public final class FastRSession implements RSession { return consoleHandler.buffer.toString(); } - private final class EvalThread extends Thread { + private final class EvalThread extends RContext.ContextThread { private volatile String expression; private volatile Throwable killedByException; @@ -172,11 +172,11 @@ public final class FastRSession implements RSession { break; } try { - RContext context = createTestContext(); + RContext testContext = createTestContext(); try { - context.getThisEngine().parseAndEval(Source.fromText(expression, "<test_input>"), true, false); + testContext.getThisEngine().parseAndEval(Source.fromText(expression, "<test_input>"), true, false); } finally { - context.destroy(); + testContext.destroy(); } } catch (RError e) { // nothing to do