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 }