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