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