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