1 /* 2 * Copyright (c) 2000, 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 */ 24 25 package sun.jvm.hotspot.runtime; 26 27 import java.io.*; 28 import java.net.*; 29 import java.util.*; 30 import java.util.regex.*; 31 import sun.jvm.hotspot.code.*; 32 import sun.jvm.hotspot.c1.*; 33 import sun.jvm.hotspot.code.*; 34 import sun.jvm.hotspot.debugger.*; 35 import sun.jvm.hotspot.interpreter.*; 36 import sun.jvm.hotspot.memory.*; 37 import sun.jvm.hotspot.oops.*; 38 import sun.jvm.hotspot.types.*; 39 import sun.jvm.hotspot.utilities.*; 40 import sun.jvm.hotspot.runtime.*; 41 import sun.jvm.hotspot.classfile.*; 42 43 /** <P> This class encapsulates the global state of the VM; the 44 universe, object heap, interpreter, etc. It is a Singleton and 45 must be initialized with a call to initialize() before calling 46 getVM(). </P> 47 48 <P> Many auxiliary classes (i.e., most of the VMObjects) keep 49 needed field offsets in the form of static Field objects. In a 50 debugging system, the VM might be shutdown and re-initialized (on 51 a differently-configured build, i.e., 32- vs. 64-bit), and all old 52 cached state (including fields and field offsets) must be 53 flushed. </P> 54 55 <P> An Observer pattern is used to implement the initialization of 56 such classes. Each such class, in its static initializer, 57 registers an Observer with the VM class via 58 VM.registerVMInitializedObserver(). This Observer is guaranteed to 59 be notified whenever the VM is initialized (or re-initialized). To 60 implement the first-time initialization, the observer is also 61 notified when it registers itself with the VM. (For bootstrapping 62 reasons, this implies that the constructor of VM can not 63 instantiate any such objects, since VM.soleInstance will not have 64 been set yet. This is a bootstrapping issue which may have to be 65 revisited later.) </P> 66 */ 67 68 public class VM { 69 private static VM soleInstance; 70 private static List vmInitializedObservers = new ArrayList(); 71 private List vmResumedObservers = new ArrayList(); 72 private List vmSuspendedObservers = new ArrayList(); 73 private TypeDataBase db; 74 private boolean isBigEndian; 75 /** This is only present if in a debugging system */ 76 private JVMDebugger debugger; 77 private long stackBias; 78 private long logAddressSize; 79 private Universe universe; 80 private ObjectHeap heap; 81 private SymbolTable symbols; 82 private StringTable strings; 83 private SystemDictionary dict; 84 private ClassLoaderDataGraph cldGraph; 85 private Threads threads; 86 private ObjectSynchronizer synchronizer; 87 private JNIHandles handles; 88 private Interpreter interpreter; 89 private StubRoutines stubRoutines; 90 private Bytes bytes; 91 92 /** Flag indicating if JVMTI support is included in the build */ 93 private boolean isJvmtiSupported; 94 /** Flags indicating whether we are attached to a core, C1, or C2 build */ 95 private boolean usingClientCompiler; 96 private boolean usingServerCompiler; 97 /** alignment constants */ 98 private boolean isLP64; 99 private int bytesPerLong; 100 private int bytesPerWord; 101 private int objectAlignmentInBytes; 102 private int minObjAlignmentInBytes; 103 private int logMinObjAlignmentInBytes; 104 private int heapWordSize; 105 private int heapOopSize; 106 private int klassPtrSize; 107 private int oopSize; 108 /** This is only present in a non-core build */ 109 private CodeCache codeCache; 110 /** This is only present in a C1 build */ 111 private Runtime1 runtime1; 112 /** These constants come from globalDefinitions.hpp */ 113 private int invocationEntryBCI; 114 private ReversePtrs revPtrs; 115 private VMRegImpl vmregImpl; 116 private int reserveForAllocationPrefetch; 117 118 // System.getProperties from debuggee VM 119 private Properties sysProps; 120 121 // VM version strings come from Abstract_VM_Version class 122 private String vmRelease; 123 private String vmInternalInfo; 124 125 private Flag[] commandLineFlags; 126 private Map flagsMap; 127 128 private static Type intType; 129 private static Type uintType; 130 private static Type intxType; 131 private static Type uintxType; 132 private static Type sizetType; 133 private static CIntegerType boolType; 134 private Boolean sharingEnabled; 135 private Boolean compressedOopsEnabled; 136 private Boolean compressedKlassPointersEnabled; 137 138 // command line flags supplied to VM - see struct Flag in globals.hpp 139 public static final class Flag { 140 private String type; 141 private String name; 142 private Address addr; 143 private int flags; 144 145 private Flag(String type, String name, Address addr, int flags) { 146 this.type = type; 147 this.name = name; 148 this.addr = addr; 149 this.flags = flags; 150 } 151 152 public String getType() { 153 return type; 154 } 155 156 public String getName() { 157 return name; 158 } 159 160 public Address getAddress() { 161 return addr; 162 } 163 164 public int getOrigin() { 165 return flags & 0xF; // XXX can we get the mask bits from somewhere? 166 } 167 168 public boolean isBool() { 169 return type.equals("bool"); 170 } 171 172 public boolean getBool() { 173 if (Assert.ASSERTS_ENABLED) { 174 Assert.that(isBool(), "not a bool flag!"); 175 } 176 return addr.getCIntegerAt(0, boolType.getSize(), boolType.isUnsigned()) != 0; 177 } 178 179 public boolean isInt() { 180 return type.equals("int"); 181 } 182 183 public long getInt() { 184 if (Assert.ASSERTS_ENABLED) { 185 Assert.that(isInt(), "not an int flag!"); 186 } 187 return addr.getCIntegerAt(0, intType.getSize(), false); 188 } 189 190 public boolean isUInt() { 191 return type.equals("uint"); 192 } 193 194 public long getUInt() { 195 if (Assert.ASSERTS_ENABLED) { 196 Assert.that(isUInt(), "not a uint flag!"); 197 } 198 return addr.getCIntegerAt(0, uintType.getSize(), false); 199 } 200 201 public boolean isIntx() { 202 return type.equals("intx"); 203 } 204 205 public long getIntx() { 206 if (Assert.ASSERTS_ENABLED) { 207 Assert.that(isIntx(), "not an intx flag!"); 208 } 209 return addr.getCIntegerAt(0, intxType.getSize(), false); 210 } 211 212 public boolean isUIntx() { 213 return type.equals("uintx"); 214 } 215 216 public long getUIntx() { 217 if (Assert.ASSERTS_ENABLED) { 218 Assert.that(isUIntx(), "not a uintx flag!"); 219 } 220 return addr.getCIntegerAt(0, uintxType.getSize(), true); 221 } 222 223 public boolean isSizet() { 224 return type.equals("size_t"); 225 } 226 227 public long getSizet() { 228 if (Assert.ASSERTS_ENABLED) { 229 Assert.that(isSizet(), "not a size_t flag!"); 230 } 231 return addr.getCIntegerAt(0, sizetType.getSize(), true); 232 } 233 234 public String getValue() { 235 if (isBool()) { 236 return Boolean.toString(getBool()); 237 } else if (isInt()) { 238 return Long.toString(getInt()); 239 } else if (isUInt()) { 240 return Long.toString(getUInt()); 241 } else if (isIntx()) { 242 return Long.toString(getIntx()); 243 } else if (isUIntx()) { 244 return Long.toString(getUIntx()); 245 } else if (isSizet()) { 246 return Long.toString(getSizet()); 247 } else { 248 return null; 249 } 250 } 251 }; 252 253 private static void checkVMVersion(String vmRelease) { 254 if (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null) { 255 // read sa build version. 256 String versionProp = "sun.jvm.hotspot.runtime.VM.saBuildVersion"; 257 String saVersion = saProps.getProperty(versionProp); 258 if (saVersion == null) 259 throw new RuntimeException("Missing property " + versionProp); 260 261 // Strip nonproduct VM version substring (note: saVersion doesn't have it). 262 String vmVersion = vmRelease.replaceAll("(-fastdebug)|(-debug)|(-jvmg)|(-optimized)|(-profiled)",""); 263 264 if (saVersion.equals(vmVersion)) { 265 // Exact match 266 return; 267 } 268 if (saVersion.indexOf('-') == saVersion.lastIndexOf('-') && 269 vmVersion.indexOf('-') == vmVersion.lastIndexOf('-')) { 270 // Throw exception if different release versions: 271 // <major>.<minor>-b<n> 272 throw new VMVersionMismatchException(saVersion, vmRelease); 273 } else { 274 // Otherwise print warning to allow mismatch not release versions 275 // during development. 276 System.err.println("WARNING: Hotspot VM version " + vmRelease + 277 " does not match with SA version " + saVersion + 278 "." + " You may see unexpected results. "); 279 } 280 } else { 281 System.err.println("WARNING: You have disabled SA and VM version check. You may be " + 282 "using incompatible version of SA and you may see unexpected " + 283 "results."); 284 } 285 } 286 287 private static final boolean disableDerivedPointerTableCheck; 288 private static final Properties saProps; 289 290 static { 291 saProps = new Properties(); 292 URL url = null; 293 try { 294 saProps.load(VM.class.getResourceAsStream("/sa.properties")); 295 } catch (Exception e) { 296 System.err.println("Unable to load properties " + 297 (url == null ? "null" : url.toString()) + 298 ": " + e.getMessage()); 299 } 300 301 disableDerivedPointerTableCheck = System.getProperty("sun.jvm.hotspot.runtime.VM.disableDerivedPointerTableCheck") != null; 302 } 303 304 private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) { 305 this.db = db; 306 this.debugger = debugger; 307 this.isBigEndian = isBigEndian; 308 309 // Note that we don't construct universe, heap, threads, 310 // interpreter, or stubRoutines here (any more). The current 311 // initialization mechanisms require that the VM be completely set 312 // up (i.e., out of its constructor, with soleInstance assigned) 313 // before their static initializers are run. 314 315 if (db.getAddressSize() == 4) { 316 logAddressSize = 2; 317 } else if (db.getAddressSize() == 8) { 318 logAddressSize = 3; 319 } else { 320 throw new RuntimeException("Address size " + db.getAddressSize() + " not yet supported"); 321 } 322 323 // read VM version info 324 try { 325 Type vmVersion = db.lookupType("Abstract_VM_Version"); 326 Address releaseAddr = vmVersion.getAddressField("_s_vm_release").getValue(); 327 vmRelease = CStringUtilities.getString(releaseAddr); 328 Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue(); 329 vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr); 330 331 Type threadLocalAllocBuffer = db.lookupType("ThreadLocalAllocBuffer"); 332 CIntegerType intType = (CIntegerType) db.lookupType("int"); 333 CIntegerField reserveForAllocationPrefetchField = threadLocalAllocBuffer.getCIntegerField("_reserve_for_allocation_prefetch"); 334 reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType); 335 } catch (Exception exp) { 336 throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); 337 } 338 339 checkVMVersion(vmRelease); 340 341 stackBias = db.lookupIntConstant("STACK_BIAS").intValue(); 342 invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue(); 343 344 // We infer the presence of JVMTI from the presence of the InstanceKlass::_breakpoints field. 345 { 346 Type type = db.lookupType("InstanceKlass"); 347 if (type.getField("_breakpoints", false, false) == null) { 348 isJvmtiSupported = false; 349 } else { 350 isJvmtiSupported = true; 351 } 352 } 353 354 // We infer the presence of C1 or C2 from a couple of fields we 355 // already have present in the type database 356 { 357 Type type = db.lookupType("Method"); 358 if (type.getField("_from_compiled_entry", false, false) == null) { 359 // Neither C1 nor C2 is present 360 usingClientCompiler = false; 361 usingServerCompiler = false; 362 } else { 363 // Determine whether C2 is present 364 if (db.lookupType("Matcher", false) != null) { 365 usingServerCompiler = true; 366 } else { 367 usingClientCompiler = true; 368 } 369 } 370 } 371 372 if (debugger != null) { 373 isLP64 = debugger.getMachineDescription().isLP64(); 374 } 375 bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue(); 376 bytesPerWord = db.lookupIntConstant("BytesPerWord").intValue(); 377 heapWordSize = db.lookupIntConstant("HeapWordSize").intValue(); 378 oopSize = db.lookupIntConstant("oopSize").intValue(); 379 380 intType = db.lookupType("int"); 381 uintType = db.lookupType("uint"); 382 intxType = db.lookupType("intx"); 383 uintxType = db.lookupType("uintx"); 384 sizetType = db.lookupType("size_t"); 385 boolType = (CIntegerType) db.lookupType("bool"); 386 387 minObjAlignmentInBytes = getObjectAlignmentInBytes(); 388 if (minObjAlignmentInBytes == 8) { 389 logMinObjAlignmentInBytes = 3; 390 } else if (minObjAlignmentInBytes == 16) { 391 logMinObjAlignmentInBytes = 4; 392 } else { 393 throw new RuntimeException("Object alignment " + minObjAlignmentInBytes + " not yet supported"); 394 } 395 396 if (isCompressedOopsEnabled()) { 397 // Size info for oops within java objects is fixed 398 heapOopSize = (int)getIntSize(); 399 } else { 400 heapOopSize = (int)getOopSize(); 401 } 402 403 if (isCompressedKlassPointersEnabled()) { 404 klassPtrSize = (int)getIntSize(); 405 } else { 406 klassPtrSize = (int)getOopSize(); // same as an oop 407 } 408 } 409 410 /** This could be used by a reflective runtime system */ 411 public static void initialize(TypeDataBase db, boolean isBigEndian) { 412 if (soleInstance != null) { 413 throw new RuntimeException("Attempt to initialize VM twice"); 414 } 415 soleInstance = new VM(db, null, isBigEndian); 416 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 417 ((Observer) iter.next()).update(null, null); 418 } 419 } 420 421 /** This is used by the debugging system */ 422 public static void initialize(TypeDataBase db, JVMDebugger debugger) { 423 if (soleInstance != null) { 424 // Using multiple SA Tool classes in the same process creates a call here. 425 return; 426 } 427 soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); 428 429 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 430 ((Observer) iter.next()).update(null, null); 431 } 432 433 debugger.putHeapConst(soleInstance.getHeapOopSize(), soleInstance.getKlassPtrSize(), 434 Universe.getNarrowOopBase(), Universe.getNarrowOopShift(), 435 Universe.getNarrowKlassBase(), Universe.getNarrowKlassShift()); 436 } 437 438 /** This is used by the debugging system */ 439 public static void shutdown() { 440 soleInstance = null; 441 } 442 443 /** This is used by both the debugger and any runtime system. It is 444 the basic mechanism by which classes which mimic underlying VM 445 functionality cause themselves to be initialized. The given 446 observer will be notified (with arguments (null, null)) when the 447 VM is re-initialized, as well as when it registers itself with 448 the VM. */ 449 public static void registerVMInitializedObserver(Observer o) { 450 vmInitializedObservers.add(o); 451 o.update(null, null); 452 } 453 454 /** This is the primary accessor used by both the debugger and any 455 potential runtime system */ 456 public static VM getVM() { 457 if (soleInstance == null) { 458 throw new RuntimeException("VM.initialize() was not yet called"); 459 } 460 return soleInstance; 461 } 462 463 /** This is only used by the debugging system. The given observer 464 will be notified if the underlying VM resumes execution. NOTE 465 that the given observer is not triggered if the VM is currently 466 running and therefore differs in behavior from {@link 467 #registerVMInitializedObserver} (because of the possibility of 468 race conditions if the observer is added while the VM is being 469 suspended or resumed). */ 470 public void registerVMResumedObserver(Observer o) { 471 vmResumedObservers.add(o); 472 } 473 474 /** This is only used by the debugging system. The given observer 475 will be notified if the underlying VM suspends execution. NOTE 476 that the given observer is not triggered if the VM is currently 477 suspended and therefore differs in behavior from {@link 478 #registerVMInitializedObserver} (because of the possibility of 479 race conditions if the observer is added while the VM is being 480 suspended or resumed). */ 481 public void registerVMSuspendedObserver(Observer o) { 482 vmSuspendedObservers.add(o); 483 } 484 485 /** This is only used by the debugging system. Informs all 486 registered resumption observers that the VM has been resumed. 487 The application is responsible for actually having performed the 488 resumption. No OopHandles must be used after this point, as they 489 may move in the target address space due to garbage 490 collection. */ 491 public void fireVMResumed() { 492 for (Iterator iter = vmResumedObservers.iterator(); iter.hasNext(); ) { 493 ((Observer) iter.next()).update(null, null); 494 } 495 } 496 497 /** This is only used by the debugging system. Informs all 498 registered suspension observers that the VM has been suspended. 499 The application is responsible for actually having performed the 500 suspension. Garbage collection must be forbidden at this point; 501 for example, a JPDA-level suspension is not adequate since the 502 VM thread may still be running. */ 503 public void fireVMSuspended() { 504 for (Iterator iter = vmSuspendedObservers.iterator(); iter.hasNext(); ) { 505 ((Observer) iter.next()).update(null, null); 506 } 507 } 508 509 /** Returns the OS this VM is running on. Notice that by delegating 510 to the debugger we can transparently support remote 511 debugging. */ 512 public String getOS() { 513 if (debugger != null) { 514 return debugger.getOS(); 515 } 516 return PlatformInfo.getOS(); 517 } 518 519 /** Returns the CPU this VM is running on. Notice that by delegating 520 to the debugger we can transparently support remote 521 debugging. */ 522 public String getCPU() { 523 if (debugger != null) { 524 return debugger.getCPU(); 525 } 526 return PlatformInfo.getCPU(); 527 } 528 529 public Type lookupType(String cTypeName) { 530 return db.lookupType(cTypeName); 531 } 532 533 public Integer lookupIntConstant(String name) { 534 return db.lookupIntConstant(name); 535 } 536 537 // Convenience function for conversions 538 static public long getAddressValue(Address addr) { 539 return VM.getVM().getDebugger().getAddressValue(addr); 540 } 541 542 public long getAddressSize() { 543 return db.getAddressSize(); 544 } 545 546 public long getOopSize() { 547 return oopSize; 548 } 549 550 public long getLogAddressSize() { 551 return logAddressSize; 552 } 553 554 public long getIntSize() { 555 return db.getJIntType().getSize(); 556 } 557 558 /** NOTE: this offset is in BYTES in this system! */ 559 public long getStackBias() { 560 return stackBias; 561 } 562 563 /** Indicates whether the underlying machine supports the LP64 data 564 model. This is needed for conditionalizing code in a few places */ 565 public boolean isLP64() { 566 if (Assert.ASSERTS_ENABLED) { 567 Assert.that(isDebugging(), "Debugging system only for now"); 568 } 569 return isLP64; 570 } 571 572 /** Get bytes-per-long == long/double natural alignment. */ 573 public int getBytesPerLong() { 574 return bytesPerLong; 575 } 576 577 public int getBytesPerWord() { 578 return bytesPerWord; 579 } 580 581 /** Get minimum object alignment in bytes. */ 582 public int getMinObjAlignmentInBytes() { 583 return minObjAlignmentInBytes; 584 } 585 public int getLogMinObjAlignmentInBytes() { 586 return logMinObjAlignmentInBytes; 587 } 588 589 public int getHeapWordSize() { 590 return heapWordSize; 591 } 592 593 public int getHeapOopSize() { 594 return heapOopSize; 595 } 596 597 public int getKlassPtrSize() { 598 return klassPtrSize; 599 } 600 /** Utility routine for getting data structure alignment correct */ 601 public long alignUp(long size, long alignment) { 602 return (size + alignment - 1) & ~(alignment - 1); 603 } 604 605 /** Utility routine for getting data structure alignment correct */ 606 public long alignDown(long size, long alignment) { 607 return size & ~(alignment - 1); 608 } 609 610 /** Utility routine for building an int from two "unsigned" 16-bit 611 shorts */ 612 public int buildIntFromShorts(short low, short high) { 613 return (((int) high) << 16) | (((int) low) & 0xFFFF); 614 } 615 616 /** Utility routine for building a long from two "unsigned" 32-bit 617 ints in <b>platform-dependent</b> order */ 618 public long buildLongFromIntsPD(int oneHalf, int otherHalf) { 619 if (isBigEndian) { 620 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL); 621 } else{ 622 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL); 623 } 624 } 625 626 public TypeDataBase getTypeDataBase() { 627 return db; 628 } 629 630 public Universe getUniverse() { 631 if (universe == null) { 632 universe = new Universe(); 633 } 634 return universe; 635 } 636 637 public ObjectHeap getObjectHeap() { 638 if (heap == null) { 639 heap = new ObjectHeap(db); 640 } 641 return heap; 642 } 643 644 public SymbolTable getSymbolTable() { 645 if (symbols == null) { 646 symbols = SymbolTable.getTheTable(); 647 } 648 return symbols; 649 } 650 651 public StringTable getStringTable() { 652 if (strings == null) { 653 strings = StringTable.getTheTable(); 654 } 655 return strings; 656 } 657 658 public SystemDictionary getSystemDictionary() { 659 if (dict == null) { 660 dict = new SystemDictionary(); 661 } 662 return dict; 663 } 664 665 public ClassLoaderDataGraph getClassLoaderDataGraph() { 666 if (cldGraph == null) { 667 cldGraph = new ClassLoaderDataGraph(); 668 } 669 return cldGraph; 670 } 671 672 public Threads getThreads() { 673 if (threads == null) { 674 threads = new Threads(); 675 } 676 return threads; 677 } 678 679 public ObjectSynchronizer getObjectSynchronizer() { 680 if (synchronizer == null) { 681 synchronizer = new ObjectSynchronizer(); 682 } 683 return synchronizer; 684 } 685 686 public JNIHandles getJNIHandles() { 687 if (handles == null) { 688 handles = new JNIHandles(); 689 } 690 return handles; 691 } 692 693 public Interpreter getInterpreter() { 694 if (interpreter == null) { 695 interpreter = new Interpreter(); 696 } 697 return interpreter; 698 } 699 700 public StubRoutines getStubRoutines() { 701 if (stubRoutines == null) { 702 stubRoutines = new StubRoutines(); 703 } 704 return stubRoutines; 705 } 706 707 public VMRegImpl getVMRegImplInfo() { 708 if (vmregImpl == null) { 709 vmregImpl = new VMRegImpl(); 710 } 711 return vmregImpl; 712 } 713 714 public Bytes getBytes() { 715 if (bytes == null) { 716 bytes = new Bytes(debugger.getMachineDescription()); 717 } 718 return bytes; 719 } 720 721 /** Returns true if this is a isBigEndian, false otherwise */ 722 public boolean isBigEndian() { 723 return isBigEndian; 724 } 725 726 /** Returns true if JVMTI is supported, false otherwise */ 727 public boolean isJvmtiSupported() { 728 return isJvmtiSupported; 729 } 730 731 /** Returns true if this is a "core" build, false if either C1 or C2 732 is present */ 733 public boolean isCore() { 734 return (!(usingClientCompiler || usingServerCompiler)); 735 } 736 737 /** Returns true if this is a C1 build, false otherwise */ 738 public boolean isClientCompiler() { 739 return usingClientCompiler; 740 } 741 742 /** Returns true if this is a C2 build, false otherwise */ 743 public boolean isServerCompiler() { 744 return usingServerCompiler; 745 } 746 747 /** Returns true if C2 derived pointer table should be used, false otherwise */ 748 public boolean useDerivedPointerTable() { 749 return !disableDerivedPointerTableCheck; 750 } 751 752 /** Returns the code cache; should not be used if is core build */ 753 public CodeCache getCodeCache() { 754 if (Assert.ASSERTS_ENABLED) { 755 Assert.that(!isCore(), "noncore builds only"); 756 } 757 if (codeCache == null) { 758 codeCache = new CodeCache(); 759 } 760 return codeCache; 761 } 762 763 /** Should only be called for C1 builds */ 764 public Runtime1 getRuntime1() { 765 if (Assert.ASSERTS_ENABLED) { 766 Assert.that(isClientCompiler(), "C1 builds only"); 767 } 768 if (runtime1 == null) { 769 runtime1 = new Runtime1(); 770 } 771 return runtime1; 772 } 773 774 /** Test to see whether we're in debugging mode (NOTE: this really 775 should not be tested by this code; currently only used in 776 StackFrameStream) */ 777 public boolean isDebugging() { 778 return (debugger != null); 779 } 780 781 /** This is only used by the debugging (i.e., non-runtime) system */ 782 public JVMDebugger getDebugger() { 783 if (debugger == null) { 784 throw new RuntimeException("Attempt to use debugger in runtime system"); 785 } 786 return debugger; 787 } 788 789 /** Indicates whether a given program counter is in Java code. This 790 includes but is not spanned by the interpreter and code cache. 791 Only used in the debugging system, for implementing 792 JavaThread.currentFrameGuess() on x86. */ 793 public boolean isJavaPCDbg(Address addr) { 794 // FIXME: this is not a complete enough set: must include areas 795 // like vtable stubs 796 return (getInterpreter().contains(addr) || 797 getCodeCache().contains(addr)); 798 } 799 800 /** FIXME: figure out where to stick this */ 801 public int getInvocationEntryBCI() { 802 return invocationEntryBCI; 803 } 804 805 // FIXME: figure out where to stick this 806 public boolean wizardMode() { 807 return true; 808 } 809 810 public ReversePtrs getRevPtrs() { 811 return revPtrs; 812 } 813 814 public void setRevPtrs(ReversePtrs rp) { 815 revPtrs = rp; 816 } 817 818 // returns null, if not available. 819 public String getVMRelease() { 820 return vmRelease; 821 } 822 823 // returns null, if not available. 824 public String getVMInternalInfo() { 825 return vmInternalInfo; 826 } 827 828 public int getReserveForAllocationPrefetch() { 829 return reserveForAllocationPrefetch; 830 } 831 832 public boolean isSharingEnabled() { 833 if (sharingEnabled == null) { 834 Flag flag = getCommandLineFlag("UseSharedSpaces"); 835 sharingEnabled = (flag == null)? Boolean.FALSE : 836 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 837 } 838 return sharingEnabled.booleanValue(); 839 } 840 841 public boolean isCompressedOopsEnabled() { 842 if (compressedOopsEnabled == null) { 843 Flag flag = getCommandLineFlag("UseCompressedOops"); 844 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 845 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 846 } 847 return compressedOopsEnabled.booleanValue(); 848 } 849 850 public boolean isCompressedKlassPointersEnabled() { 851 if (compressedKlassPointersEnabled == null) { 852 Flag flag = getCommandLineFlag("UseCompressedClassPointers"); 853 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: 854 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 855 } 856 return compressedKlassPointersEnabled.booleanValue(); 857 } 858 859 public int getObjectAlignmentInBytes() { 860 if (objectAlignmentInBytes == 0) { 861 Flag flag = getCommandLineFlag("ObjectAlignmentInBytes"); 862 objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getIntx(); 863 } 864 return objectAlignmentInBytes; 865 } 866 867 /** Indicates whether Thread-Local Allocation Buffers are used */ 868 public boolean getUseTLAB() { 869 Flag flag = getCommandLineFlag("UseTLAB"); 870 return (flag == null) ? false: flag.getBool(); 871 } 872 873 public boolean getCommandLineBooleanFlag(String name) { 874 Flag flag = getCommandLineFlag(name); 875 return (flag == null) ? Boolean.FALSE: 876 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 877 } 878 879 // returns null, if not available. 880 public Flag[] getCommandLineFlags() { 881 if (commandLineFlags == null) { 882 readCommandLineFlags(); 883 } 884 885 return commandLineFlags; 886 } 887 888 public Flag getCommandLineFlag(String name) { 889 if (flagsMap == null) { 890 flagsMap = new HashMap(); 891 Flag[] flags = getCommandLineFlags(); 892 for (int i = 0; i < flags.length; i++) { 893 flagsMap.put(flags[i].getName(), flags[i]); 894 } 895 } 896 return (Flag) flagsMap.get(name); 897 } 898 899 private void readCommandLineFlags() { 900 // get command line flags 901 TypeDataBase db = getTypeDataBase(); 902 Type flagType = db.lookupType("Flag"); 903 int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); 904 // NOTE: last flag contains null values. 905 commandLineFlags = new Flag[numFlags - 1]; 906 907 Address flagAddr = flagType.getAddressField("flags").getValue(); 908 909 AddressField typeFld = flagType.getAddressField("_type"); 910 AddressField nameFld = flagType.getAddressField("_name"); 911 AddressField addrFld = flagType.getAddressField("_addr"); 912 CIntField flagsFld = new CIntField(flagType.getCIntegerField("_flags"), 0); 913 914 long flagSize = flagType.getSize(); // sizeof(Flag) 915 916 // NOTE: last flag contains null values. 917 for (int f = 0; f < numFlags - 1; f++) { 918 String type = CStringUtilities.getString(typeFld.getValue(flagAddr)); 919 String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); 920 Address addr = addrFld.getValue(flagAddr); 921 int flags = (int)flagsFld.getValue(flagAddr); 922 commandLineFlags[f] = new Flag(type, name, addr, flags); 923 flagAddr = flagAddr.addOffsetTo(flagSize); 924 } 925 926 // sort flags by name 927 Arrays.sort(commandLineFlags, new Comparator() { 928 public int compare(Object o1, Object o2) { 929 Flag f1 = (Flag) o1; 930 Flag f2 = (Flag) o2; 931 return f1.getName().compareTo(f2.getName()); 932 } 933 }); 934 } 935 936 public String getSystemProperty(String key) { 937 Properties props = getSystemProperties(); 938 return (props != null)? props.getProperty(key) : null; 939 } 940 941 public Properties getSystemProperties() { 942 if (sysProps == null) { 943 readSystemProperties(); 944 } 945 return sysProps; 946 } 947 948 private void readSystemProperties() { 949 final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); 950 systemKls.iterateStaticFields(new DefaultOopVisitor() { 951 ObjectReader objReader = new ObjectReader(); 952 public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { 953 if (field.getID().getName().equals("props")) { 954 try { 955 sysProps = (Properties) objReader.readObject(field.getValue(getObj())); 956 } catch (Exception e) { 957 e.printStackTrace(); 958 } 959 } 960 } 961 }); 962 } 963 }