# HG changeset patch # User Jaroslav Tulach # Date 1440667232 -7200 # Node ID 2482183730b8eb3b0cfd38ab10cf76991526c159 # Parent 0aad723479e87cb2abfe711889116aef2574ac38 Use -Dcom.oracle.truffle.aot=true when launching the JVM to preload all Truffle languages on first TruffleVM usage diff -r 0aad723479e8 -r 2482183730b8 truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/LanguageCache.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/LanguageCache.java Thu Aug 27 11:20:32 2015 +0200 @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.api.vm; + +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.vm.TruffleVM.Language; +import java.util.HashMap; +import java.util.Map; + +/** + * Ahead-of-time initialization. If the JVM is started with -Dcom.oracle.truffle.aot=true, it + * populates cache with languages found in application classloader. + */ +final class LanguageCache { + private static final Map> CACHE; + static { + Map> map = null; + if (Boolean.getBoolean("com.oracle.truffle.aot")) { // NOI18N + map = new HashMap<>(); + for (Language description : TruffleVM.newVM().build().getLanguages().values()) { + TruffleLanguage language = description.getImpl(false); + map.put(language.getClass().getName(), language); + } + } + CACHE = map; + } + + static TruffleLanguage find(String name) { + return CACHE == null ? null : CACHE.get(name); + } +} diff -r 0aad723479e8 -r 2482183730b8 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 Wed Aug 26 14:49:11 2015 -0700 +++ b/truffle/com.oracle.truffle.api/src/com/oracle/truffle/api/vm/TruffleVM.java Thu Aug 27 11:20:32 2015 +0200 @@ -74,68 +74,6 @@ 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; @@ -173,11 +111,33 @@ this.initThread = Thread.currentThread(); this.globals = new HashMap<>(globals); this.langs = new HashMap<>(); - - for (LanguageData data : ALL_LANGUAGE_DATA) { - Language l = new Language(data); - for (String mimeType : l.getMimeTypes()) { - langs.put(mimeType, l); + 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); + } } } } @@ -602,13 +562,15 @@ * {@link TruffleVM#eval(java.lang.String, java.lang.String) a code is evaluated} in it. */ public final class Language { - private final LanguageData data; + private final Properties props; private TruffleLanguage impl; private TruffleLanguage.Env env; + private final String prefix; private String shortName; - Language(LanguageData data) { - this.data = data; + Language(String prefix, Properties props) { + this.prefix = prefix; + this.props = props; } /** @@ -617,7 +579,15 @@ * @return returns immutable set of recognized MIME types */ public Set getMimeTypes() { - return data.mimeTypes; + 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); } /** @@ -626,7 +596,7 @@ * @return string giving the language a name */ public String getName() { - return data.name; + return props.getProperty(prefix + "name"); } /** @@ -635,7 +605,7 @@ * @return string specifying the language version */ public String getVersion() { - return data.version; + return props.getProperty(prefix + "version"); } /** @@ -651,13 +621,25 @@ } TruffleLanguage getImpl() { + return getImpl(true); + } + + TruffleLanguage getImpl(boolean tryCache) { if (impl == null) { + String n = props.getProperty(prefix + "className"); try { - TruffleLanguage language = data.language; + TruffleLanguage language = null; + if (tryCache) { + language = LanguageCache.find(n); + } + if (language == null) { + Class langClazz = Class.forName(n, true, loader()); + language = (TruffleLanguage) langClazz.getField("INSTANCE").get(null); + } impl = language; env = SPI.attachEnv(TruffleVM.this, language, out, err, in); } catch (Exception ex) { - throw new IllegalStateException("Cannot initialize " + getShortName() + " language with implementation " + data.language.getClass().getName(), ex); + throw new IllegalStateException("Cannot initialize " + getShortName() + " language with implementation " + n, ex); } } return impl;