1 /* 2 * Copyright (c) 2015, 2019, 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 jdk.vm.ci.hotspot; 24 25 import java.util.List; 26 import java.util.Set; 27 28 import jdk.vm.ci.code.CompilationRequest; 29 import jdk.vm.ci.common.JVMCIError; 30 import jdk.vm.ci.common.NativeImageReinitialize; 31 import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; 32 import jdk.vm.ci.runtime.JVMCICompiler; 33 import jdk.vm.ci.runtime.JVMCICompilerFactory; 34 import jdk.vm.ci.runtime.JVMCIRuntime; 35 import jdk.vm.ci.services.JVMCIPermission; 36 import jdk.vm.ci.services.JVMCIServiceLocator; 37 import jdk.vm.ci.services.Services; 38 39 import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; 40 41 final class HotSpotJVMCICompilerConfig { 42 43 /** 44 * This factory allows JVMCI initialization to succeed but raises an error if the VM asks JVMCI 45 * to perform a compilation. This allows the reflective parts of the JVMCI API to be used 46 * without requiring a compiler implementation to be available. 47 */ 48 private static class DummyCompilerFactory implements JVMCICompilerFactory, JVMCICompiler { 49 50 private final String reason; 51 private final HotSpotJVMCIRuntime runtime; 52 DummyCompilerFactory(String reason, HotSpotJVMCIRuntime runtime)53 DummyCompilerFactory(String reason, HotSpotJVMCIRuntime runtime) { 54 this.reason = reason; 55 this.runtime = runtime; 56 } 57 58 @Override compileMethod(CompilationRequest request)59 public HotSpotCompilationRequestResult compileMethod(CompilationRequest request) { 60 throw runtime.exitHotSpotWithMessage(1, "Cannot use JVMCI compiler: %s%n", reason); 61 } 62 63 @Override getCompilerName()64 public String getCompilerName() { 65 return "null"; 66 } 67 68 @Override createCompiler(JVMCIRuntime rt)69 public JVMCICompiler createCompiler(JVMCIRuntime rt) { 70 return this; 71 } 72 73 @Override isGCSupported(int gcIdentifier)74 public boolean isGCSupported(int gcIdentifier) { 75 return false; 76 } 77 } 78 79 /** 80 * Factory of the selected system compiler. 81 */ 82 @NativeImageReinitialize private static JVMCICompilerFactory compilerFactory; 83 84 /** 85 * Gets the selected system compiler factory. 86 * 87 * @return the selected system compiler factory 88 * @throws SecurityException if a security manager is present and it denies 89 * {@link JVMCIPermission} for any {@link JVMCIServiceLocator} loaded by this method 90 */ getCompilerFactory(HotSpotJVMCIRuntime runtime)91 static JVMCICompilerFactory getCompilerFactory(HotSpotJVMCIRuntime runtime) { 92 if (compilerFactory == null) { 93 JVMCICompilerFactory factory = null; 94 String compilerName = Option.Compiler.getString(); 95 if (compilerName != null) { 96 String compPropertyName = Option.Compiler.getPropertyName(); 97 if (compilerName.isEmpty()) { 98 factory = new DummyCompilerFactory("Value of " + compPropertyName + " is empty", runtime); 99 } else if (compilerName.equals("null")) { 100 factory = new DummyCompilerFactory("Value of " + compPropertyName + " is \"null\"", runtime); 101 } else { 102 for (JVMCICompilerFactory f : getJVMCICompilerFactories()) { 103 if (f.getCompilerName().equals(compilerName)) { 104 factory = f; 105 } 106 } 107 if (factory == null) { 108 if (Services.IS_IN_NATIVE_IMAGE) { 109 throw runtime.exitHotSpotWithMessage(1, "JVMCI compiler '%s' not found in JVMCI native library.%n" + 110 "Use -XX:-UseJVMCINativeLibrary when specifying a JVMCI compiler available on a class path with %s.%n", 111 compilerName, compPropertyName); 112 } 113 throw runtime.exitHotSpotWithMessage(1, "JVMCI compiler '%s' specified by %s not found%n", compilerName, compPropertyName); 114 } 115 } 116 } else { 117 // Auto select a single available compiler 118 String reason = "No JVMCI compiler found"; 119 for (JVMCICompilerFactory f : getJVMCICompilerFactories()) { 120 if (factory == null) { 121 openJVMCITo(f.getClass().getModule()); 122 factory = f; 123 } else { 124 // Multiple factories seen - cancel auto selection 125 reason = "Multiple JVMCI compilers found: \"" + factory.getCompilerName() + "\" and \"" + f.getCompilerName() + "\""; 126 factory = null; 127 break; 128 } 129 } 130 if (factory == null) { 131 factory = new DummyCompilerFactory(reason, runtime); 132 } 133 } 134 factory.onSelection(); 135 compilerFactory = factory; 136 } 137 return compilerFactory; 138 } 139 140 /** 141 * Opens all JVMCI packages to {@code otherModule}. 142 */ openJVMCITo(Module otherModule)143 private static void openJVMCITo(Module otherModule) { 144 if (!IS_IN_NATIVE_IMAGE) { 145 Module jvmci = HotSpotJVMCICompilerConfig.class.getModule(); 146 if (jvmci != otherModule) { 147 Set<String> packages = jvmci.getPackages(); 148 for (String pkg : packages) { 149 boolean opened = jvmci.isOpen(pkg, otherModule); 150 if (!opened) { 151 jvmci.addOpens(pkg, otherModule); 152 } 153 } 154 } 155 } 156 } 157 getJVMCICompilerFactories()158 private static List<JVMCICompilerFactory> getJVMCICompilerFactories() { 159 return JVMCIServiceLocator.getProviders(JVMCICompilerFactory.class); 160 } 161 } 162