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 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 /** Utility routine for building a long from two "unsigned" 32-bit 732 ints in <b>platform-dependent</b> order */ 733 public long buildLongFromIntsPD(int oneHalf, int otherHalf) { 734 if (isBigEndian) { 735 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL); 736 } else{ 737 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL); 738 } 739 } 740 741 public TypeDataBase getTypeDataBase() { 742 return db; 743 } 744 745 public Universe getUniverse() { 746 if (universe == null) { 747 universe = new Universe(); 748 } 749 return universe; 750 } 751 752 public ObjectHeap getObjectHeap() { 753 if (heap == null) { 754 heap = new ObjectHeap(db); 755 } 756 return heap; 757 } 758 759 public SystemDictionary getSystemDictionary() { 760 if (dict == null) { 761 dict = new SystemDictionary(); 762 } 763 return dict; 764 } 765 766 public ClassLoaderDataGraph getClassLoaderDataGraph() { 767 if (cldGraph == null) { 768 cldGraph = new ClassLoaderDataGraph(); 769 } 770 return cldGraph; 771 } 772 773 public Threads getThreads() { 774 if (threads == null) { 775 threads = new Threads(); 776 } 777 return threads; 778 } 779 780 public ObjectSynchronizer getObjectSynchronizer() { 781 if (synchronizer == null) { 782 synchronizer = new ObjectSynchronizer(); 783 } 784 return synchronizer; 785 } 786 787 public JNIHandles getJNIHandles() { 788 if (handles == null) { 789 handles = new JNIHandles(); 790 } 791 return handles; 792 } 793 794 public Interpreter getInterpreter() { 795 if (interpreter == null) { 796 interpreter = new Interpreter(); 797 } 798 return interpreter; 799 } 800 801 public StubRoutines getStubRoutines() { 802 if (stubRoutines == null) { 803 stubRoutines = new StubRoutines(); 804 } 805 return stubRoutines; 806 } 807 808 public VMRegImpl getVMRegImplInfo() { 809 if (vmregImpl == null) { 810 vmregImpl = new VMRegImpl(); 811 } 812 return vmregImpl; 813 } 814 815 public FileMapInfo getFileMapInfo() { 816 if (!isSharingEnabled()) { 817 return null; 818 } 819 if (fileMapInfo == null) { 820 fileMapInfo = new FileMapInfo(); 821 } 822 return fileMapInfo; 823 } 824 825 public Bytes getBytes() { 826 if (bytes == null) { 827 bytes = new Bytes(debugger.getMachineDescription()); 828 } 829 return bytes; 830 } 831 832 /** Returns true if this is a isBigEndian, false otherwise */ 833 public boolean isBigEndian() { 834 return isBigEndian; 835 } 836 837 /** Returns true if JVMTI is supported, false otherwise */ 838 public boolean isJvmtiSupported() { 839 return isJvmtiSupported; 840 } 841 842 /** Returns true if this is a "core" build, false if either C1 or C2 843 is present */ 844 public boolean isCore() { 845 return (!(usingClientCompiler || usingServerCompiler)); 846 } 847 848 /** Returns true if this is a C1 build, false otherwise */ 849 public boolean isClientCompiler() { 850 return usingClientCompiler; 851 } 852 853 /** Returns true if this is a C2 build, false otherwise */ 854 public boolean isServerCompiler() { 855 return usingServerCompiler; 856 } 857 858 /** Returns true if C2 derived pointer table should be used, false otherwise */ 859 public boolean useDerivedPointerTable() { 860 return !disableDerivedPointerTableCheck; 861 } 862 863 /** Returns the code cache; should not be used if is core build */ 864 public CodeCache getCodeCache() { 865 if (Assert.ASSERTS_ENABLED) { 866 Assert.that(!isCore(), "noncore builds only"); 867 } 868 if (codeCache == null) { 869 codeCache = new CodeCache(); 870 } 871 return codeCache; 872 } 873 874 /** Should only be called for C1 builds */ 875 public Runtime1 getRuntime1() { 876 if (Assert.ASSERTS_ENABLED) { 877 Assert.that(isClientCompiler(), "C1 builds only"); 878 } 879 if (runtime1 == null) { 880 runtime1 = new Runtime1(); 881 } 882 return runtime1; 883 } 884 885 /** Test to see whether we're in debugging mode (NOTE: this really 886 should not be tested by this code; currently only used in 887 StackFrameStream) */ 888 public boolean isDebugging() { 889 return (debugger != null); 890 } 891 892 /** This is only used by the debugging (i.e., non-runtime) system */ 893 public JVMDebugger getDebugger() { 894 if (debugger == null) { 895 throw new RuntimeException("Attempt to use debugger in runtime system"); 896 } 897 return debugger; 898 } 899 900 /** Indicates whether a given program counter is in Java code. This 901 includes but is not spanned by the interpreter and code cache. 902 Only used in the debugging system, for implementing 903 JavaThread.currentFrameGuess() on x86. */ 904 public boolean isJavaPCDbg(Address addr) { 905 // FIXME: this is not a complete enough set: must include areas 906 // like vtable stubs 907 return (getInterpreter().contains(addr) || 908 getCodeCache().contains(addr)); 909 } 910 911 /** FIXME: figure out where to stick this */ 912 public int getInvocationEntryBCI() { 913 return invocationEntryBCI; 914 } 915 916 // FIXME: figure out where to stick this 917 public boolean wizardMode() { 918 return true; 919 } 920 921 public ReversePtrs getRevPtrs() { 922 return revPtrs; 923 } 924 925 public void setRevPtrs(ReversePtrs rp) { 926 revPtrs = rp; 927 } 928 929 // returns null, if not available. 930 public String getVMRelease() { 931 return vmRelease; 932 } 933 934 // returns null, if not available. 935 public String getVMInternalInfo() { 936 return vmInternalInfo; 937 } 938 939 public int getReserveForAllocationPrefetch() { 940 return reserveForAllocationPrefetch; 941 } 942 943 public boolean isSharingEnabled() { 944 if (sharingEnabled == null) { 945 Address address = VM.getVM().getDebugger().lookup(null, "UseSharedSpaces"); 946 if (address == null && getOS().equals("win32")) { 947 // On Win32 symbols are prefixed with the dll name. So look for 948 // UseSharedSpaces as a symbol in jvm.dll. 949 address = VM.getVM().getDebugger().lookup(null, "jvm!UseSharedSpaces"); 950 } 951 sharingEnabled = address.getJBooleanAt(0); 952 } 953 return sharingEnabled.booleanValue(); 954 } 955 956 public boolean isCompressedOopsEnabled() { 957 if (compressedOopsEnabled == null) { 958 Flag flag = getCommandLineFlag("UseCompressedOops"); 959 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 960 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 961 } 962 return compressedOopsEnabled.booleanValue(); 963 } 964 965 public boolean isCompressedKlassPointersEnabled() { 966 if (compressedKlassPointersEnabled == null) { 967 Flag flag = getCommandLineFlag("UseCompressedClassPointers"); 968 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: 969 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 970 } 971 return compressedKlassPointersEnabled.booleanValue(); 972 } 973 974 public boolean isCompactObjectHeadersEnabled() { 975 if (compactObjectHeadersEnabled == null) { 976 Flag flag = getCommandLineFlag("UseCompactObjectHeaders"); 977 compactObjectHeadersEnabled = (flag == null) ? Boolean.FALSE: 978 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 979 } 980 return compactObjectHeadersEnabled.booleanValue(); 981 } 982 983 public int getObjectAlignmentInBytes() { 984 if (objectAlignmentInBytes == 0) { 985 Flag flag = getCommandLineFlag("ObjectAlignmentInBytes"); 986 objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getInt(); 987 } 988 return objectAlignmentInBytes; 989 } 990 991 /** Indicates whether Thread-Local Allocation Buffers are used */ 992 public boolean getUseTLAB() { 993 Flag flag = getCommandLineFlag("UseTLAB"); 994 return (flag == null) ? false: flag.getBool(); 995 } 996 997 public boolean getCommandLineBooleanFlag(String name) { 998 Flag flag = getCommandLineFlag(name); 999 return (flag == null) ? Boolean.FALSE: 1000 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 1001 } 1002 1003 // returns null, if not available. 1004 public Flag[] getCommandLineFlags() { 1005 if (commandLineFlags == null) { 1006 readCommandLineFlags(); 1007 } 1008 1009 return commandLineFlags; 1010 } 1011 1012 public Flag getCommandLineFlag(String name) { 1013 if (flagsMap == null) { 1014 flagsMap = new HashMap<>(); 1015 Flag[] flags = getCommandLineFlags(); 1016 for (int i = 0; i < flags.length; i++) { 1017 flagsMap.put(flags[i].getName(), flags[i]); 1018 } 1019 } 1020 return flagsMap.get(name); 1021 } 1022 1023 private static final String cmdFlagTypes[] = { 1024 "bool", 1025 "int", 1026 "uint", 1027 "intx", 1028 "uintx", 1029 "uint64_t", 1030 "size_t", 1031 "double", 1032 "ccstr", 1033 "ccstrlist" 1034 }; 1035 1036 private String getFlagTypeAsString(int typeIndex) { 1037 if (0 <= typeIndex && typeIndex < cmdFlagTypes.length) { 1038 return cmdFlagTypes[typeIndex]; 1039 } else { 1040 return "unknown"; 1041 } 1042 } 1043 1044 private void readCommandLineFlags() { 1045 // get command line flags 1046 TypeDataBase db = getTypeDataBase(); 1047 Type flagType = db.lookupType("JVMFlag"); 1048 int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); 1049 // NOTE: last flag contains null values. 1050 commandLineFlags = new Flag[numFlags - 1]; 1051 1052 Address flagAddr = flagType.getAddressField("flags").getValue(); 1053 CIntField typeFld = new CIntField(flagType.getCIntegerField("_type"), 0); 1054 AddressField nameFld = flagType.getAddressField("_name"); 1055 AddressField addrFld = flagType.getAddressField("_addr"); 1056 CIntField flagsFld = new CIntField(flagType.getCIntegerField("_flags"), 0); 1057 1058 long flagSize = flagType.getSize(); // sizeof(Flag) 1059 1060 // NOTE: last flag contains null values. 1061 for (int f = 0; f < numFlags - 1; f++) { 1062 int typeIndex = (int)typeFld.getValue(flagAddr); 1063 String type = getFlagTypeAsString(typeIndex); 1064 String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); 1065 Address addr = addrFld.getValue(flagAddr); 1066 int flags = (int)flagsFld.getValue(flagAddr); 1067 commandLineFlags[f] = new Flag(type, name, addr, flags); 1068 flagAddr = flagAddr.addOffsetTo(flagSize); 1069 } 1070 1071 // sort flags by name 1072 Arrays.sort(commandLineFlags, new Comparator<>() { 1073 public int compare(Flag f1, Flag f2) { 1074 return f1.getName().compareTo(f2.getName()); 1075 } 1076 }); 1077 } 1078 1079 public String getSystemProperty(String key) { 1080 Properties props = getSystemProperties(); 1081 return (props != null)? props.getProperty(key) : null; 1082 } 1083 1084 public Properties getSystemProperties() { 1085 if (sysProps == null) { 1086 readSystemProperties(); 1087 } 1088 return sysProps; 1089 } 1090 1091 private void readSystemProperties() { 1092 final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); 1093 systemKls.iterateStaticFields(new DefaultOopVisitor() { 1094 ObjectReader objReader = new ObjectReader(); 1095 public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { 1096 if (field.getID().getName().equals("props")) { 1097 try { 1098 sysProps = (Properties) objReader.readObject(field.getValue(getObj())); 1099 } catch (Exception e) { 1100 e.printStackTrace(); 1101 } 1102 } 1103 } 1104 }); 1105 } 1106 }