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