1 /* 2 * Copyright (c) 2000, 2017, 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 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 Flag in globals.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 StringTable getStringTable() { 658 if (strings == null) { 659 strings = StringTable.getTheTable(); 660 } 661 return strings; 662 } 663 664 public SystemDictionary getSystemDictionary() { 665 if (dict == null) { 666 dict = new SystemDictionary(); 667 } 668 return dict; 669 } 670 671 public ClassLoaderDataGraph getClassLoaderDataGraph() { 672 if (cldGraph == null) { 673 cldGraph = new ClassLoaderDataGraph(); 674 } 675 return cldGraph; 676 } 677 678 public Threads getThreads() { 679 if (threads == null) { 680 threads = new Threads(); 681 } 682 return threads; 683 } 684 685 public ObjectSynchronizer getObjectSynchronizer() { 686 if (synchronizer == null) { 687 synchronizer = new ObjectSynchronizer(); 688 } 689 return synchronizer; 690 } 691 692 public JNIHandles getJNIHandles() { 693 if (handles == null) { 694 handles = new JNIHandles(); 695 } 696 return handles; 697 } 698 699 public Interpreter getInterpreter() { 700 if (interpreter == null) { 701 interpreter = new Interpreter(); 702 } 703 return interpreter; 704 } 705 706 public StubRoutines getStubRoutines() { 707 if (stubRoutines == null) { 708 stubRoutines = new StubRoutines(); 709 } 710 return stubRoutines; 711 } 712 713 public VMRegImpl getVMRegImplInfo() { 714 if (vmregImpl == null) { 715 vmregImpl = new VMRegImpl(); 716 } 717 return vmregImpl; 718 } 719 720 public Bytes getBytes() { 721 if (bytes == null) { 722 bytes = new Bytes(debugger.getMachineDescription()); 723 } 724 return bytes; 725 } 726 727 /** Returns true if this is a isBigEndian, false otherwise */ 728 public boolean isBigEndian() { 729 return isBigEndian; 730 } 731 732 /** Returns true if JVMTI is supported, false otherwise */ 733 public boolean isJvmtiSupported() { 734 return isJvmtiSupported; 735 } 736 737 /** Returns true if this is a "core" build, false if either C1 or C2 738 is present */ 739 public boolean isCore() { 740 return (!(usingClientCompiler || usingServerCompiler)); 741 } 742 743 /** Returns true if this is a C1 build, false otherwise */ 744 public boolean isClientCompiler() { 745 return usingClientCompiler; 746 } 747 748 /** Returns true if this is a C2 build, false otherwise */ 749 public boolean isServerCompiler() { 750 return usingServerCompiler; 751 } 752 753 /** Returns true if C2 derived pointer table should be used, false otherwise */ 754 public boolean useDerivedPointerTable() { 755 return !disableDerivedPointerTableCheck; 756 } 757 758 /** Returns the code cache; should not be used if is core build */ 759 public CodeCache getCodeCache() { 760 if (Assert.ASSERTS_ENABLED) { 761 Assert.that(!isCore(), "noncore builds only"); 762 } 763 if (codeCache == null) { 764 codeCache = new CodeCache(); 765 } 766 return codeCache; 767 } 768 769 /** Should only be called for C1 builds */ 770 public Runtime1 getRuntime1() { 771 if (Assert.ASSERTS_ENABLED) { 772 Assert.that(isClientCompiler(), "C1 builds only"); 773 } 774 if (runtime1 == null) { 775 runtime1 = new Runtime1(); 776 } 777 return runtime1; 778 } 779 780 /** Test to see whether we're in debugging mode (NOTE: this really 781 should not be tested by this code; currently only used in 782 StackFrameStream) */ 783 public boolean isDebugging() { 784 return (debugger != null); 785 } 786 787 /** This is only used by the debugging (i.e., non-runtime) system */ 788 public JVMDebugger getDebugger() { 789 if (debugger == null) { 790 throw new RuntimeException("Attempt to use debugger in runtime system"); 791 } 792 return debugger; 793 } 794 795 /** Indicates whether a given program counter is in Java code. This 796 includes but is not spanned by the interpreter and code cache. 797 Only used in the debugging system, for implementing 798 JavaThread.currentFrameGuess() on x86. */ 799 public boolean isJavaPCDbg(Address addr) { 800 // FIXME: this is not a complete enough set: must include areas 801 // like vtable stubs 802 return (getInterpreter().contains(addr) || 803 getCodeCache().contains(addr)); 804 } 805 806 /** FIXME: figure out where to stick this */ 807 public int getInvocationEntryBCI() { 808 return invocationEntryBCI; 809 } 810 811 // FIXME: figure out where to stick this 812 public boolean wizardMode() { 813 return true; 814 } 815 816 public ReversePtrs getRevPtrs() { 817 return revPtrs; 818 } 819 820 public void setRevPtrs(ReversePtrs rp) { 821 revPtrs = rp; 822 } 823 824 // returns null, if not available. 825 public String getVMRelease() { 826 return vmRelease; 827 } 828 829 // returns null, if not available. 830 public String getVMInternalInfo() { 831 return vmInternalInfo; 832 } 833 834 public int getReserveForAllocationPrefetch() { 835 return reserveForAllocationPrefetch; 836 } 837 838 public boolean isSharingEnabled() { 839 if (sharingEnabled == null) { 840 Flag flag = getCommandLineFlag("UseSharedSpaces"); 841 sharingEnabled = (flag == null)? Boolean.FALSE : 842 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 843 } 844 return sharingEnabled.booleanValue(); 845 } 846 847 public boolean isCompressedOopsEnabled() { 848 if (compressedOopsEnabled == null) { 849 Flag flag = getCommandLineFlag("UseCompressedOops"); 850 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 851 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 852 } 853 return compressedOopsEnabled.booleanValue(); 854 } 855 856 public boolean isCompressedKlassPointersEnabled() { 857 if (compressedKlassPointersEnabled == null) { 858 Flag flag = getCommandLineFlag("UseCompressedClassPointers"); 859 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: 860 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 861 } 862 return compressedKlassPointersEnabled.booleanValue(); 863 } 864 865 public int getObjectAlignmentInBytes() { 866 if (objectAlignmentInBytes == 0) { 867 Flag flag = getCommandLineFlag("ObjectAlignmentInBytes"); 868 objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getIntx(); 869 } 870 return objectAlignmentInBytes; 871 } 872 873 /** Indicates whether Thread-Local Allocation Buffers are used */ 874 public boolean getUseTLAB() { 875 Flag flag = getCommandLineFlag("UseTLAB"); 876 return (flag == null) ? false: flag.getBool(); 877 } 878 879 public boolean getCommandLineBooleanFlag(String name) { 880 Flag flag = getCommandLineFlag(name); 881 return (flag == null) ? Boolean.FALSE: 882 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 883 } 884 885 // returns null, if not available. 886 public Flag[] getCommandLineFlags() { 887 if (commandLineFlags == null) { 888 readCommandLineFlags(); 889 } 890 891 return commandLineFlags; 892 } 893 894 public Flag getCommandLineFlag(String name) { 895 if (flagsMap == null) { 896 flagsMap = new HashMap(); 897 Flag[] flags = getCommandLineFlags(); 898 for (int i = 0; i < flags.length; i++) { 899 flagsMap.put(flags[i].getName(), flags[i]); 900 } 901 } 902 return (Flag) flagsMap.get(name); 903 } 904 905 private void readCommandLineFlags() { 906 // get command line flags 907 TypeDataBase db = getTypeDataBase(); 908 Type flagType = db.lookupType("Flag"); 909 int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); 910 // NOTE: last flag contains null values. 911 commandLineFlags = new Flag[numFlags - 1]; 912 913 Address flagAddr = flagType.getAddressField("flags").getValue(); 914 915 AddressField typeFld = flagType.getAddressField("_type"); 916 AddressField nameFld = flagType.getAddressField("_name"); 917 AddressField addrFld = flagType.getAddressField("_addr"); 918 CIntField flagsFld = new CIntField(flagType.getCIntegerField("_flags"), 0); 919 920 long flagSize = flagType.getSize(); // sizeof(Flag) 921 922 // NOTE: last flag contains null values. 923 for (int f = 0; f < numFlags - 1; f++) { 924 String type = CStringUtilities.getString(typeFld.getValue(flagAddr)); 925 String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); 926 Address addr = addrFld.getValue(flagAddr); 927 int flags = (int)flagsFld.getValue(flagAddr); 928 commandLineFlags[f] = new Flag(type, name, addr, flags); 929 flagAddr = flagAddr.addOffsetTo(flagSize); 930 } 931 932 // sort flags by name 933 Arrays.sort(commandLineFlags, new Comparator() { 934 public int compare(Object o1, Object o2) { 935 Flag f1 = (Flag) o1; 936 Flag f2 = (Flag) o2; 937 return f1.getName().compareTo(f2.getName()); 938 } 939 }); 940 } 941 942 public String getSystemProperty(String key) { 943 Properties props = getSystemProperties(); 944 return (props != null)? props.getProperty(key) : null; 945 } 946 947 public Properties getSystemProperties() { 948 if (sysProps == null) { 949 readSystemProperties(); 950 } 951 return sysProps; 952 } 953 954 private void readSystemProperties() { 955 final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); 956 systemKls.iterateStaticFields(new DefaultOopVisitor() { 957 ObjectReader objReader = new ObjectReader(); 958 public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { 959 if (field.getID().getName().equals("props")) { 960 try { 961 sysProps = (Properties) objReader.readObject(field.getValue(getObj())); 962 } catch (Exception e) { 963 e.printStackTrace(); 964 } 965 } 966 } 967 }); 968 } 969 }