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