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 */ 23 package org.graalvm.compiler.hotspot; 24 25 import static jdk.vm.ci.common.InitTimer.timer; 26 import static org.graalvm.compiler.hotspot.HotSpotGraalOptionValues.GRAAL_OPTION_PROPERTY_PREFIX; 27 28 import java.io.PrintStream; 29 30 import org.graalvm.compiler.debug.MethodFilter; 31 import org.graalvm.compiler.options.Option; 32 import org.graalvm.compiler.options.OptionKey; 33 import org.graalvm.compiler.options.OptionType; 34 import org.graalvm.compiler.options.OptionValues; 35 import org.graalvm.compiler.options.OptionsParser; 36 import org.graalvm.compiler.phases.tiers.CompilerConfiguration; 37 38 import jdk.vm.ci.common.InitTimer; 39 import jdk.vm.ci.hotspot.HotSpotJVMCICompilerFactory; 40 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; 41 import jdk.vm.ci.hotspot.HotSpotSignature; 42 import jdk.vm.ci.runtime.JVMCIRuntime; 43 import jdk.vm.ci.services.Services; 44 45 public final class HotSpotGraalCompilerFactory extends HotSpotJVMCICompilerFactory { 46 47 private static MethodFilter[] graalCompileOnlyFilter; 48 49 private final HotSpotGraalJVMCIServiceLocator locator; 50 51 HotSpotGraalCompilerFactory(HotSpotGraalJVMCIServiceLocator locator) { 52 this.locator = locator; 53 } 54 55 @Override 56 public String getCompilerName() { 57 return "graal"; 58 } 59 60 /** 61 * Initialized when this factory is {@linkplain #onSelection() selected}. 62 */ 63 private OptionValues options; 64 65 @Override 66 public void onSelection() { 67 JVMCIVersionCheck.check(false); 68 assert options == null : "cannot select " + getClass() + " service more than once"; 69 options = HotSpotGraalOptionValues.HOTSPOT_OPTIONS; 70 initializeGraalCompileOnlyFilter(options); 71 if (graalCompileOnlyFilter != null || !Options.UseTrivialPrefixes.getValue(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 81 private static void initializeGraalCompileOnlyFilter(OptionValues 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 = "Hook into VM-level mechanism for denoting compilations to be performed in first tier.", type = OptionType.Expert) 105 public static final OptionKey<Boolean> UseTrivialPrefixes = new OptionKey<>(false); 106 107 @Option(help = "A method filter selecting what should be compiled by Graal. All other requests will be reduced to CompilationLevel.Simple.", type = OptionType.Expert) 108 public static final OptionKey<String> GraalCompileOnly = new OptionKey<>(null); 109 // @formatter:on 110 111 } 112 113 @Override 114 public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { 115 HotSpotGraalCompiler compiler = createCompiler(runtime, options, CompilerConfigurationFactory.selectFactory(null, options)); 116 // Only the HotSpotGraalRuntime associated with the compiler created via 117 // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving 118 // VM events. 119 locator.onCompilerCreation(compiler); 120 return compiler; 121 } 122 123 /** 124 * Creates a new {@link HotSpotGraalRuntime} object and a new {@link HotSpotGraalCompiler} and 125 * returns the latter. 126 * 127 * @param runtime the JVMCI runtime on which the {@link HotSpotGraalRuntime} is built 128 * @param compilerConfigurationFactory factory for the {@link CompilerConfiguration} 129 */ 130 @SuppressWarnings("try") 131 public static HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) { 132 HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime; 133 try (InitTimer t = timer("HotSpotGraalRuntime.<init>")) { 134 HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(jvmciRuntime, compilerConfigurationFactory, options); 135 return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime); 136 } 137 } 138 139 @Override 140 public String[] getTrivialPrefixes() { 141 if (Options.UseTrivialPrefixes.getValue(options)) { 142 if (Options.CompileGraalWithC1Only.getValue(options)) { 143 return new String[]{"jdk/vm/ci", "org/graalvm/compiler", "com/oracle/graal"}; 144 } 145 } 146 return null; 147 } 148 149 @Override 150 public CompilationLevelAdjustment getCompilationLevelAdjustment() { 151 if (graalCompileOnlyFilter != null) { 152 return CompilationLevelAdjustment.ByFullSignature; 153 } 154 if (!Options.UseTrivialPrefixes.getValue(options)) { 155 if (Options.CompileGraalWithC1Only.getValue(options)) { 156 // We only decide using the class declaring the method 157 // so no need to have the method name and signature 158 // symbols converted to a String. 159 return CompilationLevelAdjustment.ByHolder; 160 } 161 } 162 return CompilationLevelAdjustment.None; 163 } 164 165 @Override 166 public CompilationLevel adjustCompilationLevel(Class<?> declaringClass, String name, String signature, boolean isOsr, CompilationLevel level) { 167 return adjustCompilationLevelInternal(declaringClass, name, signature, level); 168 } 169 170 static { 171 // Fail-fast detection for package renaming to guard use of package 172 // prefixes in adjustCompilationLevelInternal. 173 assert Services.class.getName().equals("jdk.vm.ci.services.Services"); 174 assert HotSpotGraalCompilerFactory.class.getName().equals("org.graalvm.compiler.hotspot.HotSpotGraalCompilerFactory"); 175 } 176 177 /* 178 * This method is static so it can be exercised during initialization. 179 */ 180 private static CompilationLevel adjustCompilationLevelInternal(Class<?> declaringClass, String name, String signature, CompilationLevel level) { 181 if (graalCompileOnlyFilter != null) { 182 if (level == CompilationLevel.FullOptimization) { 183 String declaringClassName = declaringClass.getName(); 184 HotSpotSignature sig = null; 185 for (MethodFilter filter : graalCompileOnlyFilter) { 186 if (filter.hasSignature() && sig == null) { 187 sig = new HotSpotSignature(HotSpotJVMCIRuntime.runtime(), signature); 188 } 189 if (filter.matches(declaringClassName, name, sig)) { 190 return level; 191 } 192 } 193 return CompilationLevel.Simple; 194 } 195 } 196 if (level.ordinal() > CompilationLevel.Simple.ordinal()) { 197 String declaringClassName = declaringClass.getName(); 198 if (declaringClassName.startsWith("jdk.vm.ci") || declaringClassName.startsWith("org.graalvm.compiler") || declaringClassName.startsWith("com.oracle.graal")) { 199 return CompilationLevel.Simple; 200 } 201 } 202 return level; 203 } 204 }