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