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