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 & (minObjAlignmentInBytes - 1)) != 0) { 504 throw new RuntimeException("Object alignment " + minObjAlignmentInBytes + " is not power of two"); 505 } 506 507 logMinObjAlignmentInBytes = Integer.numberOfTrailingZeros(minObjAlignmentInBytes); 508 509 if (isCompressedOopsEnabled()) { 510 // Size info for oops within java objects is fixed 511 heapOopSize = (int)getIntSize(); 512 } else { 513 heapOopSize = (int)getOopSize(); 514 } 515 516 if (isCompressedKlassPointersEnabled()) { 517 klassPtrSize = (int)getIntSize(); 518 } else { 519 klassPtrSize = (int)getOopSize(); // same as an oop 520 } 521 } 522 523 /** This could be used by a reflective runtime system */ 524 public static void initialize(TypeDataBase db, boolean isBigEndian) { 525 if (soleInstance != null) { 526 throw new RuntimeException("Attempt to initialize VM twice"); 527 } 528 soleInstance = new VM(db, null, isBigEndian); 529 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 530 ((Observer) iter.next()).update(null, null); 531 } 532 } 533 534 /** This is used by the debugging system */ 535 public static void initialize(TypeDataBase db, JVMDebugger debugger) { 536 if (soleInstance != null) { 537 // Using multiple SA Tool classes in the same process creates a call here. 538 return; 539 } 540 soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian()); 541 542 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) { 543 ((Observer) iter.next()).update(null, null); 544 } 545 546 debugger.putHeapConst(soleInstance.getHeapOopSize(), soleInstance.getKlassPtrSize(), 547 CompressedOops.getBase(), CompressedOops.getShift(), 548 CompressedKlassPointers.getBase(), CompressedKlassPointers.getShift()); 549 } 550 551 /** This is used by the debugging system */ 552 public static void shutdown() { 553 soleInstance = null; 554 } 555 556 /** This is used by both the debugger and any runtime system. It is 557 the basic mechanism by which classes which mimic underlying VM 558 functionality cause themselves to be initialized. The given 559 observer will be notified (with arguments (null, null)) when the 560 VM is re-initialized, as well as when it registers itself with 561 the VM. */ 562 public static void registerVMInitializedObserver(Observer o) { 563 vmInitializedObservers.add(o); 564 o.update(null, null); 565 } 566 567 /** This is the primary accessor used by both the debugger and any 568 potential runtime system */ 569 public static VM getVM() { 570 if (soleInstance == null) { 571 throw new RuntimeException("VM.initialize() was not yet called"); 572 } 573 return soleInstance; 574 } 575 576 /** This is only used by the debugging system. The given observer 577 will be notified if the underlying VM resumes execution. NOTE 578 that the given observer is not triggered if the VM is currently 579 running and therefore differs in behavior from {@link 580 #registerVMInitializedObserver} (because of the possibility of 581 race conditions if the observer is added while the VM is being 582 suspended or resumed). */ 583 public void registerVMResumedObserver(Observer o) { 584 vmResumedObservers.add(o); 585 } 586 587 /** This is only used by the debugging system. The given observer 588 will be notified if the underlying VM suspends execution. NOTE 589 that the given observer is not triggered if the VM is currently 590 suspended and therefore differs in behavior from {@link 591 #registerVMInitializedObserver} (because of the possibility of 592 race conditions if the observer is added while the VM is being 593 suspended or resumed). */ 594 public void registerVMSuspendedObserver(Observer o) { 595 vmSuspendedObservers.add(o); 596 } 597 598 /** This is only used by the debugging system. Informs all 599 registered resumption observers that the VM has been resumed. 600 The application is responsible for actually having performed the 601 resumption. No OopHandles must be used after this point, as they 602 may move in the target address space due to garbage 603 collection. */ 604 public void fireVMResumed() { 605 for (Iterator iter = vmResumedObservers.iterator(); iter.hasNext(); ) { 606 ((Observer) iter.next()).update(null, null); 607 } 608 } 609 610 /** This is only used by the debugging system. Informs all 611 registered suspension observers that the VM has been suspended. 612 The application is responsible for actually having performed the 613 suspension. Garbage collection must be forbidden at this point; 614 for example, a JPDA-level suspension is not adequate since the 615 VM thread may still be running. */ 616 public void fireVMSuspended() { 617 for (Iterator iter = vmSuspendedObservers.iterator(); iter.hasNext(); ) { 618 ((Observer) iter.next()).update(null, null); 619 } 620 } 621 622 /** Returns the OS this VM is running on. Notice that by delegating 623 to the debugger we can transparently support remote 624 debugging. */ 625 public String getOS() { 626 if (debugger != null) { 627 return debugger.getOS(); 628 } 629 return PlatformInfo.getOS(); 630 } 631 632 /** Returns the CPU this VM is running on. Notice that by delegating 633 to the debugger we can transparently support remote 634 debugging. */ 635 public String getCPU() { 636 if (debugger != null) { 637 return debugger.getCPU(); 638 } 639 return PlatformInfo.getCPU(); 640 } 641 642 public Type lookupType(String cTypeName) { 643 return db.lookupType(cTypeName); 644 } 645 646 public Integer lookupIntConstant(String name) { 647 return db.lookupIntConstant(name); 648 } 649 650 // Convenience function for conversions 651 static public long getAddressValue(Address addr) { 652 return VM.getVM().getDebugger().getAddressValue(addr); 653 } 654 655 public long getAddressSize() { 656 return db.getAddressSize(); 657 } 658 659 public long getOopSize() { 660 return oopSize; 661 } 662 663 public long getLogAddressSize() { 664 return logAddressSize; 665 } 666 667 public long getIntSize() { 668 return db.getJIntType().getSize(); 669 } 670 671 /** Indicates whether the underlying machine supports the LP64 data 672 model. This is needed for conditionalizing code in a few places */ 673 public boolean isLP64() { 674 if (Assert.ASSERTS_ENABLED) { 675 Assert.that(isDebugging(), "Debugging system only for now"); 676 } 677 return isLP64; 678 } 679 680 /** Get bytes-per-long == long/double natural alignment. */ 681 public int getBytesPerLong() { 682 return bytesPerLong; 683 } 684 685 public int getBytesPerWord() { 686 return bytesPerWord; 687 } 688 689 /** Get minimum object alignment in bytes. */ 690 public int getMinObjAlignmentInBytes() { 691 return minObjAlignmentInBytes; 692 } 693 public int getLogMinObjAlignmentInBytes() { 694 return logMinObjAlignmentInBytes; 695 } 696 697 public int getHeapWordSize() { 698 return heapWordSize; 699 } 700 701 public int getHeapOopSize() { 702 return heapOopSize; 703 } 704 705 public int getKlassPtrSize() { 706 return klassPtrSize; 707 } 708 /** Utility routine for getting data structure alignment correct */ 709 public long alignUp(long size, long alignment) { 710 return (size + alignment - 1) & ~(alignment - 1); 711 } 712 713 /** Utility routine for getting data structure alignment correct */ 714 public long alignDown(long size, long alignment) { 715 return size & ~(alignment - 1); 716 } 717 718 /** Utility routine for building an int from two "unsigned" 16-bit 719 shorts */ 720 public int buildIntFromShorts(short low, short high) { 721 return (((int) high) << 16) | (((int) low) & 0xFFFF); 722 } 723 724 /** Utility routine for building a long from two "unsigned" 32-bit 725 ints in <b>platform-dependent</b> order */ 726 public long buildLongFromIntsPD(int oneHalf, int otherHalf) { 727 if (isBigEndian) { 728 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL); 729 } else{ 730 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL); 731 } 732 } 733 734 public TypeDataBase getTypeDataBase() { 735 return db; 736 } 737 738 public Universe getUniverse() { 739 if (universe == null) { 740 universe = new Universe(); 741 } 742 return universe; 743 } 744 745 public ObjectHeap getObjectHeap() { 746 if (heap == null) { 747 heap = new ObjectHeap(db); 748 } 749 return heap; 750 } 751 752 public SystemDictionary getSystemDictionary() { 753 if (dict == null) { 754 dict = new SystemDictionary(); 755 } 756 return dict; 757 } 758 759 public ClassLoaderDataGraph getClassLoaderDataGraph() { 760 if (cldGraph == null) { 761 cldGraph = new ClassLoaderDataGraph(); 762 } 763 return cldGraph; 764 } 765 766 public Threads getThreads() { 767 if (threads == null) { 768 threads = new Threads(); 769 } 770 return threads; 771 } 772 773 public ObjectSynchronizer getObjectSynchronizer() { 774 if (synchronizer == null) { 775 synchronizer = new ObjectSynchronizer(); 776 } 777 return synchronizer; 778 } 779 780 public JNIHandles getJNIHandles() { 781 if (handles == null) { 782 handles = new JNIHandles(); 783 } 784 return handles; 785 } 786 787 public Interpreter getInterpreter() { 788 if (interpreter == null) { 789 interpreter = new Interpreter(); 790 } 791 return interpreter; 792 } 793 794 public StubRoutines getStubRoutines() { 795 if (stubRoutines == null) { 796 stubRoutines = new StubRoutines(); 797 } 798 return stubRoutines; 799 } 800 801 public VMRegImpl getVMRegImplInfo() { 802 if (vmregImpl == null) { 803 vmregImpl = new VMRegImpl(); 804 } 805 return vmregImpl; 806 } 807 808 public FileMapInfo getFileMapInfo() { 809 if (!isSharingEnabled()) { 810 return null; 811 } 812 if (fileMapInfo == null) { 813 fileMapInfo = new FileMapInfo(); 814 } 815 return fileMapInfo; 816 } 817 818 public Bytes getBytes() { 819 if (bytes == null) { 820 bytes = new Bytes(debugger.getMachineDescription()); 821 } 822 return bytes; 823 } 824 825 /** Returns true if this is a isBigEndian, false otherwise */ 826 public boolean isBigEndian() { 827 return isBigEndian; 828 } 829 830 /** Returns true if JVMTI is supported, false otherwise */ 831 public boolean isJvmtiSupported() { 832 return isJvmtiSupported; 833 } 834 835 /** Returns true if this is a "core" build, false if either C1 or C2 836 is present */ 837 public boolean isCore() { 838 return (!(usingClientCompiler || usingServerCompiler)); 839 } 840 841 /** Returns true if this is a C1 build, false otherwise */ 842 public boolean isClientCompiler() { 843 return usingClientCompiler; 844 } 845 846 /** Returns true if this is a C2 build, false otherwise */ 847 public boolean isServerCompiler() { 848 return usingServerCompiler; 849 } 850 851 /** Returns true if C2 derived pointer table should be used, false otherwise */ 852 public boolean useDerivedPointerTable() { 853 return !disableDerivedPointerTableCheck; 854 } 855 856 /** Returns the code cache; should not be used if is core build */ 857 public CodeCache getCodeCache() { 858 if (Assert.ASSERTS_ENABLED) { 859 Assert.that(!isCore(), "noncore builds only"); 860 } 861 if (codeCache == null) { 862 codeCache = new CodeCache(); 863 } 864 return codeCache; 865 } 866 867 /** Should only be called for C1 builds */ 868 public Runtime1 getRuntime1() { 869 if (Assert.ASSERTS_ENABLED) { 870 Assert.that(isClientCompiler(), "C1 builds only"); 871 } 872 if (runtime1 == null) { 873 runtime1 = new Runtime1(); 874 } 875 return runtime1; 876 } 877 878 /** Test to see whether we're in debugging mode (NOTE: this really 879 should not be tested by this code; currently only used in 880 StackFrameStream) */ 881 public boolean isDebugging() { 882 return (debugger != null); 883 } 884 885 /** This is only used by the debugging (i.e., non-runtime) system */ 886 public JVMDebugger getDebugger() { 887 if (debugger == null) { 888 throw new RuntimeException("Attempt to use debugger in runtime system"); 889 } 890 return debugger; 891 } 892 893 /** Indicates whether a given program counter is in Java code. This 894 includes but is not spanned by the interpreter and code cache. 895 Only used in the debugging system, for implementing 896 JavaThread.currentFrameGuess() on x86. */ 897 public boolean isJavaPCDbg(Address addr) { 898 // FIXME: this is not a complete enough set: must include areas 899 // like vtable stubs 900 return (getInterpreter().contains(addr) || 901 getCodeCache().contains(addr)); 902 } 903 904 /** FIXME: figure out where to stick this */ 905 public int getInvocationEntryBCI() { 906 return invocationEntryBCI; 907 } 908 909 // FIXME: figure out where to stick this 910 public boolean wizardMode() { 911 return true; 912 } 913 914 public ReversePtrs getRevPtrs() { 915 return revPtrs; 916 } 917 918 public void setRevPtrs(ReversePtrs rp) { 919 revPtrs = rp; 920 } 921 922 // returns null, if not available. 923 public String getVMRelease() { 924 return vmRelease; 925 } 926 927 // returns null, if not available. 928 public String getVMInternalInfo() { 929 return vmInternalInfo; 930 } 931 932 public int getReserveForAllocationPrefetch() { 933 return reserveForAllocationPrefetch; 934 } 935 936 public boolean isSharingEnabled() { 937 if (sharingEnabled == null) { 938 Flag flag = getCommandLineFlag("UseSharedSpaces"); 939 sharingEnabled = (flag == null)? Boolean.FALSE : 940 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 941 } 942 return sharingEnabled.booleanValue(); 943 } 944 945 public boolean isCompressedOopsEnabled() { 946 if (compressedOopsEnabled == null) { 947 Flag flag = getCommandLineFlag("UseCompressedOops"); 948 compressedOopsEnabled = (flag == null) ? Boolean.FALSE: 949 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 950 } 951 return compressedOopsEnabled.booleanValue(); 952 } 953 954 public boolean isCompressedKlassPointersEnabled() { 955 if (compressedKlassPointersEnabled == null) { 956 Flag flag = getCommandLineFlag("UseCompressedClassPointers"); 957 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: 958 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 959 } 960 return compressedKlassPointersEnabled.booleanValue(); 961 } 962 963 public int getObjectAlignmentInBytes() { 964 if (objectAlignmentInBytes == 0) { 965 Flag flag = getCommandLineFlag("ObjectAlignmentInBytes"); 966 objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getIntx(); 967 } 968 return objectAlignmentInBytes; 969 } 970 971 /** Indicates whether Thread-Local Allocation Buffers are used */ 972 public boolean getUseTLAB() { 973 Flag flag = getCommandLineFlag("UseTLAB"); 974 return (flag == null) ? false: flag.getBool(); 975 } 976 977 public boolean getCommandLineBooleanFlag(String name) { 978 Flag flag = getCommandLineFlag(name); 979 return (flag == null) ? Boolean.FALSE: 980 (flag.getBool()? Boolean.TRUE: Boolean.FALSE); 981 } 982 983 // returns null, if not available. 984 public Flag[] getCommandLineFlags() { 985 if (commandLineFlags == null) { 986 readCommandLineFlags(); 987 } 988 989 return commandLineFlags; 990 } 991 992 public Flag getCommandLineFlag(String name) { 993 if (flagsMap == null) { 994 flagsMap = new HashMap<>(); 995 Flag[] flags = getCommandLineFlags(); 996 for (int i = 0; i < flags.length; i++) { 997 flagsMap.put(flags[i].getName(), flags[i]); 998 } 999 } 1000 return (Flag) flagsMap.get(name); 1001 } 1002 1003 private static final String cmdFlagTypes[] = { 1004 "bool", 1005 "int", 1006 "uint", 1007 "intx", 1008 "uintx", 1009 "uint64_t", 1010 "size_t", 1011 "double", 1012 "ccstr", 1013 "ccstrlist" 1014 }; 1015 1016 private String getFlagTypeAsString(int typeIndex) { 1017 if (0 <= typeIndex && typeIndex < cmdFlagTypes.length) { 1018 return cmdFlagTypes[typeIndex]; 1019 } else { 1020 return "unknown"; 1021 } 1022 } 1023 1024 private void readCommandLineFlags() { 1025 // get command line flags 1026 TypeDataBase db = getTypeDataBase(); 1027 Type flagType = db.lookupType("JVMFlag"); 1028 int numFlags = (int) flagType.getCIntegerField("numFlags").getValue(); 1029 // NOTE: last flag contains null values. 1030 commandLineFlags = new Flag[numFlags - 1]; 1031 1032 Address flagAddr = flagType.getAddressField("flags").getValue(); 1033 CIntField typeFld = new CIntField(flagType.getCIntegerField("_type"), 0); 1034 AddressField nameFld = flagType.getAddressField("_name"); 1035 AddressField addrFld = flagType.getAddressField("_addr"); 1036 CIntField flagsFld = new CIntField(flagType.getCIntegerField("_flags"), 0); 1037 1038 long flagSize = flagType.getSize(); // sizeof(Flag) 1039 1040 // NOTE: last flag contains null values. 1041 for (int f = 0; f < numFlags - 1; f++) { 1042 int typeIndex = (int)typeFld.getValue(flagAddr); 1043 String type = getFlagTypeAsString(typeIndex); 1044 String name = CStringUtilities.getString(nameFld.getValue(flagAddr)); 1045 Address addr = addrFld.getValue(flagAddr); 1046 int flags = (int)flagsFld.getValue(flagAddr); 1047 commandLineFlags[f] = new Flag(type, name, addr, flags); 1048 flagAddr = flagAddr.addOffsetTo(flagSize); 1049 } 1050 1051 // sort flags by name 1052 Arrays.sort(commandLineFlags, new Comparator<>() { 1053 public int compare(Flag f1, Flag f2) { 1054 return f1.getName().compareTo(f2.getName()); 1055 } 1056 }); 1057 } 1058 1059 public String getSystemProperty(String key) { 1060 Properties props = getSystemProperties(); 1061 return (props != null)? props.getProperty(key) : null; 1062 } 1063 1064 public Properties getSystemProperties() { 1065 if (sysProps == null) { 1066 readSystemProperties(); 1067 } 1068 return sysProps; 1069 } 1070 1071 private void readSystemProperties() { 1072 final InstanceKlass systemKls = getSystemDictionary().getSystemKlass(); 1073 systemKls.iterateStaticFields(new DefaultOopVisitor() { 1074 ObjectReader objReader = new ObjectReader(); 1075 public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) { 1076 if (field.getID().getName().equals("props")) { 1077 try { 1078 sysProps = (Properties) objReader.readObject(field.getValue(getObj())); 1079 } catch (Exception e) { 1080 e.printStackTrace(); 1081 } 1082 } 1083 } 1084 }); 1085 } 1086 }