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