1 /* 2 * Copyright (c) 2000, 2022, 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 /** Utility routine for building a long from two "unsigned" 32-bit 731 ints in <b>platform-dependent</b> order */ 732 public long buildLongFromIntsPD(int oneHalf, int otherHalf) { 733 if (isBigEndian) { 734 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL); 735 } else{ 736 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL); 737 } 738 } 739 740 public TypeDataBase getTypeDataBase() { 741 return db; 742 } 743 744 public Universe getUniverse() { 745 if (universe == null) { 746 universe = new Universe(); 747 } 748 return universe; 749 } 750 751 public ObjectHeap getObjectHeap() { 752 if (heap == null) { 753 heap = new ObjectHeap(db); 754 } 755 return heap; 756 } 757 758 public SystemDictionary getSystemDictionary() { 759 if (dict == null) { 760 dict = new SystemDictionary(); 761 } 762 return dict; 763 } 764 765 public ClassLoaderDataGraph getClassLoaderDataGraph() { 766 if (cldGraph == null) { 767 cldGraph = new ClassLoaderDataGraph(); 768 } 769 return cldGraph; 770 } 771 772 public Threads getThreads() { 773 if (threads == null) { 774 threads = new Threads(); 775 } 776 return threads; 777 } 778 779 public ObjectSynchronizer getObjectSynchronizer() { 780 if (synchronizer == null) { 781 synchronizer = new ObjectSynchronizer(); 782 } 783 return synchronizer; 784 } 785 786 public JNIHandles getJNIHandles() { 787 if (handles == null) { 788 handles = new JNIHandles(); 789 } 790 return handles; 791 } 792 793 public Interpreter getInterpreter() { 794 if (interpreter == null) { 795 interpreter = new Interpreter(); 796 } 797 return interpreter; 798 } 799 800 public StubRoutines getStubRoutines() { 801 if (stubRoutines == null) { 802 stubRoutines = new StubRoutines(); 803 } 804 return stubRoutines; 805 } 806 807 public VMRegImpl getVMRegImplInfo() { 808 if (vmregImpl == null) { 809 vmregImpl = new VMRegImpl(); 810 } 811 return vmregImpl; 812 } 813 814 public FileMapInfo getFileMapInfo() { 815 if (!isSharingEnabled()) { 816 return null; 817 } 818 if (fileMapInfo == null) { 819 fileMapInfo = new FileMapInfo(); 820 } 821 return fileMapInfo; 822 } 823 824 public Bytes getBytes() { 825 if (bytes == null) { 826 bytes = new Bytes(debugger.getMachineDescription()); 827 } 828 return bytes; 829 } 830 831 /** Returns true if this is a isBigEndian, false otherwise */ 832 public boolean isBigEndian() { 833 return isBigEndian; 834 } 835 836 /** Returns true if JVMTI is supported, false otherwise */ 837 public boolean isJvmtiSupported() { 838 return isJvmtiSupported; 839 } 840 841 /** Returns true if this is a "core" build, false if either C1 or C2 842 is present */ 843 public boolean isCore() { 844 return (!(usingClientCompiler || usingServerCompiler)); 845 } 846 847 /** Returns true if this is a C1 build, false otherwise */ 848 public boolean isClientCompiler() { 849 return usingClientCompiler; 850 } 851 852 /** Returns true if this is a C2 build, false otherwise */ 853 public boolean isServerCompiler() { 854 return usingServerCompiler; 855 } 856 857 /** Returns true if C2 derived pointer table should be used, false otherwise */ 858 public boolean useDerivedPointerTable() { 859 return !disableDerivedPointerTableCheck; 860 } 861 862 /** Returns the code cache; should not be used if is core build */ 863 public CodeCache getCodeCache() { 864 if (Assert.ASSERTS_ENABLED) { 865 Assert.that(!isCore(), "noncore builds only"); 866 } 867 if (codeCache == null) { 868 codeCache = new CodeCache(); 869 } 870 return codeCache; 871 } 872 873 /** Should only be called for C1 builds */ 874 public Runtime1 getRuntime1() { 875 if (Assert.ASSERTS_ENABLED) { 876 Assert.that(isClientCompiler(), "C1 builds only"); 877 } 878 if (runtime1 == null) { 879 runtime1 = new Runtime1(); 880 } 881 return runtime1; 882 } 883 884 /** Test to see whether we're in debugging mode (NOTE: this really 885 should not be tested by this code; currently only used in 886 StackFrameStream) */ 887 public boolean isDebugging() { 888 return (debugger != null); 889 } 890 891 /** This is only used by the debugging (i.e., non-runtime) system */ 892 public JVMDebugger getDebugger() { 893 if (debugger == null) { 894 throw new RuntimeException("Attempt to use debugger in runtime system"); 895 } 896 return debugger; 897 } 898 899 /** Indicates whether a given program counter is in Java code. This 900 includes but is not spanned by the interpreter and code cache. 901 Only used in the debugging system, for implementing 902 JavaThread.currentFrameGuess() on x86. */ 903 public boolean isJavaPCDbg(Address addr) { 904 // FIXME: this is not a complete enough set: must include areas 905 // like vtable stubs 906 return (getInterpreter().contains(addr) || 907 getCodeCache().contains(addr)); 908 } 909 910 /** FIXME: figure out where to stick this */ 911 public int getInvocationEntryBCI() { 912 return invocationEntryBCI; 913 } 914 915 // FIXME: figure out where to stick this 916 public boolean wizardMode() { 917 return true; 918 } 919 920 public ReversePtrs getRevPtrs() { 921 return revPtrs; 922 } 923 924 public void setRevPtrs(ReversePtrs rp) { 925 revPtrs = rp; 926 } 927 928 // returns null, if not available. 929 public String getVMRelease() { 930 return vmRelease; 931 } 932 933 // returns null, if not available. 934 public String getVMInternalInfo() { 935 return vmInternalInfo; 936 } 937 938 public int getReserveForAllocationPrefetch() { 939 return reserveForAllocationPrefetch; 940 } 941 942 public boolean isSharingEnabled() { 943 if (sharingEnabled == null) { 944 Address address = VM.getVM().getDebugger().lookup(null, "UseSharedSpaces"); 945 if (address == null && getOS().equals("win32")) { 946 // On Win32 symbols are prefixed with the dll name. So look for 947 // UseSharedSpaces as a symbol in jvm.dll. 948 address = VM.getVM().getDebugger().lookup(null, "jvm!UseSharedSpaces"); 949 } 950 sharingEnabled = address.getJBooleanAt(0); 951 } 952 return sharingEnabled.booleanValue(); 953 } 954 955 public boolean isCompressedOopsEnabled() { 956 if (compressedOopsEnabled == null) { 957 Flag flag = getCommandLineFlag("UseCompressedOops"); 958 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 959 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 960 } 961 return compressedOopsEnabled.booleanValue(); 962 } 963 964 public boolean isCompressedKlassPointersEnabled() { 965 if (compressedKlassPointersEnabled == null) { 966 Flag flag = getCommandLineFlag("UseCompressedClassPointers"); 967 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: 968 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 969 } 970 return compressedKlassPointersEnabled.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 }