comparison graal/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java @ 21557:31fc2fce38f3

Merge.
author Doug Simon <doug.simon@oracle.com>
date Wed, 27 May 2015 13:32:18 +0200
parents b1530a6cce8c 3286fb5fea4a
children 1c76a5662753
comparison
equal deleted inserted replaced
21556:48c1ebd24120 21557:31fc2fce38f3
36 import com.oracle.truffle.api.TruffleLanguage.Registration; 36 import com.oracle.truffle.api.TruffleLanguage.Registration;
37 import com.oracle.truffle.api.impl.*; 37 import com.oracle.truffle.api.impl.*;
38 import com.oracle.truffle.api.source.*; 38 import com.oracle.truffle.api.source.*;
39 39
40 /** 40 /**
41 * Virtual machine for Truffle based languages. Use {@link #create()} to instantiate new isolated 41 * Virtual machine for Truffle based languages. Use {@link #newVM()} to create new isolated virtual
42 * virtual machine ready for execution of various languages. All the languages in a single virtual 42 * machine ready for execution of various languages. All the languages in a single virtual machine
43 * machine see each other exported global symbols and can co-operate. Use {@link #create()} multiple 43 * see each other exported global symbols and can co-operate. Use {@link #newVM()} multiple times to
44 * times to create different, isolated virtual machines completely separated from each other. 44 * create different, isolated virtual machines completely separated from each other.
45 * <p> 45 * <p>
46 * Once instantiated use {@link #eval(java.net.URI)} with a reference to a file or URL or directly 46 * Once instantiated use {@link #eval(java.net.URI)} with a reference to a file or URL or directly
47 * pass code snippet into the virtual machine via {@link #eval(java.lang.String, java.lang.String)}. 47 * pass code snippet into the virtual machine via {@link #eval(java.lang.String, java.lang.String)}.
48 * Support for individual languages is initialized on demand - e.g. once a file of certain mime type 48 * Support for individual languages is initialized on demand - e.g. once a file of certain mime type
49 * is about to be processed, its appropriate engine (if found), is initialized. Once an engine gets 49 * is about to be processed, its appropriate engine (if found), is initialized. Once an engine gets
50 * initialized, it remains so, until the virtual machine isn't garbage collected. 50 * initialized, it remains so, until the virtual machine isn't garbage collected.
51 * <p> 51 * <p>
52 * The <code>TruffleVM</code> is single-threaded and tries to enforce that. It records the thread it 52 * The <code>TruffleVM</code> is single-threaded and tries to enforce that. It records the thread it
53 * has been {@link #create() created} by and checks that all subsequent calls are coming from the 53 * has been {@link Builder#build() created} by and checks that all subsequent calls are coming from
54 * same thread. 54 * the same thread.
55 */ 55 */
56 public final class TruffleVM { 56 public final class TruffleVM {
57 private static final Logger LOG = Logger.getLogger(TruffleVM.class.getName()); 57 private static final Logger LOG = Logger.getLogger(TruffleVM.class.getName());
58 private static final SPIAccessor SPI = new SPIAccessor(); 58 private static final SPIAccessor SPI = new SPIAccessor();
59 private final Thread initThread; 59 private final Thread initThread;
60 private final Map<String, Language> langs; 60 private final Map<String, Language> langs;
61 61 private final Reader in;
62 private final Writer err;
63 private final Writer out;
64
65 /**
66 * Private & temporary only constructor.
67 */
62 private TruffleVM() { 68 private TruffleVM() {
63 initThread = Thread.currentThread(); 69 this.initThread = null;
70 this.in = null;
71 this.err = null;
72 this.out = null;
73 this.langs = null;
74 }
75
76 /**
77 * Real constructor used from the builder.
78 *
79 * @param out stdout
80 * @param err stderr
81 * @param in stdin
82 */
83 private TruffleVM(Writer out, Writer err, Reader in) {
84 this.out = out;
85 this.err = err;
86 this.in = in;
87 this.initThread = Thread.currentThread();
64 this.langs = new HashMap<>(); 88 this.langs = new HashMap<>();
65 Enumeration<URL> en; 89 Enumeration<URL> en;
66 try { 90 try {
67 en = loader().getResources("META-INF/truffle/language"); 91 en = loader().getResources("META-INF/truffle/language");
68 } catch (IOException ex) { 92 } catch (IOException ex) {
94 } 118 }
95 return l; 119 return l;
96 } 120 }
97 121
98 /** 122 /**
99 * Creates new Truffle virtual machine. It searches for {@link Registration languages 123 * Creation of new Truffle virtual machine. Use the {@link Builder} methods to configure your
100 * registered} in the system class loader and makes them available for later evaluation via 124 * virtual machine and then create one using {@link Builder#build()}:
125 *
126 * <pre>
127 * {@link TruffleVM} vm = {@link TruffleVM}.{@link TruffleVM#newVM() newVM()}
128 * .{@link Builder#stdOut(java.io.Writer) stdOut}({@link Writer yourWriter})
129 * .{@link Builder#stdErr(java.io.Writer) stdErr}({@link Writer yourWriter})
130 * .{@link Builder#stdIn(java.io.Reader) stdIn}({@link Reader yourReader})
131 * .{@link Builder#build() build()};
132 * </pre>
133 *
134 * It searches for {@link Registration languages registered} in the system class loader and
135 * makes them available for later evaluation via
101 * {@link #eval(java.lang.String, java.lang.String)} methods. 136 * {@link #eval(java.lang.String, java.lang.String)} methods.
102 * 137 *
103 * @return new, isolated virtual machine with pre-registered languages 138 * @return new, isolated virtual machine with pre-registered languages
104 */ 139 */
105 public static TruffleVM create() { 140 public static TruffleVM.Builder newVM() {
106 return new TruffleVM(); 141 // making Builder non-static inner class is a
142 // nasty trick to avoid the Builder class to appear
143 // in Javadoc next to TruffleVM class
144 TruffleVM vm = new TruffleVM();
145 return vm.new Builder();
146 }
147
148 /**
149 * Builder for a new {@link TruffleVM}. Call various configuration methods in a chain and at the
150 * end create new {@link TruffleVM virtual machine}:
151 *
152 * <pre>
153 * {@link TruffleVM} vm = {@link TruffleVM}.{@link TruffleVM#newVM() newVM()}
154 * .{@link Builder#stdOut(java.io.Writer) stdOut}({@link Writer yourWriter})
155 * .{@link Builder#stdErr(java.io.Writer) stdErr}({@link Writer yourWriter})
156 * .{@link Builder#stdIn(java.io.Reader) stdIn}({@link Reader yourReader})
157 * .{@link Builder#build() build()};
158 * </pre>
159 */
160 public final class Builder {
161 private Writer out;
162 private Writer err;
163 private Reader in;
164
165 Builder() {
166 }
167
168 /**
169 * Changes the defaut output for languages running in <em>to be created</em>
170 * {@link TruffleVM virtual machine}. The default is to use {@link System#out}.
171 *
172 * @param w the writer to use as output
173 * @return instance of this builder
174 */
175 public Builder stdOut(Writer w) {
176 out = w;
177 return this;
178 }
179
180 /**
181 * Changes the error output for languages running in <em>to be created</em>
182 * {@link TruffleVM virtual machine}. The default is to use {@link System#err}.
183 *
184 * @param w the writer to use as output
185 * @return instance of this builder
186 */
187 public Builder stdErr(Writer w) {
188 err = w;
189 return this;
190 }
191
192 /**
193 * Changes the defaut input for languages running in <em>to be created</em>
194 * {@link TruffleVM virtual machine}. The default is to use {@link System#out}.
195 *
196 * @param r the reader to use as input
197 * @return instance of this builder
198 */
199 public Builder stdIn(Reader r) {
200 in = r;
201 return this;
202 }
203
204 /**
205 * Creates the {@link TruffleVM Truffle virtual machine}. The configuration is taken from
206 * values passed into configuration methods in this class.
207 *
208 * @return new, isolated virtual machine with pre-registered languages
209 */
210 public TruffleVM build() {
211 if (out == null) {
212 out = new OutputStreamWriter(System.out);
213 }
214 if (err == null) {
215 err = new OutputStreamWriter(System.err);
216 }
217 if (in == null) {
218 in = new InputStreamReader(System.in);
219 }
220 return new TruffleVM(out, err, in);
221 }
107 } 222 }
108 223
109 /** 224 /**
110 * Descriptions of languages supported in this Truffle virtual machine. 225 * Descriptions of languages supported in this Truffle virtual machine.
111 * 226 *
319 if (impl == null) { 434 if (impl == null) {
320 String n = props.getProperty("className"); 435 String n = props.getProperty("className");
321 try { 436 try {
322 Class<?> langClazz = Class.forName(n, true, loader()); 437 Class<?> langClazz = Class.forName(n, true, loader());
323 Constructor<?> constructor = langClazz.getConstructor(Env.class); 438 Constructor<?> constructor = langClazz.getConstructor(Env.class);
324 impl = SPI.attachEnv(TruffleVM.this, constructor); 439 impl = SPI.attachEnv(TruffleVM.this, constructor, out, err, in);
325 } catch (Exception ex) { 440 } catch (Exception ex) {
326 throw new IllegalStateException("Cannot initialize " + getName() + " language with implementation " + n, ex); 441 throw new IllegalStateException("Cannot initialize " + getName() + " language with implementation " + n, ex);
327 } 442 }
328 } 443 }
329 return impl; 444 return impl;
351 } 466 }
352 return null; 467 return null;
353 } 468 }
354 469
355 @Override 470 @Override
356 public TruffleLanguage attachEnv(TruffleVM vm, Constructor<?> langClazz) { 471 public TruffleLanguage attachEnv(TruffleVM vm, Constructor<?> langClazz, Writer stdOut, Writer stdErr, Reader stdIn) {
357 return super.attachEnv(vm, langClazz); 472 return super.attachEnv(vm, langClazz, stdOut, stdErr, stdIn);
358 } 473 }
359 474
360 @Override 475 @Override
361 public Object eval(TruffleLanguage l, Source s) throws IOException { 476 public Object eval(TruffleLanguage l, Source s) throws IOException {
362 return super.eval(l, s); 477 return super.eval(l, s);