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