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