Mercurial > hg > truffle
changeset 22052:446ec33cadbe
Merge
author | Mick Jordan <mick.jordan@oracle.com> |
---|---|
date | Fri, 31 Jul 2015 14:49:02 -0700 |
parents | b26deb163f16 (current diff) 7a5b874b8d12 (diff) |
children | 867960de3e9a |
files | truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java |
diffstat | 23 files changed, 320 insertions(+), 196 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgtags Fri Jul 31 14:42:26 2015 -0700 +++ b/.hgtags Fri Jul 31 14:49:02 2015 -0700 @@ -617,3 +617,4 @@ 754f2b20d8bc43053d254826e6b9f09db3f3c992 graal-0.7 7aab14a2bb4e5c06b2fb252753a4beca184eec5f graal-0.8 +7aab14a2bb4e5c06b2fb252753a4beca184eec5f truffle-0.8
--- a/mx.truffle/mx_truffle.py Fri Jul 31 14:42:26 2015 -0700 +++ b/mx.truffle/mx_truffle.py Fri Jul 31 14:49:02 2015 -0700 @@ -39,21 +39,6 @@ opts2 = mx.build(['--source', '1.7'] + args) assert len(opts2.remainder) == 0 -def maven_install_truffle(args): - """install Truffle into your local Maven repository""" - for name in mx._dists: - dist = mx._dists[name] - if dist.isProcessorDistribution: - continue - mx.archive(["@" + name]) - path = dist.path - slash = path.rfind('/') - dot = path.rfind('.') - if dot <= slash: - mx.abort('Dot should be after / in ' + path) - artifactId = path[slash + 1: dot] - mx.run(['mvn', 'install:install-file', '-DgroupId=com.oracle.' + dist.suite.name, '-DartifactId=' + artifactId, '-Dversion=' + mx.suite('truffle').release_version('SNAPSHOT'), '-Dpackaging=jar', '-Dfile=' + path]) - def sl(args): """run an SL program""" vmArgs, slArgs = mx.extract_VM_args(args) @@ -71,7 +56,6 @@ mx_gate.add_gate_runner(_suite, _truffle_gate_runner) mx.update_commands(_suite, { - 'maven-install-truffle' : [maven_install_truffle, ''], 'sl' : [sl, '[SL args|@VM options]'], 'sldebug' : [sldebug, '[SL args|@VM options]'], })
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestingLanguage.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/TestingLanguage.java Fri Jul 31 14:49:02 2015 -0700 @@ -22,9 +22,11 @@ */ package com.oracle.truffle.api.dsl.test; +import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.DebugSupportProvider; import com.oracle.truffle.api.instrument.ToolSupportProvider; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.Source; import java.io.IOException; @@ -36,7 +38,7 @@ } @Override - protected Object eval(Source code) throws IOException { + protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException { throw new IOException(); }
--- a/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/processor/LanguageRegistrationTest.java Fri Jul 31 14:49:02 2015 -0700 @@ -28,6 +28,7 @@ import com.oracle.truffle.api.debug.*; import com.oracle.truffle.api.dsl.test.*; import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.*; public class LanguageRegistrationTest { @@ -55,8 +56,8 @@ } @Override - protected Object eval(Source code) throws IOException { - return null; + protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException { + throw new IOException(); } @Override @@ -94,8 +95,8 @@ } @Override - protected Object eval(Source code) throws IOException { - return null; + protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException { + throw new IOException(); } @Override @@ -132,11 +133,6 @@ } @Override - protected Object eval(Source code) throws IOException { - return null; - } - - @Override protected Object findExportedSymbol(String globalName, boolean onlyExplicit) { return null; } @@ -161,5 +157,10 @@ return null; } + @Override + protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException { + throw new IOException(); + } + } }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TestingLanguage.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/TestingLanguage.java Fri Jul 31 14:49:02 2015 -0700 @@ -22,9 +22,11 @@ */ package com.oracle.truffle.api.test; +import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.DebugSupportProvider; import com.oracle.truffle.api.instrument.ToolSupportProvider; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.Source; import java.io.IOException; @@ -36,7 +38,7 @@ } @Override - protected Object eval(Source code) throws IOException { + protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException { throw new IOException(); }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTextTest.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/source/SourceTextTest.java Fri Jul 31 14:49:02 2015 -0700 @@ -45,13 +45,13 @@ // Temp disable of empty text tests -// @Test(expected = IllegalArgumentException.class) + // @Test(expected = IllegalArgumentException.class) @Test() public void emptyTextTest1() { emptySource.getLineNumber(0); } -// @Test(expected = IllegalArgumentException.class) + // @Test(expected = IllegalArgumentException.class) @Test() public void emptyTextTest2() { emptySource.getColumnNumber(0); @@ -62,18 +62,18 @@ emptySource.getLineNumber(-1); } -// @Test(expected = IllegalArgumentException.class) + // @Test(expected = IllegalArgumentException.class) @Test() public void emptyTextTest4() { emptySource.getLineStartOffset(0); } -// @Test(expected = IllegalArgumentException.class) + // @Test(expected = IllegalArgumentException.class) public void emptyTextTest5() { emptySource.getLineStartOffset(1); } -// @Test(expected = IllegalArgumentException.class) + // @Test(expected = IllegalArgumentException.class) public void emptyTextTest6() { emptySource.getLineLength(1); }
--- a/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/vm/ImplicitExplicitExportTest.java Fri Jul 31 14:49:02 2015 -0700 @@ -32,6 +32,8 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.debug.*; import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.vm.*; @@ -115,28 +117,8 @@ private final Map<String, String> implicit = new HashMap<>(); @Override - protected Object eval(Source code) throws IOException { - Properties p = new Properties(); - try (Reader r = code.getReader()) { - p.load(r); - } - Enumeration<Object> en = p.keys(); - while (en.hasMoreElements()) { - Object n = en.nextElement(); - if (n instanceof String) { - String k = (String) n; - if (k.startsWith("explicit.")) { - explicit.put(k.substring(9), p.getProperty(k)); - } - if (k.startsWith("implicit.")) { - implicit.put(k.substring(9), p.getProperty(k)); - } - if (k.equals("return")) { - return env().importSymbol(p.getProperty(k)); - } - } - } - return null; + protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException { + return new ValueCallTarget(code, getClass()); } @Override @@ -150,6 +132,10 @@ return null; } + public static <Language extends TruffleLanguage> Language findContext(Class<Language> type) { + return TruffleLanguage.findContext(type); + } + @Override protected Object getLanguageGlobal() { return null; @@ -169,6 +155,53 @@ protected DebugSupportProvider getDebugSupport() { return null; } + + private Object importExport(Source code) { + Properties p = new Properties(); + try (Reader r = code.getReader()) { + p.load(r); + } catch (IOException ex) { + throw new IllegalStateException(ex); + } + Enumeration<Object> en = p.keys(); + while (en.hasMoreElements()) { + Object n = en.nextElement(); + if (n instanceof String) { + String k = (String) n; + if (k.startsWith("explicit.")) { + explicit.put(k.substring(9), p.getProperty(k)); + } + if (k.startsWith("implicit.")) { + implicit.put(k.substring(9), p.getProperty(k)); + } + if (k.equals("return")) { + return env().importSymbol(p.getProperty(k)); + } + } + } + return null; + } + } + + private static final class ValueCallTarget implements RootCallTarget { + private final Source code; + private final Class<? extends AbstractExportImportLanguage> language; + + private ValueCallTarget(Source code, Class<? extends AbstractExportImportLanguage> language) { + this.code = code; + this.language = language; + } + + @Override + public RootNode getRootNode() { + throw new UnsupportedOperationException(); + } + + @Override + public Object call(Object... arguments) { + AbstractExportImportLanguage context = AbstractExportImportLanguage.findContext(language); + return context.importExport(code); + } } static final String L1 = "application/x-test-import-export-1";
--- a/truffle/com.oracle.truffle.api/.checkstyle_checks.xml Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api/.checkstyle_checks.xml Fri Jul 31 14:49:02 2015 -0700 @@ -209,7 +209,7 @@ <module name="SuppressionCommentFilter"> <property name="offCommentFormat" value="CheckStyle: start generated"/> <property name="onCommentFormat" value="CheckStyle: stop generated"/> - <property name="checkFormat" value=".*Name|.*LineLength"/> + <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/> </module> <module name="RegexpSingleline"> <property name="format" value="System\.(out|err)\.print"/>
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/TruffleLanguage.java Fri Jul 31 14:49:02 2015 -0700 @@ -31,9 +31,13 @@ import com.oracle.truffle.api.debug.*; import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.instrument.*; +import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.*; import com.oracle.truffle.api.vm.*; import com.oracle.truffle.api.vm.TruffleVM.Language; +import java.util.Collections; +import java.util.Map; +import java.util.WeakHashMap; /** * An entry point for everyone who wants to implement a Truffle based language. By providing @@ -98,7 +102,24 @@ return this.env; } - protected abstract Object eval(Source code) throws IOException; + /** + * Parses the provided source and generates appropriate AST. The parsing should execute no user + * code, it should only create the {@link Node} tree to represent the source. The parsing may be + * performed in a context (specified as another {@link Node}) or without context. The + * {@code argumentNames} may contain symbolic names for actual parameters of the call to the + * returned value. The result should be a call target with method + * {@link CallTarget#call(java.lang.Object...)} that accepts as many arguments as were provided + * via the {@code argumentNames} array. + * + * @param code source code to parse + * @param context a {@link Node} defining context for the parsing + * @param argumentNames symbolic names for parameters of + * {@link CallTarget#call(java.lang.Object...)} + * @return a call target to invoke which also keeps in memory the {@link Node} tree representing + * just parsed <code>code</code> + * @throws IOException thrown when I/O or parsing goes wrong + */ + protected abstract CallTarget parse(Source code, Node context, String... argumentNames) throws IOException; /** * Called when some other language is seeking for a global symbol. This method is supposed to do @@ -150,6 +171,18 @@ protected abstract DebugSupportProvider getDebugSupport(); /** + * Finds the currently executing context for current thread. + * + * @param <Lang> type of language making the query + * @param language the language class + * @return the context associated with current execution + * @throws IllegalStateException if no context is associated with the execution + */ + protected static <Lang extends TruffleLanguage> Lang findContext(Class<Lang> language) { + return language.cast(API.findLanguage(null, language)); + } + + /** * Represents execution environment of the {@link TruffleLanguage}. Each active * {@link TruffleLanguage} receives instance of the environment before any code is executed upon * it. The environment has knowledge of all active languages and can exchange symbols between @@ -229,9 +262,23 @@ return super.importSymbol(vm, queryingLang, globalName); } + private static final Map<Source, CallTarget> COMPILED = Collections.synchronizedMap(new WeakHashMap<Source, CallTarget>()); + @Override - protected Object eval(TruffleLanguage l, Source s) throws IOException { - return l.eval(s); + protected Object eval(TruffleLanguage language, Source source) throws IOException { + CallTarget target = COMPILED.get(source); + if (target == null) { + target = language.parse(source, null); + if (target == null) { + throw new IOException("Parsing has not produced a CallTarget for " + source); + } + COMPILED.put(source, target); + } + try { + return target.call(); + } catch (Exception ex) { + throw new IOException(ex); + } } @Override @@ -240,6 +287,11 @@ } @Override + protected TruffleLanguage findLanguage(TruffleVM vm, Class<? extends TruffleLanguage> languageClass) { + return super.findLanguage(vm, languageClass); + } + + @Override protected Object languageGlobal(TruffleLanguage l) { return l.getLanguageGlobal(); }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/package-info.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/debug/package-info.java Fri Jul 31 14:49:02 2015 -0700 @@ -30,12 +30,14 @@ * needs to turn debugging on when constructing its Truffle virtual machine: * <pre> * vm = {@link com.oracle.truffle.api.vm.TruffleVM#newVM()}. - * {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(<b>new</b> {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}{@code <}{@link com.oracle.truffle.api.debug.ExecutionEvent}{@code >}() { + * {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(<b>new</b> {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer} + * {@code <}{@link com.oracle.truffle.api.debug.ExecutionEvent}{@code >}() { * <b>public void</b> handle({@link com.oracle.truffle.api.debug.ExecutionEvent} ev) { * <em>// configure the virtual machine as {@link com.oracle.truffle.api.vm.TruffleVM#eval(java.net.URI) new execution} is starting</em> * } * }). - * {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(<b>new</b> {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}{@code <}{@link com.oracle.truffle.api.debug.SuspendedEvent}{@code >}() { + * {@link com.oracle.truffle.api.vm.TruffleVM.Builder#onEvent(com.oracle.truffle.api.vm.EventConsumer) onEvent}(<b>new</b> {@link com.oracle.truffle.api.vm.EventConsumer EventConsumer}{@code <} + * {@link com.oracle.truffle.api.debug.SuspendedEvent}{@code >}() { * <b>public void</b> handle({@link com.oracle.truffle.api.debug.SuspendedEvent} ev) { * <em>// execution is suspended on a breakpoint or on a step - decide what next</em> * } @@ -43,30 +45,31 @@ * </pre> * The debugging is controlled by events emitted by the Truffle virtual machine * at important moments. The {@link com.oracle.truffle.api.debug.ExecutionEvent} - * is sent when a call to {@link com.oracle.truffle.api.vm.TruffleVM#eval(java.net.URI) eval(...)} + * is sent when a call to {@link com.oracle.truffle.api.vm.TruffleVM#eval(java.net.URI) eval(...)} * is made and allows one to configure {@link com.oracle.truffle.api.debug.Breakpoint breakpoints} and/or decide whether the - * program should {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareStepInto() step-into} or + * program should {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareStepInto() step-into} or * {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareContinue() just run}. Once the execution is suspended a * {@link com.oracle.truffle.api.debug.SuspendedEvent} is generated which * allows one to inspect the stack and choose the further execution mode - * ({@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepInto(int) step-into}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepOver(int) step-over}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepOut() step-out}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareContinue() continue}). + * ({@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepInto(int) step-into}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepOver(int) step-over}, + * {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareStepOut() step-out}, {@link com.oracle.truffle.api.debug.SuspendedEvent#prepareContinue() continue}). * <p> * The events methods are only available when the event is being delivered and * shouldn't be used anytime later. Both events however provide access to * {@link com.oracle.truffle.api.debug.Debugger} which can be kept and used * during whole existence of the {@link com.oracle.truffle.api.vm.TruffleVM}. - * {@link com.oracle.truffle.api.debug.Debugger} is the central class that + * {@link com.oracle.truffle.api.debug.Debugger} is the central class that * keeps information about {@link com.oracle.truffle.api.debug.Debugger#getBreakpoints() registered breakpoints} * and allows one create new {@link com.oracle.truffle.api.debug.Breakpoint ones}. - * + * * <h4>Turning on Stepping Mode</h4> - * + * * In case you want your execution to pause on first statement, register for * {@link com.oracle.truffle.api.debug.ExecutionEvent} and once delivered * call {@link com.oracle.truffle.api.debug.ExecutionEvent#prepareStepInto()}. * * <h4>Register a {@link com.oracle.truffle.api.debug.Breakpoint}</h4> - * + * * Wait for execution to be started - which generates an * {@link com.oracle.truffle.api.debug.ExecutionEvent}. Use its * {@link com.oracle.truffle.api.debug.Debugger ev.getDebugger}()
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Fri Jul 31 14:49:02 2015 -0700 @@ -45,15 +45,11 @@ private static Accessor NODES; private static Accessor INSTRUMENT; private static Accessor DEBUG; + private static final ThreadLocal<TruffleVM> CURRENT_VM = new ThreadLocal<>(); static { TruffleLanguage lng = new TruffleLanguage(null) { @Override - protected Object eval(Source code) throws IOException { - return null; - } - - @Override protected Object findExportedSymbol(String globalName, boolean onlyExplicit) { return null; } @@ -77,6 +73,11 @@ protected DebugSupportProvider getDebugSupport() { return null; } + + @Override + protected CallTarget parse(Source code, Node context, String... argumentNames) throws IOException { + throw new IOException(); + } }; lng.hashCode(); new Node(null) { @@ -161,12 +162,31 @@ return INSTRUMENT.findLanguage(probe); } - protected TruffleLanguage findLanguage(TruffleVM vm, Class<? extends TruffleLanguage> languageClass) { + protected TruffleLanguage findLanguage(TruffleVM known, Class<? extends TruffleLanguage> languageClass) { + TruffleVM vm; + if (known == null) { + vm = CURRENT_VM.get(); + if (vm == null) { + throw new IllegalStateException(); + } + } else { + vm = known; + } return SPI.findLanguage(vm, languageClass); } protected Closeable executionStart(TruffleVM vm, Debugger[] fillIn, Source s) { - return DEBUG.executionStart(vm, fillIn, s); + final Closeable debugClose = DEBUG.executionStart(vm, fillIn, s); + final TruffleVM prev = CURRENT_VM.get(); + CURRENT_VM.set(vm); + class ContextCloseable implements Closeable { + @Override + public void close() throws IOException { + CURRENT_VM.set(prev); + debugClose.close(); + } + } + return new ContextCloseable(); } protected void dispatchEvent(TruffleVM vm, Object event) {
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/DefaultTruffleRuntime.java Fri Jul 31 14:49:02 2015 -0700 @@ -164,5 +164,4 @@ } return new DefaultLoopNode(repeating); } - }
--- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/source/Source.java Fri Jul 31 14:49:02 2015 -0700 @@ -814,7 +814,7 @@ @Override public int hashCode() { - return description.hashCode(); + return description.hashCode() * code.hashCode(); } @Override @@ -827,7 +827,7 @@ } if (obj instanceof LiteralSource) { LiteralSource other = (LiteralSource) obj; - return description.equals(other.description); + return description.equals(other.description) && code.equals(other.code); } return false; }
--- a/truffle/com.oracle.truffle.dsl.processor/.checkstyle_checks.xml Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.dsl.processor/.checkstyle_checks.xml Fri Jul 31 14:49:02 2015 -0700 @@ -207,6 +207,6 @@ <module name="SuppressionCommentFilter"> <property name="offCommentFormat" value="CheckStyle: start generated"/> <property name="onCommentFormat" value="CheckStyle: stop generated"/> - <property name="checkFormat" value=".*Name|.*LineLength"/> + <property name="checkFormat" value=".*Name|.*LineLength|.*Header"/> </module> </module>
--- a/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/SLTckTest.java Fri Jul 31 14:49:02 2015 -0700 @@ -70,6 +70,14 @@ "function apply(f) {\n" + " return f(18, 32) + 10;\n" + "}\n" + + "function cnt() {\n" + + " return 0;\n" + + "}\n" + + "function count() {\n" + + " n = cnt() + 1;\n" + + " defineFunction(\"function cnt() { return \" + n + \"; }\");\n" + + " return n;\n" + + "}\n" + "function null() {\n" + "}\n" ); @@ -111,4 +119,9 @@ "}\n"; // @formatter:on } + + @Override + protected String countInvocations() { + return "count"; + } }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/SLLanguage.java Fri Jul 31 14:49:02 2015 -0700 @@ -56,7 +56,6 @@ import com.oracle.truffle.api.vm.*; import com.oracle.truffle.api.vm.TruffleVM.Symbol; import com.oracle.truffle.sl.builtins.*; -import com.oracle.truffle.sl.factory.*; import com.oracle.truffle.sl.nodes.*; import com.oracle.truffle.sl.nodes.call.*; import com.oracle.truffle.sl.nodes.controlflow.*; @@ -155,7 +154,6 @@ */ @TruffleLanguage.Registration(name = "SL", version = "0.5", mimeType = "application/x-sl") public class SLLanguage extends TruffleLanguage { - private static SLLanguage LAST; private static List<NodeFactory<? extends SLBuiltinNode>> builtins = Collections.emptyList(); private static Visualizer visualizer = new SLDefaultVisualizer(); private static ASTProber registeredASTProber; // non-null if prober already registered @@ -164,10 +162,9 @@ public SLLanguage(Env env) { super(env); - context = SLContextFactory.create(this, new BufferedReader(env().stdIn()), new PrintWriter(env().stdOut(), true)); - LAST = this; + context = new SLContext(this, new BufferedReader(env().stdIn()), new PrintWriter(env().stdOut(), true)); for (NodeFactory<? extends SLBuiltinNode> builtin : builtins) { - context.installBuiltin(builtin); + context.installBuiltin(builtin, true); } } @@ -258,7 +255,7 @@ /* Change to dump the AST to IGV over the network. */ boolean dumpASTToIGV = false; - printScript("before execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); + printScript("before execution", null, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); long totalRuntime = 0; try { for (int i = 0; i < repeats; i++) { @@ -283,7 +280,7 @@ } } finally { - printScript("after execution", LAST.context, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); + printScript("after execution", null, logOutput, printASTToLog, printSourceAttributionToLog, dumpASTToIGV); } return totalRuntime; } @@ -381,14 +378,43 @@ return result.toString(); } + public static SLLanguage find() { + return SLLanguage.findContext(SLLanguage.class); + } + @Override - protected Object eval(Source code) throws IOException { + protected CallTarget parse(Source code, Node node, String... argumentNames) throws IOException { + final SLContext c = new SLContext(this); + final Exception[] failed = {null}; try { - context.evalSource(code); + c.evalSource(code); + failed[0] = null; } catch (Exception e) { - throw new IOException(e); + failed[0] = e; } - return null; + return new CallTarget() { + @Override + public Object call(Object... arguments) { + if (failed[0] instanceof RuntimeException) { + throw (RuntimeException) failed[0]; + } + if (failed[0] != null) { + throw new IllegalStateException(failed[0]); + } + SLLanguage current = SLLanguage.find(); + SLContext fillIn = current.context; + final SLFunctionRegistry functionRegistry = fillIn.getFunctionRegistry(); + for (SLFunction f : c.getFunctionRegistry().getFunctions()) { + RootCallTarget callTarget = f.getCallTarget(); + if (callTarget == null) { + continue; + } + functionRegistry.lookup(f.getName()); + functionRegistry.register(f.getName(), (SLRootNode) f.getCallTarget().getRootNode()); + } + return null; + } + }; } @Override @@ -465,6 +491,10 @@ } } + public SLContext getContext() { + return context; + } + private final class SLDebugProvider implements DebugSupportProvider { public SLDebugProvider() {
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/factory/SLContextFactory.java Fri Jul 31 14:42:26 2015 -0700 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * The Universal Permissive License (UPL), Version 1.0 - * - * Subject to the condition set forth below, permission is hereby granted to any - * person obtaining a copy of this software, associated documentation and/or - * data (collectively the "Software"), free of charge and under any and all - * copyright rights in the Software, and any and all patent rights owned or - * freely licensable by each licensor hereunder covering either (i) the - * unmodified Software as contributed to or provided by such licensor, or (ii) - * the Larger Works (as defined below), to deal in both - * - * (a) the Software, and - * - * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - * one is included with the Software each a "Larger Work" to which the Software - * is contributed by such licensors), - * - * without restriction, including without limitation the rights to copy, create - * derivative works of, display, perform, and distribute the Software and make, - * use, sell, offer for sale, import, export, have made, and have sold the - * Software and the Larger Work(s), and to sublicense the foregoing rights on - * either these or other terms. - * - * This license is subject to the following condition: - * - * The above copyright notice and either this complete permission notice or at a - * minimum a reference to the UPL must be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.oracle.truffle.sl.factory; - -import com.oracle.truffle.sl.SLLanguage; -import java.io.*; - -import com.oracle.truffle.sl.runtime.*; - -public final class SLContextFactory { - - private SLContextFactory() { - } - - public static SLContext create(SLLanguage sl, BufferedReader input, PrintWriter output) { - return new SLContext(sl, input, output); - } -}
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/SLRootNode.java Fri Jul 31 14:49:02 2015 -0700 @@ -41,7 +41,6 @@ package com.oracle.truffle.sl.nodes; import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; -import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.instrument.*; import com.oracle.truffle.api.nodes.*; @@ -65,16 +64,13 @@ /** The name of the function, for printing purposes only. */ private final String name; - /** The Simple execution context for this tree. **/ - private final SLContext context; - @CompilationFinal private boolean isCloningAllowed; - public SLRootNode(SLContext context, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) { + @SuppressWarnings("unused") + public SLRootNode(SLContext ignore, FrameDescriptor frameDescriptor, SLExpressionNode bodyNode, String name) { super(SLLanguage.class, null, frameDescriptor); this.bodyNode = bodyNode; this.name = name; - this.context = context; } @Override @@ -108,13 +104,4 @@ public String toString() { return "root " + name; } - - public SLContext getSLContext() { - return this.context; - } - - @Override - public ExecutionContext getExecutionContext() { - return this.context; - } }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/expression/SLFunctionLiteralNode.java Fri Jul 31 14:49:02 2015 -0700 @@ -44,6 +44,7 @@ import com.oracle.truffle.api.frame.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.source.*; +import com.oracle.truffle.sl.SLLanguage; import com.oracle.truffle.sl.nodes.*; import com.oracle.truffle.sl.runtime.*; @@ -56,15 +57,16 @@ @NodeInfo(shortName = "func") public final class SLFunctionLiteralNode extends SLExpressionNode { - private final SLFunction value; + private final String value; - public SLFunctionLiteralNode(SourceSection src, SLFunction value) { + public SLFunctionLiteralNode(SourceSection src, String value) { super(src); this.value = value; } @Override public SLFunction executeGeneric(VirtualFrame frame) { - return value; + SLLanguage language = SLLanguage.find(); + return language.getContext().getFunctionRegistry().lookup(value); } }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Fri Jul 31 14:49:02 2015 -0700 @@ -331,7 +331,7 @@ return SLReadLocalVariableNodeGen.create(src, frameSlot); } else { /* Read of a global name. In our language, the only global names are functions. */ - return new SLFunctionLiteralNode(src, context.getFunctionRegistry().lookup(nameToken.val)); + return new SLFunctionLiteralNode(src, nameToken.val); } }
--- a/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.sl/src/com/oracle/truffle/sl/runtime/SLContext.java Fri Jul 31 14:49:02 2015 -0700 @@ -74,11 +74,19 @@ private final Shape emptyShape; public SLContext(SLLanguage language, BufferedReader input, PrintWriter output) { + this(language, input, output, true); + } + + public SLContext(SLLanguage language) { + this(language, null, null, false); + } + + private SLContext(SLLanguage language, BufferedReader input, PrintWriter output, boolean installBuiltins) { this.language = language; this.input = input; this.output = output; this.functionRegistry = new SLFunctionRegistry(); - installBuiltins(); + installBuiltins(installBuiltins); this.emptyShape = LAYOUT.createShape(new ObjectType()); } @@ -114,19 +122,19 @@ * Adds all builtin functions to the {@link SLFunctionRegistry}. This method lists all * {@link SLBuiltinNode builtin implementation classes}. */ - private void installBuiltins() { - installBuiltin(SLReadlnBuiltinFactory.getInstance()); - installBuiltin(SLPrintlnBuiltinFactory.getInstance()); - installBuiltin(SLNanoTimeBuiltinFactory.getInstance()); - installBuiltin(SLDefineFunctionBuiltinFactory.getInstance()); - installBuiltin(SLStackTraceBuiltinFactory.getInstance()); - installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance()); - installBuiltin(SLAssertTrueBuiltinFactory.getInstance()); - installBuiltin(SLAssertFalseBuiltinFactory.getInstance()); - installBuiltin(SLNewObjectBuiltinFactory.getInstance()); + private void installBuiltins(boolean registerRootNodes) { + installBuiltin(SLReadlnBuiltinFactory.getInstance(), registerRootNodes); + installBuiltin(SLPrintlnBuiltinFactory.getInstance(), registerRootNodes); + installBuiltin(SLNanoTimeBuiltinFactory.getInstance(), registerRootNodes); + installBuiltin(SLDefineFunctionBuiltinFactory.getInstance(), registerRootNodes); + installBuiltin(SLStackTraceBuiltinFactory.getInstance(), registerRootNodes); + installBuiltin(SLHelloEqualsWorldBuiltinFactory.getInstance(), registerRootNodes); + installBuiltin(SLAssertTrueBuiltinFactory.getInstance(), registerRootNodes); + installBuiltin(SLAssertFalseBuiltinFactory.getInstance(), registerRootNodes); + installBuiltin(SLNewObjectBuiltinFactory.getInstance(), registerRootNodes); } - public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory) { + public void installBuiltin(NodeFactory<? extends SLBuiltinNode> factory, boolean registerRootNodes) { /* * The builtin node factory is a class that is automatically generated by the Truffle DSL. * The signature returned by the factory reflects the signature of the @Specialization @@ -149,8 +157,13 @@ /* Wrap the builtin in a RootNode. Truffle requires all AST to start with a RootNode. */ SLRootNode rootNode = new SLRootNode(this, new FrameDescriptor(), builtinBodyNode, name); - /* Register the builtin function in our function registry. */ - getFunctionRegistry().register(name, rootNode); + if (registerRootNodes) { + /* Register the builtin function in our function registry. */ + getFunctionRegistry().register(name, rootNode); + } else { + // make sure the function is known + getFunctionRegistry().lookup(name); + } } public static NodeInfo lookupNodeInfo(Class<?> clazz) {
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/MaxMinObject.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/MaxMinObject.java Fri Jul 31 14:49:02 2015 -0700 @@ -47,16 +47,10 @@ @Override public ForeignAccess getForeignAccess() { - return ForeignAccess.create(MaxMinObject.class, new AF(max)); + return ForeignAccess.create(MaxMinObject.class, new AF()); } static final class AF implements ForeignAccess.Factory10 { - private final boolean max; - - public AF(boolean max) { - this.max = max; - } - @Override public CallTarget accessIsNull() { return null; @@ -100,7 +94,7 @@ @Override public CallTarget accessExecute(int argumentsLength) { if (argumentsLength == 2) { - MaxMinNode maxNode = MaxMinObjectFactory.MaxMinNodeGen.create(max, MaxMinObjectFactory.UnboxNodeGen.create(new ReadArgNode(0)), + MaxMinNode maxNode = MaxMinObjectFactory.MaxMinNodeGen.create(new ReadReceiverNode(), MaxMinObjectFactory.UnboxNodeGen.create(new ReadArgNode(0)), MaxMinObjectFactory.UnboxNodeGen.create(new ReadArgNode(1))); return Truffle.getRuntime().createCallTarget(maxNode); } @@ -130,6 +124,12 @@ } } + static class ReadReceiverNode extends Node { + public Object execute(VirtualFrame frame) { + return ForeignAccess.getReceiver(frame); + } + } + @NodeChildren({@NodeChild(value = "valueNode", type = ReadArgNode.class)}) abstract static class UnboxNode extends Node { @Child private Node unbox; @@ -171,28 +171,26 @@ } - @NodeChildren({@NodeChild(value = "firstNode", type = UnboxNode.class), @NodeChild(value = "secondNode", type = UnboxNode.class)}) + @NodeChildren({@NodeChild(value = "receiver", type = ReadReceiverNode.class), @NodeChild(value = "firstNode", type = UnboxNode.class), @NodeChild(value = "secondNode", type = UnboxNode.class)}) abstract static class MaxMinNode extends RootNode { - private final boolean max; - MaxMinNode(boolean max) { + MaxMinNode() { super(MMLanguage.class, null, null); - this.max = max; } @Specialization - public int execute(int first, int second) { - return max ? Math.max(first, second) : Math.min(first, second); + public int execute(MaxMinObject receiver, int first, int second) { + return receiver.max ? Math.max(first, second) : Math.min(first, second); } @Specialization - public long execute(long first, long second) { - return max ? Math.max(first, second) : Math.min(first, second); + public long execute(MaxMinObject receiver, long first, long second) { + return receiver.max ? Math.max(first, second) : Math.min(first, second); } @Specialization - public double execute(double first, double second) { - return max ? Math.max(first, second) : Math.min(first, second); + public double execute(MaxMinObject receiver, double first, double second) { + return receiver.max ? Math.max(first, second) : Math.min(first, second); } }
--- a/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Fri Jul 31 14:42:26 2015 -0700 +++ b/truffle/com.oracle.truffle.tck/src/com/oracle/truffle/tck/TruffleTCK.java Fri Jul 31 14:49:02 2015 -0700 @@ -102,6 +102,19 @@ protected abstract String applyNumbers(); /** + * Name of a function that counts number of its invocations in current {@link TruffleVM} + * context. Your function should somehow keep a counter to remember number of its invocations + * and always increment it. The first invocation should return <code>1</code>, the second + * <code>2</code> and so on. The returned values are expected to be instances of {@link Number}. + * <p> + * The function will be used to test that two instances of your language can co-exist next to + * each other. Without being mutually influenced. + * + * @return name of globally expected symbol + */ + protected abstract String countInvocations(); + + /** * Return a code snippet that is invalid in your language. Its * {@link TruffleVM#eval(java.lang.String, java.lang.String) evaluation} should fail and yield * an exception. @@ -197,6 +210,33 @@ assert 28 == n.intValue() : "18 < 32 and plus 10"; } + @Test + public void testCoExistanceOfMultipleLanguageInstances() throws Exception { + final String countMethod = countInvocations(); + TruffleVM.Symbol count1 = findGlobalSymbol(countMethod); + tckVM = null; // clean-up + TruffleVM.Symbol count2 = findGlobalSymbol(countMethod); + + int prev1 = 0; + int prev2 = 0; + Random r = new Random(); + for (int i = 0; i < 10; i++) { + int quantum = r.nextInt(10); + for (int j = 0; j < quantum; j++) { + Object res = count1.invoke(null); + assert res instanceof Number : "expecting number: " + res; + assert ((Number) res).intValue() == ++prev1 : "expecting " + prev1 + " but was " + res; + } + for (int j = 0; j < quantum; j++) { + Object res = count2.invoke(null); + assert res instanceof Number : "expecting number: " + res; + assert ((Number) res).intValue() == ++prev2 : "expecting " + prev2 + " but was " + res; + } + assert prev1 == prev2 : "At round " + i + " the same number of invocations " + prev1 + " vs. " + prev2; + } + + } + private TruffleVM.Symbol findGlobalSymbol(String name) throws Exception { TruffleVM.Symbol s = vm().findGlobalSymbol(name); assert s != null : "Symbol " + name + " is not found!";