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 152 // command line flags supplied to VM - see struct JVMFlag in jvmFlag.hpp 153 public static final class Flag { 154 private String type; 155 private String name; 156 private Address addr; 157 private int flags; 158 159 private Flag(String type, String name, Address addr, int flags) { 160 this.type = type; 161 this.name = name; 162 this.addr = addr; 163 this.flags = flags; 164 } 165 166 public String getType() { 167 return type; 168 } 169 170 public String getName() { 171 return name; 172 } 173 174 public Address getAddress() { 175 return addr; 176 } 177 178 public int getOrigin() { 179 return flags & Flags_VALUE_ORIGIN_MASK; 180 } 181 182 // See JVMFlag::print_origin() in HotSpot 183 public String getOriginString() { 184 var origin = flags & Flags_VALUE_ORIGIN_MASK; 185 if (origin == Flags_DEFAULT) { 186 return "default"; 187 } else if (origin == Flags_COMMAND_LINE) { 188 return "command line"; 189 } else if (origin == Flags_ENVIRON_VAR) { 190 return "environment"; 191 } else if (origin == Flags_CONFIG_FILE) { 192 return "config file"; 193 } else if (origin == Flags_MANAGEMENT) { 194 return "management"; 195 } else if (origin == Flags_ERGONOMIC) { 196 String result = ""; 197 if ((flags & Flags_WAS_SET_ON_COMMAND_LINE) == Flags_WAS_SET_ON_COMMAND_LINE) { 198 result = "command line, "; 199 } 200 return result + "ergonomic"; 201 } else if (origin == Flags_ATTACH_ON_DEMAND) { 202 return "attach"; 203 } else if (origin == Flags_INTERNAL) { 204 return "internal"; 205 } else if (origin == Flags_JIMAGE_RESOURCE) { 206 return "jimage"; 207 } else { 208 throw new IllegalStateException( 209 "Unknown flag origin " + origin + " is detected in " + name); 210 } 211 } 212 213 public boolean isBool() { 214 return type.equals("bool"); 215 } 216 217 public boolean getBool() { 218 if (Assert.ASSERTS_ENABLED) { 219 Assert.that(isBool(), "not a bool flag!"); 220 } 221 return addr.getCIntegerAt(0, boolType.getSize(), boolType.isUnsigned()) != 0; 222 } 223 224 public boolean isInt() { 225 return type.equals("int"); 226 } 227 228 public long getInt() { 229 if (Assert.ASSERTS_ENABLED) { 230 Assert.that(isInt(), "not an int flag!"); 231 } 232 return addr.getCIntegerAt(0, intType.getSize(), false); 233 } 234 235 public boolean isUInt() { 236 return type.equals("uint"); 237 } 238 239 public long getUInt() { 240 if (Assert.ASSERTS_ENABLED) { 241 Assert.that(isUInt(), "not a uint flag!"); 242 } 243 return addr.getCIntegerAt(0, uintType.getSize(), false); 244 } 245 246 public boolean isIntx() { 247 return type.equals("intx"); 248 } 249 250 public long getIntx() { 251 if (Assert.ASSERTS_ENABLED) { 252 Assert.that(isIntx(), "not an intx flag!"); 253 } 254 return addr.getCIntegerAt(0, intxType.getSize(), false); 255 } 256 257 public boolean isUIntx() { 258 return type.equals("uintx"); 259 } 260 261 public long getUIntx() { 262 if (Assert.ASSERTS_ENABLED) { 263 Assert.that(isUIntx(), "not a uintx flag!"); 264 } 265 return addr.getCIntegerAt(0, uintxType.getSize(), true); 266 } 267 268 public boolean isSizet() { 269 return type.equals("size_t"); 270 } 271 272 public long getSizet() { 273 if (Assert.ASSERTS_ENABLED) { 274 Assert.that(isSizet(), "not a size_t flag!"); 275 } 276 return addr.getCIntegerAt(0, sizetType.getSize(), true); 277 } 278 279 public boolean isCcstr() { 280 return type.equals("ccstr"); 281 } 282 283 public String getCcstr() { 284 if (Assert.ASSERTS_ENABLED) { 285 Assert.that(isCcstr(), "not a ccstr flag!"); 286 } 287 return CStringUtilities.getString(addr.getAddressAt(0)); 288 } 289 290 public boolean isCcstrlist() { 291 return type.equals("ccstrlist"); 292 } 293 294 public String getCcstrlist() { 295 if (Assert.ASSERTS_ENABLED) { 296 Assert.that(isCcstrlist(), "not a ccstrlist flag!"); 297 } 298 return CStringUtilities.getString(addr.getAddressAt(0)); 299 } 300 301 public boolean isDouble() { 302 return type.equals("double"); 303 } 304 305 public double getDouble() { 306 if (Assert.ASSERTS_ENABLED) { 307 Assert.that(isDouble(), "not a double flag!"); 308 } 309 return addr.getJDoubleAt(0); 310 } 311 312 public boolean isUint64t() { 313 return type.equals("uint64_t"); 314 } 315 316 public long getUint64t() { 317 if (Assert.ASSERTS_ENABLED) { 318 Assert.that(isUint64t(), "not an uint64_t flag!"); 319 } 320 return addr.getCIntegerAt(0, uint64tType.getSize(), true); 321 } 322 323 public String getValue() { 324 if (isBool()) { 325 return Boolean.toString(getBool()); 326 } else if (isInt()) { 327 return Long.toString(getInt()); 328 } else if (isUInt()) { 329 return Long.toString(getUInt()); 330 } else if (isIntx()) { 331 return Long.toString(getIntx()); 332 } else if (isUIntx()) { 333 return Long.toUnsignedString(getUIntx()); 334 } else if (isSizet()) { 335 return Long.toUnsignedString(getSizet()); 336 } else if (isCcstr()) { 337 var str = getCcstr(); 338 if (str != null) { 339 str = "\"" + str + "\""; 340 } 341 return str; 342 } else if (isCcstrlist()) { 343 var str = getCcstrlist(); 344 if (str != null) { 345 str = "\"" + str + "\""; 346 } 347 return str; 348 } else if (isDouble()) { 349 return Double.toString(getDouble()); 350 } else if (isUint64t()) { 351 return Long.toUnsignedString(getUint64t()); 352 } else { 353 throw new WrongTypeException("Unknown type: " + type + " (" + name + ")"); 354 } 355 } 356 }; 357 358 private static void checkVMVersion(String vmRelease) { 359 if (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null) { 360 // read sa build version. 361 String versionProp = "sun.jvm.hotspot.runtime.VM.saBuildVersion"; 362 String versionPropVal = saProps.getProperty(versionProp); 363 if (versionPropVal == null) { 364 throw new RuntimeException("Missing property " + versionProp); 365 } 366 367 var saVersion = Runtime.Version.parse(versionPropVal); 368 var vmVersion = Runtime.Version.parse(vmRelease); 369 370 if (saVersion.equals(vmVersion)) { 371 // Exact match 372 return; 373 } 374 if (!saVersion.equalsIgnoreOptional(vmVersion)) { 375 // Throw exception if different release versions: 376 // <version>+<build> 377 throw new VMVersionMismatchException(saVersion, vmVersion); 378 } else { 379 // Otherwise print warning to allow mismatch not release versions 380 // during development. 381 System.err.println("WARNING: Hotspot VM version " + vmVersion + 382 " does not match with SA version " + saVersion + 383 "." + " You may see unexpected results. "); 384 } 385 } else { 386 System.err.println("WARNING: You have disabled SA and VM version check. You may be " + 387 "using incompatible version of SA and you may see unexpected " + 388 "results."); 389 } 390 } 391 392 private static final boolean disableDerivedPointerTableCheck; 393 private static final Properties saProps; 394 395 static { 396 saProps = new Properties(); 397 URL url = null; 398 try { 399 saProps.load(VM.class.getResourceAsStream("/sa.properties")); 400 } catch (Exception e) { 401 System.err.println("Unable to load properties " + 402 (url == null ? "null" : url.toString()) + 403 ": " + e.getMessage()); 404 } 405 406 disableDerivedPointerTableCheck = System.getProperty("sun.jvm.hotspot.runtime.VM.disableDerivedPointerTableCheck") != null; 407 } 408 409 private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) { 410 this.db = db; 411 this.debugger = debugger; 412 this.isBigEndian = isBigEndian; 413 414 // Note that we don't construct universe, heap, threads, 415 // interpreter, or stubRoutines here (any more). The current 416 // initialization mechanisms require that the VM be completely set 417 // up (i.e., out of its constructor, with soleInstance assigned) 418 // before their static initializers are run. 419 420 if (db.getAddressSize() == 4) { 421 logAddressSize = 2; 422 } else if (db.getAddressSize() == 8) { 423 logAddressSize = 3; 424 } else { 425 throw new RuntimeException("Address size " + db.getAddressSize() + " not yet supported"); 426 } 427 428 // read VM version info 429 try { 430 Type vmVersion = db.lookupType("Abstract_VM_Version"); 431 Address releaseAddr = vmVersion.getAddressField("_s_vm_release").getValue(); 432 vmRelease = CStringUtilities.getString(releaseAddr); 433 Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue(); 434 vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr); 435 436 Type threadLocalAllocBuffer = db.lookupType("ThreadLocalAllocBuffer"); 437 CIntegerType intType = (CIntegerType) db.lookupType("int"); 438 CIntegerField reserveForAllocationPrefetchField = threadLocalAllocBuffer.getCIntegerField("_reserve_for_allocation_prefetch"); 439 reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType); 440 } catch (Exception exp) { 441 throw new RuntimeException("can't determine target's VM version : " + exp.getMessage()); 442 } 443 444 checkVMVersion(vmRelease); 445 446 invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue(); 447 448 // We infer the presence of JVMTI from the presence of the InstanceKlass::_breakpoints field. 449 { 450 Type type = db.lookupType("InstanceKlass"); 451 if (type.getField("_breakpoints", false, false) == null) { 452 isJvmtiSupported = false; 453 } else { 454 isJvmtiSupported = true; 455 } 456 } 457 458 // We infer the presence of C1 or C2 from a couple of fields we 459 // already have present in the type database 460 { 461 Type type = db.lookupType("Method"); 462 if (type.getField("_from_compiled_entry", false, false) == null) { 463 // Neither C1 nor C2 is present 464 usingClientCompiler = false; 465 usingServerCompiler = false; 466 } else { 467 // Determine whether C2 is present 468 if (db.lookupType("Matcher", false) != null) { 469 usingServerCompiler = true; 470 } else { 471 usingClientCompiler = true; 472 } 473 } 474 } 475 476 if (debugger != null) { 477 isLP64 = debugger.getMachineDescription().isLP64(); 478 } 479 bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue(); 480 bytesPerWord = db.lookupIntConstant("BytesPerWord").intValue(); 481 logBytesPerWord = db.lookupIntConstant("LogBytesPerWord").intValue(); 482 heapWordSize = db.lookupIntConstant("HeapWordSize").intValue(); 483 Flags_DEFAULT = db.lookupIntConstant("JVMFlagOrigin::DEFAULT").intValue(); 484 Flags_COMMAND_LINE = db.lookupIntConstant("JVMFlagOrigin::COMMAND_LINE").intValue(); 485 Flags_ENVIRON_VAR = db.lookupIntConstant("JVMFlagOrigin::ENVIRON_VAR").intValue(); 486 Flags_CONFIG_FILE = db.lookupIntConstant("JVMFlagOrigin::CONFIG_FILE").intValue(); 487 Flags_MANAGEMENT = db.lookupIntConstant("JVMFlagOrigin::MANAGEMENT").intValue(); 488 Flags_ERGONOMIC = db.lookupIntConstant("JVMFlagOrigin::ERGONOMIC").intValue(); 489 Flags_ATTACH_ON_DEMAND = db.lookupIntConstant("JVMFlagOrigin::ATTACH_ON_DEMAND").intValue(); 490 Flags_INTERNAL = db.lookupIntConstant("JVMFlagOrigin::INTERNAL").intValue(); 491 Flags_JIMAGE_RESOURCE = db.lookupIntConstant("JVMFlagOrigin::JIMAGE_RESOURCE").intValue(); 492 Flags_VALUE_ORIGIN_MASK = db.lookupIntConstant("JVMFlag::VALUE_ORIGIN_MASK").intValue(); 493 Flags_WAS_SET_ON_COMMAND_LINE = db.lookupIntConstant("JVMFlag::WAS_SET_ON_COMMAND_LINE").intValue(); 494 oopSize = db.lookupIntConstant("oopSize").intValue(); 495 496 intType = db.lookupType("int"); 497 uintType = db.lookupType("uint"); 498 intxType = db.lookupType("intx"); 499 uintxType = db.lookupType("uintx"); 500 sizetType = db.lookupType("size_t"); 501 uint64tType = db.lookupType("uint64_t"); 502 boolType = (CIntegerType) db.lookupType("bool"); 503 504 minObjAlignmentInBytes = getObjectAlignmentInBytes(); 505 if ((minObjAlignmentInBytes & (minObjAlignmentInBytes - 1)) != 0) { 506 throw new RuntimeException("Object alignment " + minObjAlignmentInBytes + " is not power of two"); 507 } 508 509 logMinObjAlignmentInBytes = Integer.numberOfTrailingZeros(minObjAlignmentInBytes); 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 public static 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 /** Indicates whether the underlying machine supports the LP64 data 674 model. This is needed for conditionalizing code in a few places */ 675 public boolean isLP64() { 676 if (Assert.ASSERTS_ENABLED) { 677 Assert.that(isDebugging(), "Debugging system only for now"); 678 } 679 return isLP64; 680 } 681 682 /** Get bytes-per-long == long/double natural alignment. */ 683 public int getBytesPerLong() { 684 return bytesPerLong; 685 } 686 687 public int getBytesPerWord() { 688 return bytesPerWord; 689 } 690 691 public int getLogBytesPerWord() { 692 return logBytesPerWord; 693 } 694 695 /** Get minimum object alignment in bytes. */ 696 public int getMinObjAlignmentInBytes() { 697 return minObjAlignmentInBytes; 698 } 699 public int getLogMinObjAlignmentInBytes() { 700 return logMinObjAlignmentInBytes; 701 } 702 703 public int getHeapWordSize() { 704 return heapWordSize; 705 } 706 707 public int getHeapOopSize() { 708 return heapOopSize; 709 } 710 711 public int getKlassPtrSize() { 712 return klassPtrSize; 713 } 714 /** Utility routine for getting data structure alignment correct */ 715 public long alignUp(long size, long alignment) { 716 return (size + alignment - 1) & ~(alignment - 1); 717 } 718 719 /** Utility routine for getting data structure alignment correct */ 720 public long alignDown(long size, long alignment) { 721 return size & ~(alignment - 1); 722 } 723 724 /** Utility routine for building an int from two "unsigned" 16-bit 725 shorts */ 726 public int buildIntFromShorts(short low, short high) { 727 return (((int) high) << 16) | (((int) low) & 0xFFFF); 728 } 729 730 public TypeDataBase getTypeDataBase() { 731 return db; 732 } 733 734 public Universe getUniverse() { 735 if (universe == null) { 736 universe = new Universe(); 737 } 738 return universe; 739 } 740 741 public ObjectHeap getObjectHeap() { 742 if (heap == null) { 743 heap = new ObjectHeap(db); 744 } 745 return heap; 746 } 747 748 public SystemDictionary getSystemDictionary() { 749 if (dict == null) { 750 dict = new SystemDictionary(); 751 } 752 return dict; 753 } 754 755 public ClassLoaderDataGraph getClassLoaderDataGraph() { 756 if (cldGraph == null) { 757 cldGraph = new ClassLoaderDataGraph(); 758 } 759 return cldGraph; 760 } 761 762 public Threads getThreads() { 763 if (threads == null) { 764 threads = new Threads(); 765 } 766 return threads; 767 } 768 769 public ObjectSynchronizer getObjectSynchronizer() { 770 if (synchronizer == null) { 771 synchronizer = new ObjectSynchronizer(); 772 } 773 return synchronizer; 774 } 775 776 public JNIHandles getJNIHandles() { 777 if (handles == null) { 778 handles = new JNIHandles(); 779 } 780 return handles; 781 } 782 783 public Interpreter getInterpreter() { 784 if (interpreter == null) { 785 interpreter = new Interpreter(); 786 } 787 return interpreter; 788 } 789 790 public StubRoutines getStubRoutines() { 791 if (stubRoutines == null) { 792 stubRoutines = new StubRoutines(); 793 } 794 return stubRoutines; 795 } 796 797 public VMRegImpl getVMRegImplInfo() { 798 if (vmregImpl == null) { 799 vmregImpl = new VMRegImpl(); 800 } 801 return vmregImpl; 802 } 803 804 public FileMapInfo getFileMapInfo() { 805 if (!isSharingEnabled()) { 806 return null; 807 } 808 if (fileMapInfo == null) { 809 fileMapInfo = new FileMapInfo(); 810 } 811 return fileMapInfo; 812 } 813 814 public Bytes getBytes() { 815 if (bytes == null) { 816 bytes = new Bytes(debugger.getMachineDescription()); 817 } 818 return bytes; 819 } 820 821 /** Returns true if this is a isBigEndian, false otherwise */ 822 public boolean isBigEndian() { 823 return isBigEndian; 824 } 825 826 /** Returns true if JVMTI is supported, false otherwise */ 827 public boolean isJvmtiSupported() { 828 return isJvmtiSupported; 829 } 830 831 /** Returns true if this is a "core" build, false if either C1 or C2 832 is present */ 833 public boolean isCore() { 834 return (!(usingClientCompiler || usingServerCompiler)); 835 } 836 837 /** Returns true if this is a C1 build, false otherwise */ 838 public boolean isClientCompiler() { 839 return usingClientCompiler; 840 } 841 842 /** Returns true if this is a C2 build, false otherwise */ 843 public boolean isServerCompiler() { 844 return usingServerCompiler; 845 } 846 847 /** Returns true if C2 derived pointer table should be used, false otherwise */ 848 public boolean useDerivedPointerTable() { 849 return !disableDerivedPointerTableCheck; 850 } 851 852 /** Returns the code cache; should not be used if is core build */ 853 public CodeCache getCodeCache() { 854 if (Assert.ASSERTS_ENABLED) { 855 Assert.that(!isCore(), "noncore builds only"); 856 } 857 if (codeCache == null) { 858 codeCache = new CodeCache(); 859 } 860 return codeCache; 861 } 862 863 /** Should only be called for C1 builds */ 864 public Runtime1 getRuntime1() { 865 if (Assert.ASSERTS_ENABLED) { 866 Assert.that(isClientCompiler(), "C1 builds only"); 867 } 868 if (runtime1 == null) { 869 runtime1 = new Runtime1(); 870 } 871 return runtime1; 872 } 873 874 /** Test to see whether we're in debugging mode (NOTE: this really 875 should not be tested by this code; currently only used in 876 StackFrameStream) */ 877 public boolean isDebugging() { 878 return (debugger != null); 879 } 880 881 /** This is only used by the debugging (i.e., non-runtime) system */ 882 public JVMDebugger getDebugger() { 883 if (debugger == null) { 884 throw new RuntimeException("Attempt to use debugger in runtime system"); 885 } 886 return debugger; 887 } 888 889 /** Indicates whether a given program counter is in Java code. This 890 includes but is not spanned by the interpreter and code cache. 891 Only used in the debugging system, for implementing 892 JavaThread.currentFrameGuess() on x86. */ 893 public boolean isJavaPCDbg(Address addr) { 894 // FIXME: this is not a complete enough set: must include areas 895 // like vtable stubs 896 return (getInterpreter().contains(addr) || 897 getCodeCache().contains(addr)); 898 } 899 900 /** FIXME: figure out where to stick this */ 901 public int getInvocationEntryBCI() { 902 return invocationEntryBCI; 903 } 904 905 // FIXME: figure out where to stick this 906 public boolean wizardMode() { 907 return true; 908 } 909 910 public ReversePtrs getRevPtrs() { 911 return revPtrs; 912 } 913 914 public void setRevPtrs(ReversePtrs rp) { 915 revPtrs = rp; 916 } 917 918 // returns null, if not available. 919 public String getVMRelease() { 920 return vmRelease; 921 } 922 923 // returns null, if not available. 924 public String getVMInternalInfo() { 925 return vmInternalInfo; 926 } 927 928 public int getReserveForAllocationPrefetch() { 929 return reserveForAllocationPrefetch; 930 } 931 932 public boolean isSharingEnabled() { 933 if (sharingEnabled == null) { 934 Address address = VM.getVM().getDebugger().lookup(null, "UseSharedSpaces"); 935 if (address == null && getOS().equals("win32")) { 936 // On Win32 symbols are prefixed with the dll name. So look for 937 // UseSharedSpaces as a symbol in jvm.dll. 938 address = VM.getVM().getDebugger().lookup(null, "jvm!UseSharedSpaces"); 939 } 940 sharingEnabled = address.getJBooleanAt(0); 941 } 942 return sharingEnabled.booleanValue(); 943 } 944 945 public boolean isCompressedOopsEnabled() { 946 if (compressedOopsEnabled == null) { 947 Flag flag = getCommandLineFlag("UseCompressedOops"); 948 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 949 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 950 } 951 return compressedOopsEnabled.booleanValue(); 952 } 953 954 public boolean isCompressedKlassPointersEnabled() { 955 if (compressedKlassPointersEnabled == null) { 956 Flag flag = getCommandLineFlag("UseCompressedClassPointers"); 957 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: 958 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 959 } 960 return compressedKlassPointersEnabled.booleanValue(); 961 } 962 963 public int getObjectAlignmentInBytes() { 964 if (objectAlignmentInBytes == 0) { 965 Flag flag = getCommandLineFlag("ObjectAlignmentInBytes"); 966 objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getInt(); 967 } 968 return objectAlignmentInBytes; 969 } 970 971 /** Indicates whether Thread-Local Allocation Buffers are used */ 972 public boolean getUseTLAB() { 973 Flag flag = getCommandLineFlag("UseTLAB"); 974 return (flag == null) ? false: flag.getBool(); 975 } 976 977 public boolean getCommandLineBooleanFlag(String name) { 978 Flag flag = getCommandLineFlag(name); 979 return (flag == null) ? Boolean.FALSE: 980 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 981 } 982 983 // returns null, if not available. 984 public Flag[] getCommandLineFlags() { 985 if (commandLineFlags == null) { 986 readCommandLineFlags(); 987 } 988 989 return commandLineFlags; 990 } 991 992 public Flag getCommandLineFlag(String name) { 993 if (flagsMap == null) { 994 flagsMap = new HashMap<>(); 995 Flag[] flags = getCommandLineFlags(); 996 for (int i = 0; i < flags.length; i++) { 997 flagsMap.put(flags[i].getName(), flags[i]); 998 } 999 } 1000 return flagsMap.get(name); 1001 } 1002 1003 private static final String cmdFlagTypes[] = { 1004 "bool", 1005 "int", 1006 "uint", 1007 "intx", 1008 "uintx", 1009 "uint64_t", 1010 "size_t", 1011 "double", 1012 "ccstr", 1013 "ccstrlist" 1014 }; 1015 1016 private String getFlagTypeAsString(int typeIndex) { 1017 if (0 <= typeIndex && typeIndex < cmdFlagTypes.length) { 1018 return cmdFlagTypes[typeIndex]; 1019 } else { 1020 return "unknown"; 1021 } 1022 } 1023 1024 private void readCommandLineFlags() { 1025 // get command line flags 1026 TypeDataBase db = getTypeDataBase(); 1027 Type flagType = db.lookupType("JVMFlag"); 1028 int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); 1029 // NOTE: last flag contains null values. 1030 commandLineFlags = new Flag[numFlags - 1]; 1031 1032 Address flagAddr = flagType.getAddressField("flags").getValue(); 1033 CIntField typeFld = new CIntField(flagType.getCIntegerField("_type"), 0); 1034 AddressField nameFld = flagType.getAddressField("_name"); 1035 AddressField addrFld = flagType.getAddressField("_addr"); 1036 CIntField flagsFld = new CIntField(flagType.getCIntegerField("_flags"), 0); 1037 1038 long flagSize = flagType.getSize(); // sizeof(Flag) 1039 1040 // NOTE: last flag contains null values. 1041 for (int f = 0; f < numFlags - 1; f++) { 1042 int typeIndex = (int)typeFld.getValue(flagAddr); 1043 String type = getFlagTypeAsString(typeIndex); 1044 String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); 1045 Address addr = addrFld.getValue(flagAddr); 1046 int flags = (int)flagsFld.getValue(flagAddr); 1047 commandLineFlags[f] = new Flag(type, name, addr, flags); 1048 flagAddr = flagAddr.addOffsetTo(flagSize); 1049 } 1050 1051 // sort flags by name 1052 Arrays.sort(commandLineFlags, new Comparator<>() { 1053 public int compare(Flag f1, Flag f2) { 1054 return f1.getName().compareTo(f2.getName()); 1055 } 1056 }); 1057 } 1058 1059 public String getSystemProperty(String key) { 1060 Properties props = getSystemProperties(); 1061 return (props != null)? props.getProperty(key) : null; 1062 } 1063 1064 public Properties getSystemProperties() { 1065 if (sysProps == null) { 1066 readSystemProperties(); 1067 } 1068 return sysProps; 1069 } 1070 1071 private void readSystemProperties() { 1072 final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); 1073 systemKls.iterateStaticFields(new DefaultOopVisitor() { 1074 ObjectReader objReader = new ObjectReader(); 1075 public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { 1076 if (field.getID().getName().equals("props")) { 1077 try { 1078 sysProps = (Properties) objReader.readObject(field.getValue(getObj())); 1079 } catch (Exception e) { 1080 e.printStackTrace(); 1081 } 1082 } 1083 } 1084 }); 1085 } 1086 }