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