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