HotSpotGraalCompilerFactory.java revision 12995:5e441a7ec5e3
1/*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23package org.graalvm.compiler.hotspot;
24
25import static jdk.vm.ci.common.InitTimer.timer;
26import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX;
27
28import java.io.PrintStream;
29
30import org.graalvm.compiler.debug.MethodFilter;
31import org.graalvm.compiler.options.Option;
32import org.graalvm.compiler.options.OptionKey;
33import org.graalvm.compiler.options.OptionType;
34import org.graalvm.compiler.options.OptionValues;
35import org.graalvm.compiler.options.OptionsParser;
36import org.graalvm.compiler.phases.tiers.CompilerConfiguration;
37
38import jdk.vm.ci.common.InitTimer;
39import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory;
40import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
41import jdk.vm.ci.hotspot.HotSpotSignature;
42import jdk.vm.ci.runtime.JVMCIRuntime;
43import jdk.vm.ci.services.Services;
44
45public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory {
46
47    private static MethodFilter[] graalCompileOnlyFilter;
48    private static boolean compileGraalWithC1Only;
49
50    private final HotSpotGraalJVMCIServiceLocator locator;
51
52    HotSpotGraalCompilerFactory(HotSpotGraalJVMCIServiceLocator locator) {
53        this.locator = locator;
54    }
55
56    @Override
57    public String getCompilerName() {
58        return "graal";
59    }
60
61    /**
62     * Initialized when this factory is {@linkplain #onSelection() selected}.
63     */
64    private OptionValues options;
65
66    @Override
67    public void onSelection() {
68        JVMCIVersionCheck.check(false);
69        assert options == null : "cannot select " + getClass() + " service more than once";
70        options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS;
71        initializeGraalCompilePolicyFields(options);
72        /*
73         * Exercise this code path early to encourage loading now. This doesn't solve problem of
74         * deadlock during class loading but seems to eliminate it in practice.
75         */
76        adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.FullOptimization);
77        adjustCompilationLevelInternal(Object.class, "hashCode", "()I", CompilationLevel.Simple);
78    }
79
80    private static void initializeGraalCompilePolicyFields(OptionValues options) {
81        compileGraalWithC1Only = Options.CompileGraalWithC1Only.getValue(options);
82        String optionValue = Options.GraalCompileOnly.getValue(options);
83        if (optionValue != null) {
84            MethodFilter[] filter = MethodFilter.parse(optionValue);
85            if (filter.length == 0) {
86                filter = null;
87            }
88            graalCompileOnlyFilter = filter;
89        }
90    }
91
92    @Override
93    public void printProperties(PrintStream out) {
94        out.println("[Graal properties]");
95        options.printHelp(OptionsParser.getOptionsLoader(), out, GRAAL_OPTION_PROPERTY_PREFIX);
96    }
97
98    static class Options {
99
100        // @formatter:off
101        @Option(help = "In tiered mode compile Graal and JVMCI using optimized first tier code.", type = OptionType.Expert)
102        public static final OptionKey<Boolean> CompileGraalWithC1Only = new OptionKey<>(true);
103
104        @Option(help = "A method filter selecting what should be compiled by Graal.  All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert)
105        public static final OptionKey<String> GraalCompileOnly = new OptionKey<>(null);
106        // @formatter:on
107
108    }
109
110    @Override
111    public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) {
112        HotSpotGraalCompiler compiler = createCompiler(runtime, options, CompilerConfigurationFactory.selectFactory(null, options));
113        // Only the HotSpotGraalRuntime associated with the compiler created via
114        // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving
115        // VM events.
116        locator.onCompilerCreation(compiler);
117        return compiler;
118    }
119
120    /**
121     * Creates a new {@link HotSpotGraalRuntime} object and a new {@link HotSpotGraalCompiler} and
122     * returns the latter.
123     *
124     * @param runtime the JVMCI runtime on which the {@link HotSpotGraalRuntime} is built
125     * @param compilerConfigurationFactory factory for the {@link CompilerConfiguration}
126     */
127    @SuppressWarnings("try")
128    public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) {
129        HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime;
130        try (InitTimer t = timer("HotSpotGraalRuntime.<init>")) {
131            HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory, options);
132            return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime);
133        }
134    }
135
136    @Override
137    public CompilationLevelAdjustment getCompilationLevelAdjustment() {
138        if (graalCompileOnlyFilter != null) {
139            return CompilationLevelAdjustment.ByFullSignature;
140        }
141        if (compileGraalWithC1Only) {
142            // We only decide using the class declaring the method
143            // so no need to have the method name and signature
144            // symbols converted to a String.
145            return CompilationLevelAdjustment.ByHolder;
146        }
147        return CompilationLevelAdjustment.None;
148    }
149
150    @Override
151    public CompilationLevel adjustCompilationLevel(Class<?> declaringClass, String name, String signature, boolean isOsr, CompilationLevel level) {
152        return adjustCompilationLevelInternal(declaringClass, name, signature, level);
153    }
154
155    static {
156        // Fail-fast detection for package renaming to guard use of package
157        // prefixes in adjustCompilationLevelInternal.
158        assert Services.class.getName().equals("jdk.vm.ci.services.Services");
159        assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory");
160    }
161
162    /*
163     * This method is static so it can be exercised during initialization.
164     */
165    private static CompilationLevel adjustCompilationLevelInternal(Class<?> declaringClass, String name, String signature, CompilationLevel level) {
166        if (graalCompileOnlyFilter != null) {
167            if (level == CompilationLevel.FullOptimization) {
168                String declaringClassName = declaringClass.getName();
169                HotSpotSignature sig = null;
170                for (MethodFilter filter : graalCompileOnlyFilter) {
171                    if (filter.hasSignature() && sig == null) {
172                        sig = new HotSpotSignature(HotSpotJVMCIRuntime.runtime(), signature);
173                    }
174                    if (filter.matches(declaringClassName, name, sig)) {
175                        return level;
176                    }
177                }
178                return CompilationLevel.Simple;
179            }
180        }
181        if (compileGraalWithC1Only) {
182            if (level.ordinal() > CompilationLevel.Simple.ordinal()) {
183                String declaringClassName = declaringClass.getName();
184                if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm") || declaringClassName.startsWith("com.oracle.graal")) {
185                    return CompilationLevel.Simple;
186                }
187            }
188        }
189        return level;
190    }
191}
192