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 /** 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 int invalidOSREntryBCI; 111 private ReversePtrs revPtrs; 112 private VMRegImpl vmregImpl; 113 private int reserveForAllocationPrefetch; 114 115 // System.getProperties from debuggee VM 116 private Properties sysProps; 117 118 // VM version strings come from Abstract_VM_Version class 119 private String vmRelease; 120 private String vmInternalInfo; 121 122 private Flag[] commandLineFlags; 123 private Map flagsMap; 124 125 private static Type intxType; 126 private static Type uintxType; 127 private static CIntegerType boolType; 128 private Boolean sharingEnabled; 129 private Boolean compressedOopsEnabled; 130 private Boolean compressedKlassPointersEnabled; 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 disableDerivedPointerTableCheck; 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 System.err.println("Unable to load properties " + 260 (url == null ? "null" : url.toString()) + 261 ": " + e.getMessage()); 262 } 263 264 disableDerivedPointerTableCheck = 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 294 CIntegerType intType = (CIntegerType) db.lookupType("int"); 295 CIntegerField reserveForAllocationPrefetchField = vmVersion.getCIntegerField("_reserve_for_allocation_prefetch"); 296 reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType); 297 } catch (Exception exp) { 298 throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); 299 } 300 301 checkVMVersion(vmRelease); 302 303 stackBias = db.lookupIntConstant("STACK_BIAS").intValue(); 304 invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue(); 305 invalidOSREntryBCI = db.lookupIntConstant("InvalidOSREntryBci").intValue(); 306 307 // We infer the presence of C1 or C2 from a couple of fields we 308 // already have present in the type database 309 { 310 Type type = db.lookupType("Method"); 311 if (type.getField("_from_compiled_entry", false, false) == null) { 312 // Neither C1 nor C2 is present 313 usingClientCompiler = false; 314 usingServerCompiler = false; 315 } else { 316 // Determine whether C2 is present 317 if (db.lookupType("Matcher", false) != null) { 318 usingServerCompiler = true; 319 } else { 320 usingClientCompiler = true; 321 } 322 } 323 } 324 325 if (debugger != null) { 326 isLP64 = debugger.getMachineDescription().isLP64(); 327 } 328 bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue(); 329 bytesPerWord = db.lookupIntConstant("BytesPerWord").intValue(); 330 heapWordSize = db.lookupIntConstant("HeapWordSize").intValue(); 331 oopSize = db.lookupIntConstant("oopSize").intValue(); 332 333 intxType = db.lookupType("intx"); 334 uintxType = db.lookupType("uintx"); 335 boolType = (CIntegerType) db.lookupType("bool"); 336 337 minObjAlignmentInBytes = getObjectAlignmentInBytes(); 338 if (minObjAlignmentInBytes == 8) { 339 logMinObjAlignmentInBytes = 3; 340 } else if (minObjAlignmentInBytes == 16) { 341 logMinObjAlignmentInBytes = 4; 342 } else { 343 throw new RuntimeException("Object alignment " + minObjAlignmentInBytes + " not yet supported"); 344 } 345 346 if (isCompressedOopsEnabled()) { 347 // Size info for oops within java objects is fixed 348 heapOopSize = (int)getIntSize(); 349 } else { 350 heapOopSize = (int)getOopSize(); 351 } 352 353 if (isCompressedKlassPointersEnabled()) { 354 klassPtrSize = (int)getIntSize(); 355 } else { 356 klassPtrSize = (int)getOopSize(); // same as an oop 357 } 358 } 359 360 /** This could be used by a reflective runtime system */ 361 public static void initialize(TypeDataBase db, boolean isBigEndian) { 362 if (soleInstance != null) { 363 throw new RuntimeException("Attempt to initialize VM twice"); 364 } 365 soleInstance = new VM(db, null, isBigEndian); 366 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 367 ((Observer) iter.next()).update(null, null); 368 } 369 } 370 371 /** This is used by the debugging system */ 372 public static void initialize(TypeDataBase db, JVMDebugger debugger) { 373 if (soleInstance != null) { 374 // Using multiple SA Tool classes in the same process creates a call here. 375 return; 376 } 377 soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); 378 379 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 380 ((Observer) iter.next()).update(null, null); 381 } 382 383 debugger.putHeapConst(soleInstance.getHeapOopSize(), soleInstance.getKlassPtrSize(), 384 Universe.getNarrowOopBase(), Universe.getNarrowOopShift(), 385 Universe.getNarrowKlassBase(), Universe.getNarrowKlassShift()); 386 } 387 388 /** This is used by the debugging system */ 389 public static void shutdown() { 390 soleInstance = null; 391 } 392 393 /** This is used by both the debugger and any runtime system. It is 394 the basic mechanism by which classes which mimic underlying VM 395 functionality cause themselves to be initialized. The given 396 observer will be notified (with arguments (null, null)) when the 397 VM is re-initialized, as well as when it registers itself with 398 the VM. */ 399 public static void registerVMInitializedObserver(Observer o) { 400 vmInitializedObservers.add(o); 401 o.update(null, null); 402 } 403 404 /** This is the primary accessor used by both the debugger and any 405 potential runtime system */ 406 public static VM getVM() { 407 if (soleInstance == null) { 408 throw new RuntimeException("VM.initialize() was not yet called"); 409 } 410 return soleInstance; 411 } 412 413 /** This is only used by the debugging system. The given observer 414 will be notified if the underlying VM resumes execution. NOTE 415 that the given observer is not triggered if the VM is currently 416 running 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 registerVMResumedObserver(Observer o) { 421 vmResumedObservers.add(o); 422 } 423 424 /** This is only used by the debugging system. The given observer 425 will be notified if the underlying VM suspends execution. NOTE 426 that the given observer is not triggered if the VM is currently 427 suspended and therefore differs in behavior from {@link 428 #registerVMInitializedObserver} (because of the possibility of 429 race conditions if the observer is added while the VM is being 430 suspended or resumed). */ 431 public void registerVMSuspendedObserver(Observer o) { 432 vmSuspendedObservers.add(o); 433 } 434 435 /** This is only used by the debugging system. Informs all 436 registered resumption observers that the VM has been resumed. 437 The application is responsible for actually having performed the 438 resumption. No OopHandles must be used after this point, as they 439 may move in the target address space due to garbage 440 collection. */ 441 public void fireVMResumed() { 442 for (Iterator iter = vmResumedObservers.iterator(); iter.hasNext(); ) { 443 ((Observer) iter.next()).update(null, null); 444 } 445 } 446 447 /** This is only used by the debugging system. Informs all 448 registered suspension observers that the VM has been suspended. 449 The application is responsible for actually having performed the 450 suspension. Garbage collection must be forbidden at this point; 451 for example, a JPDA-level suspension is not adequate since the 452 VM thread may still be running. */ 453 public void fireVMSuspended() { 454 for (Iterator iter = vmSuspendedObservers.iterator(); iter.hasNext(); ) { 455 ((Observer) iter.next()).update(null, null); 456 } 457 } 458 459 /** Returns the OS this VM is running on. Notice that by delegating 460 to the debugger we can transparently support remote 461 debugging. */ 462 public String getOS() { 463 if (debugger != null) { 464 return debugger.getOS(); 465 } 466 return PlatformInfo.getOS(); 467 } 468 469 /** Returns the CPU this VM is running on. Notice that by delegating 470 to the debugger we can transparently support remote 471 debugging. */ 472 public String getCPU() { 473 if (debugger != null) { 474 return debugger.getCPU(); 475 } 476 return PlatformInfo.getCPU(); 477 } 478 479 public Type lookupType(String cTypeName) { 480 return db.lookupType(cTypeName); 481 } 482 483 public Integer lookupIntConstant(String name) { 484 return db.lookupIntConstant(name); 485 } 486 487 // Convenience function for conversions 488 static public long getAddressValue(Address addr) { 489 return VM.getVM().getDebugger().getAddressValue(addr); 490 } 491 492 public long getAddressSize() { 493 return db.getAddressSize(); 494 } 495 496 public long getOopSize() { 497 return oopSize; 498 } 499 500 public long getLogAddressSize() { 501 return logAddressSize; 502 } 503 504 public long getIntSize() { 505 return db.getJIntType().getSize(); 506 } 507 508 /** NOTE: this offset is in BYTES in this system! */ 509 public long getStackBias() { 510 return stackBias; 511 } 512 513 /** Indicates whether the underlying machine supports the LP64 data 514 model. This is needed for conditionalizing code in a few places */ 515 public boolean isLP64() { 516 if (Assert.ASSERTS_ENABLED) { 517 Assert.that(isDebugging(), "Debugging system only for now"); 518 } 519 return isLP64; 520 } 521 522 /** Get bytes-per-long == long/double natural alignment. */ 523 public int getBytesPerLong() { 524 return bytesPerLong; 525 } 526 527 public int getBytesPerWord() { 528 return bytesPerWord; 529 } 530 531 /** Get minimum object alignment in bytes. */ 532 public int getMinObjAlignmentInBytes() { 533 return minObjAlignmentInBytes; 534 } 535 public int getLogMinObjAlignmentInBytes() { 536 return logMinObjAlignmentInBytes; 537 } 538 539 public int getHeapWordSize() { 540 return heapWordSize; 541 } 542 543 public int getHeapOopSize() { 544 return heapOopSize; 545 } 546 547 public int getKlassPtrSize() { 548 return klassPtrSize; 549 } 550 /** Utility routine for getting data structure alignment correct */ 551 public long alignUp(long size, long alignment) { 552 return (size + alignment - 1) & ~(alignment - 1); 553 } 554 555 /** Utility routine for getting data structure alignment correct */ 556 public long alignDown(long size, long alignment) { 557 return size & ~(alignment - 1); 558 } 559 560 /** Utility routine for building an int from two "unsigned" 16-bit 561 shorts */ 562 public int buildIntFromShorts(short low, short high) { 563 return (((int) high) << 16) | (((int) low) & 0xFFFF); 564 } 565 566 /** Utility routine for building a long from two "unsigned" 32-bit 567 ints in <b>platform-dependent</b> order */ 568 public long buildLongFromIntsPD(int oneHalf, int otherHalf) { 569 if (isBigEndian) { 570 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL); 571 } else{ 572 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL); 573 } 574 } 575 576 public TypeDataBase getTypeDataBase() { 577 return db; 578 } 579 580 public Universe getUniverse() { 581 if (universe == null) { 582 universe = new Universe(); 583 } 584 return universe; 585 } 586 587 public ObjectHeap getObjectHeap() { 588 if (heap == null) { 589 heap = new ObjectHeap(db); 590 } 591 return heap; 592 } 593 594 public SymbolTable getSymbolTable() { 595 if (symbols == null) { 596 symbols = SymbolTable.getTheTable(); 597 } 598 return symbols; 599 } 600 601 public StringTable getStringTable() { 602 if (strings == null) { 603 strings = StringTable.getTheTable(); 604 } 605 return strings; 606 } 607 608 public SystemDictionary getSystemDictionary() { 609 if (dict == null) { 610 dict = new SystemDictionary(); 611 } 612 return dict; 613 } 614 615 public Threads getThreads() { 616 if (threads == null) { 617 threads = new Threads(); 618 } 619 return threads; 620 } 621 622 public ObjectSynchronizer getObjectSynchronizer() { 623 if (synchronizer == null) { 624 synchronizer = new ObjectSynchronizer(); 625 } 626 return synchronizer; 627 } 628 629 public JNIHandles getJNIHandles() { 630 if (handles == null) { 631 handles = new JNIHandles(); 632 } 633 return handles; 634 } 635 636 public Interpreter getInterpreter() { 637 if (interpreter == null) { 638 interpreter = new Interpreter(); 639 } 640 return interpreter; 641 } 642 643 public StubRoutines getStubRoutines() { 644 if (stubRoutines == null) { 645 stubRoutines = new StubRoutines(); 646 } 647 return stubRoutines; 648 } 649 650 public VMRegImpl getVMRegImplInfo() { 651 if (vmregImpl == null) { 652 vmregImpl = new VMRegImpl(); 653 } 654 return vmregImpl; 655 } 656 657 public Bytes getBytes() { 658 if (bytes == null) { 659 bytes = new Bytes(debugger.getMachineDescription()); 660 } 661 return bytes; 662 } 663 664 /** Returns true if this is a isBigEndian, false otherwise */ 665 public boolean isBigEndian() { 666 return isBigEndian; 667 } 668 669 /** Returns true if this is a "core" build, false if either C1 or C2 670 is present */ 671 public boolean isCore() { 672 return (!(usingClientCompiler || usingServerCompiler)); 673 } 674 675 /** Returns true if this is a C1 build, false otherwise */ 676 public boolean isClientCompiler() { 677 return usingClientCompiler; 678 } 679 680 /** Returns true if this is a C2 build, false otherwise */ 681 public boolean isServerCompiler() { 682 return usingServerCompiler; 683 } 684 685 /** Returns true if C2 derived pointer table should be used, false otherwise */ 686 public boolean useDerivedPointerTable() { 687 return !disableDerivedPointerTableCheck; 688 } 689 690 /** Returns the code cache; should not be used if is core build */ 691 public CodeCache getCodeCache() { 692 if (Assert.ASSERTS_ENABLED) { 693 Assert.that(!isCore(), "noncore builds only"); 694 } 695 if (codeCache == null) { 696 codeCache = new CodeCache(); 697 } 698 return codeCache; 699 } 700 701 /** Should only be called for C1 builds */ 702 public Runtime1 getRuntime1() { 703 if (Assert.ASSERTS_ENABLED) { 704 Assert.that(isClientCompiler(), "C1 builds only"); 705 } 706 if (runtime1 == null) { 707 runtime1 = new Runtime1(); 708 } 709 return runtime1; 710 } 711 712 /** Test to see whether we're in debugging mode (NOTE: this really 713 should not be tested by this code; currently only used in 714 StackFrameStream) */ 715 public boolean isDebugging() { 716 return (debugger != null); 717 } 718 719 /** This is only used by the debugging (i.e., non-runtime) system */ 720 public JVMDebugger getDebugger() { 721 if (debugger == null) { 722 throw new RuntimeException("Attempt to use debugger in runtime system"); 723 } 724 return debugger; 725 } 726 727 /** Indicates whether a given program counter is in Java code. This 728 includes but is not spanned by the interpreter and code cache. 729 Only used in the debugging system, for implementing 730 JavaThread.currentFrameGuess() on x86. */ 731 public boolean isJavaPCDbg(Address addr) { 732 // FIXME: this is not a complete enough set: must include areas 733 // like vtable stubs 734 return (getInterpreter().contains(addr) || 735 getCodeCache().contains(addr)); 736 } 737 738 /** FIXME: figure out where to stick this */ 739 public int getInvocationEntryBCI() { 740 return invocationEntryBCI; 741 } 742 743 /** FIXME: figure out where to stick this */ 744 public int getInvalidOSREntryBCI() { 745 return invalidOSREntryBCI; 746 } 747 748 // FIXME: figure out where to stick this 749 public boolean wizardMode() { 750 return true; 751 } 752 753 public ReversePtrs getRevPtrs() { 754 return revPtrs; 755 } 756 757 public void setRevPtrs(ReversePtrs rp) { 758 revPtrs = rp; 759 } 760 761 // returns null, if not available. 762 public String getVMRelease() { 763 return vmRelease; 764 } 765 766 // returns null, if not available. 767 public String getVMInternalInfo() { 768 return vmInternalInfo; 769 } 770 771 public int getReserveForAllocationPrefetch() { 772 return reserveForAllocationPrefetch; 773 } 774 775 public boolean isSharingEnabled() { 776 if (sharingEnabled == null) { 777 Flag flag = getCommandLineFlag("UseSharedSpaces"); 778 sharingEnabled = (flag == null)? Boolean.FALSE : 779 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 780 } 781 return sharingEnabled.booleanValue(); 782 } 783 784 public boolean isCompressedOopsEnabled() { 785 if (compressedOopsEnabled == null) { 786 Flag flag = getCommandLineFlag("UseCompressedOops"); 787 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 788 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 789 } 790 return compressedOopsEnabled.booleanValue(); 791 } 792 793 public boolean isCompressedKlassPointersEnabled() { 794 if (compressedKlassPointersEnabled == null) { 795 Flag flag = getCommandLineFlag("UseCompressedKlassPointers"); 796 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: 797 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 798 } 799 return compressedKlassPointersEnabled.booleanValue(); 800 } 801 802 public int getObjectAlignmentInBytes() { 803 if (objectAlignmentInBytes == 0) { 804 Flag flag = getCommandLineFlag("ObjectAlignmentInBytes"); 805 objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getIntx(); 806 } 807 return objectAlignmentInBytes; 808 } 809 810 /** Indicates whether Thread-Local Allocation Buffers are used */ 811 public boolean getUseTLAB() { 812 Flag flag = getCommandLineFlag("UseTLAB"); 813 return (flag == null) ? false: flag.getBool(); 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 }