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 Type threadLocalAllocBuffer = db.lookupType("ThreadLocalAllocBuffer"); 328 CIntegerType intType = (CIntegerType) db.lookupType("int"); 329 CIntegerField reserveForAllocationPrefetchField = threadLocalAllocBuffer.getCIntegerField("_reserve_for_allocation_prefetch"); 330 reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType); 331 } catch (Exception exp) { 332 throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); 333 } 334 335 checkVMVersion(vmRelease); 336 337 stackBias = db.lookupIntConstant("STACK_BIAS").intValue(); 338 invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue(); 339 340 // We infer the presence of C1 or C2 from a couple of fields we 341 // already have present in the type database 342 { 343 Type type = db.lookupType("Method"); 344 if (type.getField("_from_compiled_entry", false, false) == null) { 345 // Neither C1 nor C2 is present 346 usingClientCompiler = false; 347 usingServerCompiler = false; 348 } else { 349 // Determine whether C2 is present 350 if (db.lookupType("Matcher", false) != null) { 351 usingServerCompiler = true; 352 } else { 353 usingClientCompiler = true; 354 } 355 } 356 } 357 358 if (debugger != null) { 359 isLP64 = debugger.getMachineDescription().isLP64(); 360 } 361 bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue(); 362 bytesPerWord = db.lookupIntConstant("BytesPerWord").intValue(); 363 heapWordSize = db.lookupIntConstant("HeapWordSize").intValue(); 364 oopSize = db.lookupIntConstant("oopSize").intValue(); 365 366 intType = db.lookupType("int"); 367 uintType = db.lookupType("uint"); 368 intxType = db.lookupType("intx"); 369 uintxType = db.lookupType("uintx"); 370 sizetType = db.lookupType("size_t"); 371 boolType = (CIntegerType) db.lookupType("bool"); 372 373 minObjAlignmentInBytes = getObjectAlignmentInBytes(); 374 if (minObjAlignmentInBytes == 8) { 375 logMinObjAlignmentInBytes = 3; 376 } else if (minObjAlignmentInBytes == 16) { 377 logMinObjAlignmentInBytes = 4; 378 } else { 379 throw new RuntimeException("Object alignment " + minObjAlignmentInBytes + " not yet supported"); 380 } 381 382 if (isCompressedOopsEnabled()) { 383 // Size info for oops within java objects is fixed 384 heapOopSize = (int)getIntSize(); 385 } else { 386 heapOopSize = (int)getOopSize(); 387 } 388 389 if (isCompressedKlassPointersEnabled()) { 390 klassPtrSize = (int)getIntSize(); 391 } else { 392 klassPtrSize = (int)getOopSize(); // same as an oop 393 } 394 } 395 396 /** This could be used by a reflective runtime system */ 397 public static void initialize(TypeDataBase db, boolean isBigEndian) { 398 if (soleInstance != null) { 399 throw new RuntimeException("Attempt to initialize VM twice"); 400 } 401 soleInstance = new VM(db, null, isBigEndian); 402 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 403 ((Observer) iter.next()).update(null, null); 404 } 405 } 406 407 /** This is used by the debugging system */ 408 public static void initialize(TypeDataBase db, JVMDebugger debugger) { 409 if (soleInstance != null) { 410 // Using multiple SA Tool classes in the same process creates a call here. 411 return; 412 } 413 soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); 414 415 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 416 ((Observer) iter.next()).update(null, null); 417 } 418 419 debugger.putHeapConst(soleInstance.getHeapOopSize(), soleInstance.getKlassPtrSize(), 420 Universe.getNarrowOopBase(), Universe.getNarrowOopShift(), 421 Universe.getNarrowKlassBase(), Universe.getNarrowKlassShift()); 422 } 423 424 /** This is used by the debugging system */ 425 public static void shutdown() { 426 soleInstance = null; 427 } 428 429 /** This is used by both the debugger and any runtime system. It is 430 the basic mechanism by which classes which mimic underlying VM 431 functionality cause themselves to be initialized. The given 432 observer will be notified (with arguments (null, null)) when the 433 VM is re-initialized, as well as when it registers itself with 434 the VM. */ 435 public static void registerVMInitializedObserver(Observer o) { 436 vmInitializedObservers.add(o); 437 o.update(null, null); 438 } 439 440 /** This is the primary accessor used by both the debugger and any 441 potential runtime system */ 442 public static VM getVM() { 443 if (soleInstance == null) { 444 throw new RuntimeException("VM.initialize() was not yet called"); 445 } 446 return soleInstance; 447 } 448 449 /** This is only used by the debugging system. The given observer 450 will be notified if the underlying VM resumes execution. NOTE 451 that the given observer is not triggered if the VM is currently 452 running and therefore differs in behavior from {@link 453 #registerVMInitializedObserver} (because of the possibility of 454 race conditions if the observer is added while the VM is being 455 suspended or resumed). */ 456 public void registerVMResumedObserver(Observer o) { 457 vmResumedObservers.add(o); 458 } 459 460 /** This is only used by the debugging system. The given observer 461 will be notified if the underlying VM suspends execution. NOTE 462 that the given observer is not triggered if the VM is currently 463 suspended and therefore differs in behavior from {@link 464 #registerVMInitializedObserver} (because of the possibility of 465 race conditions if the observer is added while the VM is being 466 suspended or resumed). */ 467 public void registerVMSuspendedObserver(Observer o) { 468 vmSuspendedObservers.add(o); 469 } 470 471 /** This is only used by the debugging system. Informs all 472 registered resumption observers that the VM has been resumed. 473 The application is responsible for actually having performed the 474 resumption. No OopHandles must be used after this point, as they 475 may move in the target address space due to garbage 476 collection. */ 477 public void fireVMResumed() { 478 for (Iterator iter = vmResumedObservers.iterator(); iter.hasNext(); ) { 479 ((Observer) iter.next()).update(null, null); 480 } 481 } 482 483 /** This is only used by the debugging system. Informs all 484 registered suspension observers that the VM has been suspended. 485 The application is responsible for actually having performed the 486 suspension. Garbage collection must be forbidden at this point; 487 for example, a JPDA-level suspension is not adequate since the 488 VM thread may still be running. */ 489 public void fireVMSuspended() { 490 for (Iterator iter = vmSuspendedObservers.iterator(); iter.hasNext(); ) { 491 ((Observer) iter.next()).update(null, null); 492 } 493 } 494 495 /** Returns the OS this VM is running on. Notice that by delegating 496 to the debugger we can transparently support remote 497 debugging. */ 498 public String getOS() { 499 if (debugger != null) { 500 return debugger.getOS(); 501 } 502 return PlatformInfo.getOS(); 503 } 504 505 /** Returns the CPU this VM is running on. Notice that by delegating 506 to the debugger we can transparently support remote 507 debugging. */ 508 public String getCPU() { 509 if (debugger != null) { 510 return debugger.getCPU(); 511 } 512 return PlatformInfo.getCPU(); 513 } 514 515 public Type lookupType(String cTypeName) { 516 return db.lookupType(cTypeName); 517 } 518 519 public Integer lookupIntConstant(String name) { 520 return db.lookupIntConstant(name); 521 } 522 523 // Convenience function for conversions 524 static public long getAddressValue(Address addr) { 525 return VM.getVM().getDebugger().getAddressValue(addr); 526 } 527 528 public long getAddressSize() { 529 return db.getAddressSize(); 530 } 531 532 public long getOopSize() { 533 return oopSize; 534 } 535 536 public long getLogAddressSize() { 537 return logAddressSize; 538 } 539 540 public long getIntSize() { 541 return db.getJIntType().getSize(); 542 } 543 544 /** NOTE: this offset is in BYTES in this system! */ 545 public long getStackBias() { 546 return stackBias; 547 } 548 549 /** Indicates whether the underlying machine supports the LP64 data 550 model. This is needed for conditionalizing code in a few places */ 551 public boolean isLP64() { 552 if (Assert.ASSERTS_ENABLED) { 553 Assert.that(isDebugging(), "Debugging system only for now"); 554 } 555 return isLP64; 556 } 557 558 /** Get bytes-per-long == long/double natural alignment. */ 559 public int getBytesPerLong() { 560 return bytesPerLong; 561 } 562 563 public int getBytesPerWord() { 564 return bytesPerWord; 565 } 566 567 /** Get minimum object alignment in bytes. */ 568 public int getMinObjAlignmentInBytes() { 569 return minObjAlignmentInBytes; 570 } 571 public int getLogMinObjAlignmentInBytes() { 572 return logMinObjAlignmentInBytes; 573 } 574 575 public int getHeapWordSize() { 576 return heapWordSize; 577 } 578 579 public int getHeapOopSize() { 580 return heapOopSize; 581 } 582 583 public int getKlassPtrSize() { 584 return klassPtrSize; 585 } 586 /** Utility routine for getting data structure alignment correct */ 587 public long alignUp(long size, long alignment) { 588 return (size + alignment - 1) & ~(alignment - 1); 589 } 590 591 /** Utility routine for getting data structure alignment correct */ 592 public long alignDown(long size, long alignment) { 593 return size & ~(alignment - 1); 594 } 595 596 /** Utility routine for building an int from two "unsigned" 16-bit 597 shorts */ 598 public int buildIntFromShorts(short low, short high) { 599 return (((int) high) << 16) | (((int) low) & 0xFFFF); 600 } 601 602 /** Utility routine for building a long from two "unsigned" 32-bit 603 ints in <b>platform-dependent</b> order */ 604 public long buildLongFromIntsPD(int oneHalf, int otherHalf) { 605 if (isBigEndian) { 606 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL); 607 } else{ 608 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL); 609 } 610 } 611 612 public TypeDataBase getTypeDataBase() { 613 return db; 614 } 615 616 public Universe getUniverse() { 617 if (universe == null) { 618 universe = new Universe(); 619 } 620 return universe; 621 } 622 623 public ObjectHeap getObjectHeap() { 624 if (heap == null) { 625 heap = new ObjectHeap(db); 626 } 627 return heap; 628 } 629 630 public SymbolTable getSymbolTable() { 631 if (symbols == null) { 632 symbols = SymbolTable.getTheTable(); 633 } 634 return symbols; 635 } 636 637 public StringTable getStringTable() { 638 if (strings == null) { 639 strings = StringTable.getTheTable(); 640 } 641 return strings; 642 } 643 644 public SystemDictionary getSystemDictionary() { 645 if (dict == null) { 646 dict = new SystemDictionary(); 647 } 648 return dict; 649 } 650 651 public Threads getThreads() { 652 if (threads == null) { 653 threads = new Threads(); 654 } 655 return threads; 656 } 657 658 public ObjectSynchronizer getObjectSynchronizer() { 659 if (synchronizer == null) { 660 synchronizer = new ObjectSynchronizer(); 661 } 662 return synchronizer; 663 } 664 665 public JNIHandles getJNIHandles() { 666 if (handles == null) { 667 handles = new JNIHandles(); 668 } 669 return handles; 670 } 671 672 public Interpreter getInterpreter() { 673 if (interpreter == null) { 674 interpreter = new Interpreter(); 675 } 676 return interpreter; 677 } 678 679 public StubRoutines getStubRoutines() { 680 if (stubRoutines == null) { 681 stubRoutines = new StubRoutines(); 682 } 683 return stubRoutines; 684 } 685 686 public VMRegImpl getVMRegImplInfo() { 687 if (vmregImpl == null) { 688 vmregImpl = new VMRegImpl(); 689 } 690 return vmregImpl; 691 } 692 693 public Bytes getBytes() { 694 if (bytes == null) { 695 bytes = new Bytes(debugger.getMachineDescription()); 696 } 697 return bytes; 698 } 699 700 /** Returns true if this is a isBigEndian, false otherwise */ 701 public boolean isBigEndian() { 702 return isBigEndian; 703 } 704 705 /** Returns true if this is a "core" build, false if either C1 or C2 706 is present */ 707 public boolean isCore() { 708 return (!(usingClientCompiler || usingServerCompiler)); 709 } 710 711 /** Returns true if this is a C1 build, false otherwise */ 712 public boolean isClientCompiler() { 713 return usingClientCompiler; 714 } 715 716 /** Returns true if this is a C2 build, false otherwise */ 717 public boolean isServerCompiler() { 718 return usingServerCompiler; 719 } 720 721 /** Returns true if C2 derived pointer table should be used, false otherwise */ 722 public boolean useDerivedPointerTable() { 723 return !disableDerivedPointerTableCheck; 724 } 725 726 /** Returns the code cache; should not be used if is core build */ 727 public CodeCache getCodeCache() { 728 if (Assert.ASSERTS_ENABLED) { 729 Assert.that(!isCore(), "noncore builds only"); 730 } 731 if (codeCache == null) { 732 codeCache = new CodeCache(); 733 } 734 return codeCache; 735 } 736 737 /** Should only be called for C1 builds */ 738 public Runtime1 getRuntime1() { 739 if (Assert.ASSERTS_ENABLED) { 740 Assert.that(isClientCompiler(), "C1 builds only"); 741 } 742 if (runtime1 == null) { 743 runtime1 = new Runtime1(); 744 } 745 return runtime1; 746 } 747 748 /** Test to see whether we're in debugging mode (NOTE: this really 749 should not be tested by this code; currently only used in 750 StackFrameStream) */ 751 public boolean isDebugging() { 752 return (debugger != null); 753 } 754 755 /** This is only used by the debugging (i.e., non-runtime) system */ 756 public JVMDebugger getDebugger() { 757 if (debugger == null) { 758 throw new RuntimeException("Attempt to use debugger in runtime system"); 759 } 760 return debugger; 761 } 762 763 /** Indicates whether a given program counter is in Java code. This 764 includes but is not spanned by the interpreter and code cache. 765 Only used in the debugging system, for implementing 766 JavaThread.currentFrameGuess() on x86. */ 767 public boolean isJavaPCDbg(Address addr) { 768 // FIXME: this is not a complete enough set: must include areas 769 // like vtable stubs 770 return (getInterpreter().contains(addr) || 771 getCodeCache().contains(addr)); 772 } 773 774 /** FIXME: figure out where to stick this */ 775 public int getInvocationEntryBCI() { 776 return invocationEntryBCI; 777 } 778 779 // FIXME: figure out where to stick this 780 public boolean wizardMode() { 781 return true; 782 } 783 784 public ReversePtrs getRevPtrs() { 785 return revPtrs; 786 } 787 788 public void setRevPtrs(ReversePtrs rp) { 789 revPtrs = rp; 790 } 791 792 // returns null, if not available. 793 public String getVMRelease() { 794 return vmRelease; 795 } 796 797 // returns null, if not available. 798 public String getVMInternalInfo() { 799 return vmInternalInfo; 800 } 801 802 public int getReserveForAllocationPrefetch() { 803 return reserveForAllocationPrefetch; 804 } 805 806 public boolean isSharingEnabled() { 807 if (sharingEnabled == null) { 808 Flag flag = getCommandLineFlag("UseSharedSpaces"); 809 sharingEnabled = (flag == null)? Boolean.FALSE : 810 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 811 } 812 return sharingEnabled.booleanValue(); 813 } 814 815 public boolean isCompressedOopsEnabled() { 816 if (compressedOopsEnabled == null) { 817 Flag flag = getCommandLineFlag("UseCompressedOops"); 818 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 819 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 820 } 821 return compressedOopsEnabled.booleanValue(); 822 } 823 824 public boolean isCompressedKlassPointersEnabled() { 825 if (compressedKlassPointersEnabled == null) { 826 Flag flag = getCommandLineFlag("UseCompressedClassPointers"); 827 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: 828 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 829 } 830 return compressedKlassPointersEnabled.booleanValue(); 831 } 832 833 public int getObjectAlignmentInBytes() { 834 if (objectAlignmentInBytes == 0) { 835 Flag flag = getCommandLineFlag("ObjectAlignmentInBytes"); 836 objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getIntx(); 837 } 838 return objectAlignmentInBytes; 839 } 840 841 /** Indicates whether Thread-Local Allocation Buffers are used */ 842 public boolean getUseTLAB() { 843 Flag flag = getCommandLineFlag("UseTLAB"); 844 return (flag == null) ? false: flag.getBool(); 845 } 846 847 // returns null, if not available. 848 public Flag[] getCommandLineFlags() { 849 if (commandLineFlags == null) { 850 readCommandLineFlags(); 851 } 852 853 return commandLineFlags; 854 } 855 856 public Flag getCommandLineFlag(String name) { 857 if (flagsMap == null) { 858 flagsMap = new HashMap(); 859 Flag[] flags = getCommandLineFlags(); 860 for (int i = 0; i < flags.length; i++) { 861 flagsMap.put(flags[i].getName(), flags[i]); 862 } 863 } 864 return (Flag) flagsMap.get(name); 865 } 866 867 private void readCommandLineFlags() { 868 // get command line flags 869 TypeDataBase db = getTypeDataBase(); 870 Type flagType = db.lookupType("Flag"); 871 int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); 872 // NOTE: last flag contains null values. 873 commandLineFlags = new Flag[numFlags - 1]; 874 875 Address flagAddr = flagType.getAddressField("flags").getValue(); 876 877 AddressField typeFld = flagType.getAddressField("_type"); 878 AddressField nameFld = flagType.getAddressField("_name"); 879 AddressField addrFld = flagType.getAddressField("_addr"); 880 CIntField flagsFld = new CIntField(flagType.getCIntegerField("_flags"), 0); 881 882 long flagSize = flagType.getSize(); // sizeof(Flag) 883 884 // NOTE: last flag contains null values. 885 for (int f = 0; f < numFlags - 1; f++) { 886 String type = CStringUtilities.getString(typeFld.getValue(flagAddr)); 887 String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); 888 Address addr = addrFld.getValue(flagAddr); 889 int flags = (int)flagsFld.getValue(flagAddr); 890 commandLineFlags[f] = new Flag(type, name, addr, flags); 891 flagAddr = flagAddr.addOffsetTo(flagSize); 892 } 893 894 // sort flags by name 895 Arrays.sort(commandLineFlags, new Comparator() { 896 public int compare(Object o1, Object o2) { 897 Flag f1 = (Flag) o1; 898 Flag f2 = (Flag) o2; 899 return f1.getName().compareTo(f2.getName()); 900 } 901 }); 902 } 903 904 public String getSystemProperty(String key) { 905 Properties props = getSystemProperties(); 906 return (props != null)? props.getProperty(key) : null; 907 } 908 909 public Properties getSystemProperties() { 910 if (sysProps == null) { 911 readSystemProperties(); 912 } 913 return sysProps; 914 } 915 916 private void readSystemProperties() { 917 final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); 918 systemKls.iterateStaticFields(new DefaultOopVisitor() { 919 ObjectReader objReader = new ObjectReader(); 920 public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { 921 if (field.getID().getName().equals("props")) { 922 try { 923 sysProps = (Properties) objReader.readObject(field.getValue(getObj())); 924 } catch (Exception e) { 925 e.printStackTrace(); 926 } 927 } 928 } 929 }); 930 } 931 }