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