< prev index next >

src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java

Print this page




  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 static jdk.vm.ci.common.InitTimer.timer;
  26 
  27 import java.io.IOException;
  28 import java.io.OutputStream;
  29 import java.io.PrintStream;
  30 import java.lang.reflect.Array;
  31 import java.lang.reflect.Field;
  32 import java.lang.reflect.Method;
  33 import java.lang.reflect.Modifier;
  34 import java.util.ArrayList;
  35 import java.util.Collections;
  36 import java.util.HashMap;
  37 import java.util.List;
  38 import java.util.Map;
  39 import java.util.Objects;
  40 import java.util.ServiceLoader;
  41 import java.util.TreeMap;
  42 
  43 import jdk.internal.misc.VM;
  44 import jdk.vm.ci.code.Architecture;
  45 import jdk.vm.ci.code.CompilationRequestResult;
  46 import jdk.vm.ci.code.CompiledCode;
  47 import jdk.vm.ci.code.InstalledCode;
  48 import jdk.vm.ci.common.InitTimer;
  49 import jdk.vm.ci.common.JVMCIError;
  50 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory;
  51 import jdk.vm.ci.hotspot.services.HotSpotVMEventListener;
  52 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory.CompilationLevel;

  53 import jdk.vm.ci.meta.JavaKind;
  54 import jdk.vm.ci.meta.JavaType;
  55 import jdk.vm.ci.meta.ResolvedJavaType;
  56 import jdk.vm.ci.runtime.JVMCI;
  57 import jdk.vm.ci.runtime.JVMCIBackend;
  58 import jdk.vm.ci.runtime.JVMCICompiler;
  59 import jdk.vm.ci.runtime.services.JVMCICompilerFactory;
  60 import jdk.vm.ci.services.Services;
  61 
  62 /**
  63  * HotSpot implementation of a JVMCI runtime.
  64  *
  65  * The initialization of this class is very fragile since it's initialized both through
  66  * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and
  67  * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class
  68  * can't have a static initializer and any required initialization must be done as part of
  69  * {@link #runtime()}. This allows the initialization to funnel back through
  70  * {@link JVMCI#initialize()} without deadlocking.
  71  */
  72 public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider {


  78         static {
  79             try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
  80                 instance = new HotSpotJVMCIRuntime();
  81             }
  82         }
  83     }
  84 
  85     /**
  86      * Gets the singleton {@link HotSpotJVMCIRuntime} object.
  87      */
  88     public static HotSpotJVMCIRuntime runtime() {
  89         JVMCI.initialize();
  90         return DelayedInit.instance;
  91     }
  92 
  93     /**
  94      * A list of all supported JVMCI options.
  95      */
  96     public enum Option {
  97         Compiler(String.class, null, "Selects the system compiler."),
  98         // Note: The following one is not used (see InitTimer.ENABLED).

  99         InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."),
 100         PrintConfig(boolean.class, false, "Prints all HotSpotVMConfig fields."),
 101         PrintFlags(boolean.class, false, "Prints all JVMCI flags and exits."),
 102         ShowFlags(boolean.class, false, "Prints all JVMCI flags and continues."),
 103         TraceMethodDataFilter(String.class, null, "");
 104 
 105         /**
 106          * The prefix for system properties that are JVMCI options.
 107          */
 108         private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
 109 
 110         /**
 111          * Marker for uninitialized flags.
 112          */
 113         private static final String UNINITIALIZED = "UNINITIALIZED";
 114 
 115         private final Class<?> type;
 116         private Object value;
 117         private final Object defaultValue;
 118         private boolean isDefault;
 119         private final String help;
 120 


 225             synchronized (this) {
 226                 if (vmEventListeners == null) {
 227                     List<HotSpotVMEventListener> listeners = new ArrayList<>();
 228                     for (HotSpotVMEventListener vmEventListener : ServiceLoader.load(HotSpotVMEventListener.class)) {
 229                         listeners.add(vmEventListener);
 230                     }
 231                     vmEventListeners = listeners;
 232                 }
 233             }
 234         }
 235         return vmEventListeners;
 236     }
 237 
 238     /**
 239      * Stores the result of {@link HotSpotJVMCICompilerFactory#getTrivialPrefixes()} so that it can
 240      * be read from the VM.
 241      */
 242     @SuppressWarnings("unused") private final String[] trivialPrefixes;
 243 
 244     @SuppressWarnings("try")

 245     private HotSpotJVMCIRuntime() {
 246         compilerToVm = new CompilerToVM();
 247 
 248         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
 249             configStore = new HotSpotVMConfigStore(compilerToVm);
 250             config = new HotSpotVMConfig(configStore);
 251         }
 252 
 253         String hostArchitecture = config.getHostArchitectureName();
 254 
 255         HotSpotJVMCIBackendFactory factory;
 256         try (InitTimer t = timer("find factory:", hostArchitecture)) {
 257             factory = findFactory(hostArchitecture);
 258         }
 259 
 260         try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
 261             hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
 262         }
 263 
 264         metaAccessContext = new HotSpotJVMCIMetaAccessContext();
 265 
 266         boolean printFlags = Option.PrintFlags.getBoolean();
 267         boolean showFlags = Option.ShowFlags.getBoolean();
 268         if (printFlags || showFlags) {
 269             Option.printFlags(System.out);
 270             if (printFlags) {
 271                 System.exit(0);
 272             }
 273         }
 274 
 275         if (Option.PrintConfig.getBoolean()) {
 276             printConfig(config, compilerToVm);

 277         }
 278 
 279         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
 280         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
 281             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
 282             trivialPrefixes = hsCompilerFactory.getTrivialPrefixes();
 283             switch (hsCompilerFactory.getCompilationLevelAdjustment()) {
 284                 case None:
 285                     compilationLevelAdjustment = config.compLevelAdjustmentNone;
 286                     break;
 287                 case ByHolder:
 288                     compilationLevelAdjustment = config.compLevelAdjustmentByHolder;
 289                     break;
 290                 case ByFullSignature:
 291                     compilationLevelAdjustment = config.compLevelAdjustmentByFullSignature;
 292                     break;
 293                 default:
 294                     compilationLevelAdjustment = config.compLevelAdjustmentNone;
 295                     break;
 296             }


 447     @SuppressWarnings({"unused"})
 448     private void bootstrapFinished() throws Exception {
 449         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
 450             vmEventListener.notifyBootstrapFinished();
 451         }
 452     }
 453 
 454     /**
 455      * Notify on successful install into the CodeCache.
 456      *
 457      * @param hotSpotCodeCacheProvider
 458      * @param installedCode
 459      * @param compiledCode
 460      */
 461     void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
 462         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
 463             vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compiledCode);
 464         }
 465     }
 466 
 467     private static void printConfig(HotSpotVMConfig config, CompilerToVM vm) {
 468         Field[] fields = config.getClass().getDeclaredFields();
 469         Map<String, Field> sortedFields = new TreeMap<>();
 470         for (Field f : fields) {
 471             if (!f.isSynthetic() && !Modifier.isStatic(f.getModifiers())) {
 472                 f.setAccessible(true);
 473                 sortedFields.put(f.getName(), f);
 474             }
 475         }
 476         for (Field f : sortedFields.values()) {
 477             try {
 478                 String line = String.format("%9s %-40s = %s%n", f.getType().getSimpleName(), f.getName(), pretty(f.get(config)));
 479                 byte[] lineBytes = line.getBytes();
 480                 vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
 481                 vm.flushDebugOutput();
 482             } catch (Exception e) {
 483             }
 484         }
 485     }
 486 
 487     private static String pretty(Object value) {
 488         if (value == null) {
 489             return "null";
 490         }
 491 
 492         Class<?> klass = value.getClass();
 493         if (value instanceof String) {
 494             return "\"" + value + "\"";
 495         } else if (value instanceof Method) {
 496             return "method \"" + ((Method) value).getName() + "\"";
 497         } else if (value instanceof Class<?>) {
 498             return "class \"" + ((Class<?>) value).getSimpleName() + "\"";
 499         } else if (value instanceof Integer) {
 500             if ((Integer) value < 10) {
 501                 return value.toString();
 502             }
 503             return value + " (0x" + Integer.toHexString((Integer) value) + ")";
 504         } else if (value instanceof Long) {
 505             if ((Long) value < 10 && (Long) value > -10) {
 506                 return value + "l";
 507             }
 508             return value + "l (0x" + Long.toHexString((Long) value) + "l)";
 509         } else if (klass.isArray()) {
 510             StringBuilder str = new StringBuilder();
 511             int dimensions = 0;
 512             while (klass.isArray()) {
 513                 dimensions++;
 514                 klass = klass.getComponentType();
 515             }
 516             int length = Array.getLength(value);
 517             str.append(klass.getSimpleName()).append('[').append(length).append(']');
 518             for (int i = 1; i < dimensions; i++) {
 519                 str.append("[]");
 520             }
 521             str.append(" {");
 522             for (int i = 0; i < length; i++) {
 523                 str.append(pretty(Array.get(value, i)));
 524                 if (i < length - 1) {
 525                     str.append(", ");
 526                 }



 527             }
 528             str.append('}');
 529             return str.toString();

 530         }
 531         return value.toString();
 532     }
 533 
 534     public OutputStream getLogStream() {
 535         return new OutputStream() {
 536 
 537             @Override
 538             public void write(byte[] b, int off, int len) throws IOException {
 539                 if (b == null) {
 540                     throw new NullPointerException();
 541                 } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length || (off + len) < 0) {
 542                     throw new IndexOutOfBoundsException();
 543                 } else if (len == 0) {
 544                     return;
 545                 }
 546                 compilerToVm.writeDebugOutput(b, off, len);
 547             }
 548 
 549             @Override
 550             public void write(int b) throws IOException {
 551                 write(new byte[]{(byte) b}, 0, 1);


  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 static jdk.vm.ci.common.InitTimer.timer;
  26 
  27 import java.io.IOException;
  28 import java.io.OutputStream;
  29 import java.io.PrintStream;




  30 import java.util.ArrayList;
  31 import java.util.Collections;
  32 import java.util.HashMap;
  33 import java.util.List;
  34 import java.util.Map;
  35 import java.util.Objects;
  36 import java.util.ServiceLoader;
  37 import java.util.TreeMap;
  38 
  39 import jdk.internal.misc.VM;
  40 import jdk.vm.ci.code.Architecture;
  41 import jdk.vm.ci.code.CompilationRequestResult;
  42 import jdk.vm.ci.code.CompiledCode;
  43 import jdk.vm.ci.code.InstalledCode;
  44 import jdk.vm.ci.common.InitTimer;
  45 import jdk.vm.ci.common.JVMCIError;
  46 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory;

  47 import jdk.vm.ci.hotspot.services.HotSpotJVMCICompilerFactory.CompilationLevel;
  48 import jdk.vm.ci.hotspot.services.HotSpotVMEventListener;
  49 import jdk.vm.ci.meta.JavaKind;
  50 import jdk.vm.ci.meta.JavaType;
  51 import jdk.vm.ci.meta.ResolvedJavaType;
  52 import jdk.vm.ci.runtime.JVMCI;
  53 import jdk.vm.ci.runtime.JVMCIBackend;
  54 import jdk.vm.ci.runtime.JVMCICompiler;
  55 import jdk.vm.ci.runtime.services.JVMCICompilerFactory;
  56 import jdk.vm.ci.services.Services;
  57 
  58 /**
  59  * HotSpot implementation of a JVMCI runtime.
  60  *
  61  * The initialization of this class is very fragile since it's initialized both through
  62  * {@link JVMCI#initialize()} or through calling {@link HotSpotJVMCIRuntime#runtime()} and
  63  * {@link HotSpotJVMCIRuntime#runtime()} is also called by {@link JVMCI#initialize()}. So this class
  64  * can't have a static initializer and any required initialization must be done as part of
  65  * {@link #runtime()}. This allows the initialization to funnel back through
  66  * {@link JVMCI#initialize()} without deadlocking.
  67  */
  68 public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider {


  74         static {
  75             try (InitTimer t = timer("HotSpotJVMCIRuntime.<init>")) {
  76                 instance = new HotSpotJVMCIRuntime();
  77             }
  78         }
  79     }
  80 
  81     /**
  82      * Gets the singleton {@link HotSpotJVMCIRuntime} object.
  83      */
  84     public static HotSpotJVMCIRuntime runtime() {
  85         JVMCI.initialize();
  86         return DelayedInit.instance;
  87     }
  88 
  89     /**
  90      * A list of all supported JVMCI options.
  91      */
  92     public enum Option {
  93         Compiler(String.class, null, "Selects the system compiler."),
  94         // Note: The following one is not used (see InitTimer.ENABLED). It is added here
  95         // so that -Djvmci.PrintFlags=true shows the option.
  96         InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."),
  97         PrintConfig(boolean.class, false, "Prints VM configuration available via JVMCI and exits."),
  98         PrintFlags(boolean.class, false, "Prints all JVMCI flags and exits."),
  99         ShowFlags(boolean.class, false, "Prints all JVMCI flags and continues."),
 100         TraceMethodDataFilter(String.class, null, "");
 101 
 102         /**
 103          * The prefix for system properties that are JVMCI options.
 104          */
 105         private static final String JVMCI_OPTION_PROPERTY_PREFIX = "jvmci.";
 106 
 107         /**
 108          * Marker for uninitialized flags.
 109          */
 110         private static final String UNINITIALIZED = "UNINITIALIZED";
 111 
 112         private final Class<?> type;
 113         private Object value;
 114         private final Object defaultValue;
 115         private boolean isDefault;
 116         private final String help;
 117 


 222             synchronized (this) {
 223                 if (vmEventListeners == null) {
 224                     List<HotSpotVMEventListener> listeners = new ArrayList<>();
 225                     for (HotSpotVMEventListener vmEventListener : ServiceLoader.load(HotSpotVMEventListener.class)) {
 226                         listeners.add(vmEventListener);
 227                     }
 228                     vmEventListeners = listeners;
 229                 }
 230             }
 231         }
 232         return vmEventListeners;
 233     }
 234 
 235     /**
 236      * Stores the result of {@link HotSpotJVMCICompilerFactory#getTrivialPrefixes()} so that it can
 237      * be read from the VM.
 238      */
 239     @SuppressWarnings("unused") private final String[] trivialPrefixes;
 240 
 241     @SuppressWarnings("try")
 242     @SuppressFBWarnings(value = "DM_EXIT", justification = "PrintFlags is meant to exit the VM")
 243     private HotSpotJVMCIRuntime() {
 244         compilerToVm = new CompilerToVM();
 245 
 246         try (InitTimer t = timer("HotSpotVMConfig<init>")) {
 247             configStore = new HotSpotVMConfigStore(compilerToVm);
 248             config = new HotSpotVMConfig(configStore);
 249         }
 250 
 251         String hostArchitecture = config.getHostArchitectureName();
 252 
 253         HotSpotJVMCIBackendFactory factory;
 254         try (InitTimer t = timer("find factory:", hostArchitecture)) {
 255             factory = findFactory(hostArchitecture);
 256         }
 257 
 258         try (InitTimer t = timer("create JVMCI backend:", hostArchitecture)) {
 259             hostBackend = registerBackend(factory.createJVMCIBackend(this, null));
 260         }
 261 
 262         metaAccessContext = new HotSpotJVMCIMetaAccessContext();
 263 
 264         boolean printFlags = Option.PrintFlags.getBoolean();
 265         boolean showFlags = Option.ShowFlags.getBoolean();
 266         if (printFlags || showFlags) {
 267             Option.printFlags(System.out);
 268             if (printFlags) {
 269                 System.exit(0);
 270             }
 271         }
 272 
 273         if (Option.PrintConfig.getBoolean()) {
 274             printConfig(configStore, compilerToVm);
 275             System.exit(0);
 276         }
 277 
 278         compilerFactory = HotSpotJVMCICompilerConfig.getCompilerFactory();
 279         if (compilerFactory instanceof HotSpotJVMCICompilerFactory) {
 280             hsCompilerFactory = (HotSpotJVMCICompilerFactory) compilerFactory;
 281             trivialPrefixes = hsCompilerFactory.getTrivialPrefixes();
 282             switch (hsCompilerFactory.getCompilationLevelAdjustment()) {
 283                 case None:
 284                     compilationLevelAdjustment = config.compLevelAdjustmentNone;
 285                     break;
 286                 case ByHolder:
 287                     compilationLevelAdjustment = config.compLevelAdjustmentByHolder;
 288                     break;
 289                 case ByFullSignature:
 290                     compilationLevelAdjustment = config.compLevelAdjustmentByFullSignature;
 291                     break;
 292                 default:
 293                     compilationLevelAdjustment = config.compLevelAdjustmentNone;
 294                     break;
 295             }


 446     @SuppressWarnings({"unused"})
 447     private void bootstrapFinished() throws Exception {
 448         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
 449             vmEventListener.notifyBootstrapFinished();
 450         }
 451     }
 452 
 453     /**
 454      * Notify on successful install into the CodeCache.
 455      *
 456      * @param hotSpotCodeCacheProvider
 457      * @param installedCode
 458      * @param compiledCode
 459      */
 460     void notifyInstall(HotSpotCodeCacheProvider hotSpotCodeCacheProvider, InstalledCode installedCode, CompiledCode compiledCode) {
 461         for (HotSpotVMEventListener vmEventListener : getVmEventListeners()) {
 462             vmEventListener.notifyInstall(hotSpotCodeCacheProvider, installedCode, compiledCode);
 463         }
 464     }
 465 
 466     @SuppressFBWarnings(value = "DM_DEFAULT_ENCODING", justification = "no localization here please!")
 467     private static void printConfigLine(CompilerToVM vm, String format, Object... args) {
 468         String line = String.format(format, args);









 469         byte[] lineBytes = line.getBytes();
 470         vm.writeDebugOutput(lineBytes, 0, lineBytes.length);
 471         vm.flushDebugOutput();








 472     }
 473 
 474     private static void printConfig(HotSpotVMConfigStore store, CompilerToVM vm) {
 475         TreeMap<String, VMField> fields = new TreeMap<>(store.getFields());
 476         for (VMField field : fields.values()) {
 477             if (!field.isStatic()) {
 478                 printConfigLine(vm, "[vmconfig:instance field] %s %s {offset=%d[0x%x]}%n", field.type, field.name, field.offset, field.offset);
 479             } else {
 480                 String value = field.value == null ? "null" : String.format("%d[0x%x]", field.value, field.value);
 481                 printConfigLine(vm, "[vmconfig:static field] %s %s = %s {address=0x%x}%n", field.type, field.name, value, field.address);







 482             }







 483         }
 484         TreeMap<String, VMFlag> flags = new TreeMap<>(store.getFlags());
 485         for (VMFlag flag : flags.values()) {
 486             printConfigLine(vm, "[vmconfig:flag] %s %s = %s%n", flag.type, flag.name, flag.value);

 487         }
 488         TreeMap<String, Long> addresses = new TreeMap<>(store.getAddresses());
 489         for (Map.Entry<String, Long> e : addresses.entrySet()) {
 490             printConfigLine(vm, "[vmconfig:address] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());


 491         }
 492         TreeMap<String, Long> constants = new TreeMap<>(store.getConstants());
 493         for (Map.Entry<String, Long> e : constants.entrySet()) {
 494             printConfigLine(vm, "[vmconfig:constant] %s = %d[0x%x]%n", e.getKey(), e.getValue(), e.getValue());
 495         }
 496         TreeMap<String, Long> typeSizes = new TreeMap<>(store.getTypeSizes());
 497         for (Map.Entry<String, Long> e : typeSizes.entrySet()) {
 498             printConfigLine(vm, "[vmconfig:type size] %s = %d%n", e.getKey(), e.getValue());
 499         }

 500     }
 501 
 502     public OutputStream getLogStream() {
 503         return new OutputStream() {
 504 
 505             @Override
 506             public void write(byte[] b, int off, int len) throws IOException {
 507                 if (b == null) {
 508                     throw new NullPointerException();
 509                 } else if (off < 0 || off > b.length || len < 0 || (off + len) > b.length || (off + len) < 0) {
 510                     throw new IndexOutOfBoundsException();
 511                 } else if (len == 0) {
 512                     return;
 513                 }
 514                 compilerToVm.writeDebugOutput(b, off, len);
 515             }
 516 
 517             @Override
 518             public void write(int b) throws IOException {
 519                 write(new byte[]{(byte) b}, 0, 1);
< prev index next >