# HG changeset patch # User Christian Wimmer # Date 1440181040 25200 # Node ID 2a22cec8411458f07732e1ca05468c180fef533b # Parent 049e6eeaf80a7fe3744ed6e75e4aa1049c762493 Call reflection and service loader code from static initializers diff -r 049e6eeaf80a -r 2a22cec84114 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Fri Aug 21 16:19:26 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/impl/Accessor.java Fri Aug 21 11:17:20 2015 -0700 @@ -155,11 +155,20 @@ return API.getDebugSupport(l); } - protected CallTarget createCallTarget(TruffleLanguage lang, Object obj, Object[] args) throws IOException { + private static final SymbolInvoker INVOKER; + + static { + SymbolInvoker singleton = null; for (SymbolInvoker si : ServiceLoader.load(SymbolInvoker.class)) { - return si.createCallTarget(lang, obj, args); + assert singleton == null : "More than one SymbolInvoker found: " + singleton + ", " + si; + singleton = si; } - throw new IOException("No symbol invoker found!"); + assert singleton != null : "No SymbolInvoker found"; + INVOKER = singleton; + } + + protected CallTarget createCallTarget(TruffleLanguage lang, Object obj, Object[] args) throws IOException { + return INVOKER.createCallTarget(lang, obj, args); } protected Class findLanguage(RootNode n) { diff -r 049e6eeaf80a -r 2a22cec84114 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java --- a/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java Fri Aug 21 16:19:26 2015 +0200 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java Fri Aug 21 11:17:20 2015 -0700 @@ -74,6 +74,68 @@ public final class TruffleVM { private static final Logger LOG = Logger.getLogger(TruffleVM.class.getName()); private static final SPIAccessor SPI = new SPIAccessor(); + + static final class LanguageData { + final String name; + final String version; + final Set mimeTypes; + final TruffleLanguage language; + + LanguageData(String prefix, Properties props) { + this.name = props.getProperty(prefix + "name"); + this.version = props.getProperty(prefix + "version"); + + TreeSet ts = new TreeSet<>(); + for (int i = 0;; i++) { + String mt = props.getProperty(prefix + "mimeType." + i); + if (mt == null) { + break; + } + ts.add(mt); + } + this.mimeTypes = Collections.unmodifiableSet(ts); + + String n = props.getProperty(prefix + "className"); + try { + Class langClazz = Class.forName(n, true, loader()); + this.language = (TruffleLanguage) langClazz.getField("INSTANCE").get(null); + } catch (Exception ex) { + throw new IllegalStateException("Cannot initialize " + name + " language with implementation " + n, ex); + } + } + } + + private static final List ALL_LANGUAGE_DATA; + static { + ALL_LANGUAGE_DATA = new ArrayList<>(); + Enumeration en; + try { + en = loader().getResources("META-INF/truffle/language"); + } catch (IOException ex) { + throw new IllegalStateException("Cannot read list of Truffle languages", ex); + } + while (en.hasMoreElements()) { + URL u = en.nextElement(); + Properties p; + try { + p = new Properties(); + try (InputStream is = u.openStream()) { + p.load(is); + } + } catch (IOException ex) { + LOG.log(Level.CONFIG, "Cannot process " + u + " as language definition", ex); + continue; + } + for (int cnt = 1;; cnt++) { + String prefix = "language" + cnt + "."; + if (p.getProperty(prefix + "name") == null) { + break; + } + ALL_LANGUAGE_DATA.add(new LanguageData(prefix, p)); + } + } + } + private final Thread initThread; private final Map langs; private final Reader in; @@ -111,33 +173,11 @@ this.initThread = Thread.currentThread(); this.globals = new HashMap<>(globals); this.langs = new HashMap<>(); - Enumeration en; - try { - en = loader().getResources("META-INF/truffle/language"); - } catch (IOException ex) { - throw new IllegalStateException("Cannot read list of Truffle languages", ex); - } - while (en.hasMoreElements()) { - URL u = en.nextElement(); - Properties p; - try { - p = new Properties(); - try (InputStream is = u.openStream()) { - p.load(is); - } - } catch (IOException ex) { - LOG.log(Level.CONFIG, "Cannot process " + u + " as language definition", ex); - continue; - } - for (int cnt = 1;; cnt++) { - String prefix = "language" + cnt + "."; - if (p.getProperty(prefix + "name") == null) { - break; - } - Language l = new Language(prefix, p); - for (String mimeType : l.getMimeTypes()) { - langs.put(mimeType, l); - } + + for (LanguageData data : ALL_LANGUAGE_DATA) { + Language l = new Language(data); + for (String mimeType : l.getMimeTypes()) { + langs.put(mimeType, l); } } } @@ -537,15 +577,13 @@ * {@link TruffleVM#eval(java.lang.String, java.lang.String) a code is evaluated} in it. */ public final class Language { - private final Properties props; + private final LanguageData data; private TruffleLanguage impl; private TruffleLanguage.Env env; - private final String prefix; private String shortName; - Language(String prefix, Properties props) { - this.prefix = prefix; - this.props = props; + Language(LanguageData data) { + this.data = data; } /** @@ -554,15 +592,7 @@ * @return returns immutable set of recognized MIME types */ public Set getMimeTypes() { - TreeSet ts = new TreeSet<>(); - for (int i = 0;; i++) { - String mt = props.getProperty(prefix + "mimeType." + i); - if (mt == null) { - break; - } - ts.add(mt); - } - return Collections.unmodifiableSet(ts); + return data.mimeTypes; } /** @@ -571,7 +601,7 @@ * @return string giving the language a name */ public String getName() { - return props.getProperty(prefix + "name"); + return data.name; } /** @@ -580,7 +610,7 @@ * @return string specifying the language version */ public String getVersion() { - return props.getProperty(prefix + "version"); + return data.version; } /** @@ -597,14 +627,12 @@ TruffleLanguage getImpl() { if (impl == null) { - String n = props.getProperty(prefix + "className"); try { - Class langClazz = Class.forName(n, true, loader()); - TruffleLanguage language = (TruffleLanguage) langClazz.getField("INSTANCE").get(null); + TruffleLanguage language = data.language; env = SPI.attachEnv(TruffleVM.this, language, out, err, in); impl = language; } catch (Exception ex) { - throw new IllegalStateException("Cannot initialize " + getShortName() + " language with implementation " + n, ex); + throw new IllegalStateException("Cannot initialize " + getShortName() + " language with implementation " + data.language.getClass().getName(), ex); } } return impl;