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