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