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
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 versionPropVal = saProps.getProperty(versionProp);
363 if (versionPropVal == null) {
364 throw new RuntimeException("Missing property " + versionProp);
365 }
366
367 var saVersion = Runtime.Version.parse(versionPropVal);
368 var vmVersion = Runtime.Version.parse(vmRelease);
369
370 if (saVersion.equals(vmVersion)) {
371 // Exact match
372 return;
373 }
374 if (!saVersion.equalsIgnoreOptional(vmVersion)) {
375 // Throw exception if different release versions:
376 // <version>+<build>
377 throw new VMVersionMismatchException(saVersion, vmVersion);
378 } else {
379 // Otherwise print warning to allow mismatch not release versions
380 // during development.
381 System.err.println("WARNING: Hotspot VM version " + vmVersion +
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 logBytesPerWord = db.lookupIntConstant("LogBytesPerWord").intValue();
482 heapWordSize = db.lookupIntConstant("HeapWordSize").intValue();
483 Flags_DEFAULT = db.lookupIntConstant("JVMFlagOrigin::DEFAULT").intValue();
484 Flags_COMMAND_LINE = db.lookupIntConstant("JVMFlagOrigin::COMMAND_LINE").intValue();
485 Flags_ENVIRON_VAR = db.lookupIntConstant("JVMFlagOrigin::ENVIRON_VAR").intValue();
486 Flags_CONFIG_FILE = db.lookupIntConstant("JVMFlagOrigin::CONFIG_FILE").intValue();
487 Flags_MANAGEMENT = db.lookupIntConstant("JVMFlagOrigin::MANAGEMENT").intValue();
488 Flags_ERGONOMIC = db.lookupIntConstant("JVMFlagOrigin::ERGONOMIC").intValue();
489 Flags_ATTACH_ON_DEMAND = db.lookupIntConstant("JVMFlagOrigin::ATTACH_ON_DEMAND").intValue();
490 Flags_INTERNAL = db.lookupIntConstant("JVMFlagOrigin::INTERNAL").intValue();
491 Flags_JIMAGE_RESOURCE = db.lookupIntConstant("JVMFlagOrigin::JIMAGE_RESOURCE").intValue();
492 Flags_VALUE_ORIGIN_MASK = db.lookupIntConstant("JVMFlag::VALUE_ORIGIN_MASK").intValue();
493 Flags_WAS_SET_ON_COMMAND_LINE = db.lookupIntConstant("JVMFlag::WAS_SET_ON_COMMAND_LINE").intValue();
494 oopSize = db.lookupIntConstant("oopSize").intValue();
495
496 intType = db.lookupType("int");
497 uintType = db.lookupType("uint");
498 intxType = db.lookupType("intx");
499 uintxType = db.lookupType("uintx");
500 sizetType = db.lookupType("size_t");
501 uint64tType = db.lookupType("uint64_t");
502 boolType = (CIntegerType) db.lookupType("bool");
503
504 minObjAlignmentInBytes = getObjectAlignmentInBytes();
505 if ((minObjAlignmentInBytes & (minObjAlignmentInBytes - 1)) != 0) {
506 throw new RuntimeException("Object alignment " + minObjAlignmentInBytes + " is not power of two");
507 }
508
509 logMinObjAlignmentInBytes = Integer.numberOfTrailingZeros(minObjAlignmentInBytes);
510
511 if (isCompressedOopsEnabled()) {
512 // Size info for oops within java objects is fixed
513 heapOopSize = (int)getIntSize();
514 } else {
515 heapOopSize = (int)getOopSize();
516 }
517
518 if (isCompressedKlassPointersEnabled()) {
519 klassPtrSize = (int)getIntSize();
520 } else {
521 klassPtrSize = (int)getOopSize(); // same as an oop
522 }
523 }
524
525 /** This could be used by a reflective runtime system */
526 public static void initialize(TypeDataBase db, boolean isBigEndian) {
527 if (soleInstance != null) {
528 throw new RuntimeException("Attempt to initialize VM twice");
529 }
530 soleInstance = new VM(db, null, isBigEndian);
531 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
532 ((Observer) iter.next()).update(null, null);
533 }
534 }
535
536 /** This is used by the debugging system */
537 public static void initialize(TypeDataBase db, JVMDebugger debugger) {
538 if (soleInstance != null) {
539 // Using multiple SA Tool classes in the same process creates a call here.
540 return;
541 }
542 soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian());
543
544 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
545 ((Observer) iter.next()).update(null, null);
546 }
547
548 debugger.putHeapConst(soleInstance.getHeapOopSize(), soleInstance.getKlassPtrSize(),
549 CompressedOops.getBase(), CompressedOops.getShift(),
550 CompressedKlassPointers.getBase(), CompressedKlassPointers.getShift());
551 }
552
553 /** This is used by the debugging system */
554 public static void shutdown() {
555 soleInstance = null;
556 }
557
558 /** This is used by both the debugger and any runtime system. It is
559 the basic mechanism by which classes which mimic underlying VM
560 functionality cause themselves to be initialized. The given
561 observer will be notified (with arguments (null, null)) when the
562 VM is re-initialized, as well as when it registers itself with
563 the VM. */
564 public static void registerVMInitializedObserver(Observer o) {
565 vmInitializedObservers.add(o);
566 o.update(null, null);
567 }
568
569 /** This is the primary accessor used by both the debugger and any
570 potential runtime system */
571 public static VM getVM() {
572 if (soleInstance == null) {
573 throw new RuntimeException("VM.initialize() was not yet called");
574 }
575 return soleInstance;
576 }
577
578 /** This is only used by the debugging system. The given observer
579 will be notified if the underlying VM resumes execution. NOTE
580 that the given observer is not triggered if the VM is currently
581 running and therefore differs in behavior from {@link
582 #registerVMInitializedObserver} (because of the possibility of
583 race conditions if the observer is added while the VM is being
584 suspended or resumed). */
585 public void registerVMResumedObserver(Observer o) {
586 vmResumedObservers.add(o);
587 }
588
589 /** This is only used by the debugging system. The given observer
590 will be notified if the underlying VM suspends execution. NOTE
591 that the given observer is not triggered if the VM is currently
592 suspended and therefore differs in behavior from {@link
593 #registerVMInitializedObserver} (because of the possibility of
594 race conditions if the observer is added while the VM is being
595 suspended or resumed). */
596 public void registerVMSuspendedObserver(Observer o) {
597 vmSuspendedObservers.add(o);
598 }
599
600 /** This is only used by the debugging system. Informs all
601 registered resumption observers that the VM has been resumed.
602 The application is responsible for actually having performed the
603 resumption. No OopHandles must be used after this point, as they
604 may move in the target address space due to garbage
605 collection. */
606 public void fireVMResumed() {
607 for (Iterator iter = vmResumedObservers.iterator(); iter.hasNext(); ) {
608 ((Observer) iter.next()).update(null, null);
609 }
610 }
611
612 /** This is only used by the debugging system. Informs all
613 registered suspension observers that the VM has been suspended.
614 The application is responsible for actually having performed the
615 suspension. Garbage collection must be forbidden at this point;
616 for example, a JPDA-level suspension is not adequate since the
617 VM thread may still be running. */
618 public void fireVMSuspended() {
619 for (Iterator iter = vmSuspendedObservers.iterator(); iter.hasNext(); ) {
620 ((Observer) iter.next()).update(null, null);
621 }
622 }
623
624 /** Returns the OS this VM is running on. Notice that by delegating
625 to the debugger we can transparently support remote
626 debugging. */
627 public String getOS() {
628 if (debugger != null) {
629 return debugger.getOS();
630 }
631 return PlatformInfo.getOS();
632 }
633
634 /** Returns the CPU this VM is running on. Notice that by delegating
635 to the debugger we can transparently support remote
636 debugging. */
637 public String getCPU() {
638 if (debugger != null) {
639 return debugger.getCPU();
640 }
641 return PlatformInfo.getCPU();
642 }
643
644 public Type lookupType(String cTypeName) {
645 return db.lookupType(cTypeName);
646 }
647
648 public Integer lookupIntConstant(String name) {
649 return db.lookupIntConstant(name);
650 }
651
652 // Convenience function for conversions
653 public static long getAddressValue(Address addr) {
654 return VM.getVM().getDebugger().getAddressValue(addr);
655 }
656
657 public long getAddressSize() {
658 return db.getAddressSize();
659 }
660
661 public long getOopSize() {
662 return oopSize;
663 }
664
665 public long getLogAddressSize() {
666 return logAddressSize;
667 }
668
669 public long getIntSize() {
670 return db.getJIntType().getSize();
671 }
672
673 /** Indicates whether the underlying machine supports the LP64 data
674 model. This is needed for conditionalizing code in a few places */
675 public boolean isLP64() {
676 if (Assert.ASSERTS_ENABLED) {
677 Assert.that(isDebugging(), "Debugging system only for now");
678 }
679 return isLP64;
680 }
681
682 /** Get bytes-per-long == long/double natural alignment. */
683 public int getBytesPerLong() {
684 return bytesPerLong;
685 }
686
687 public int getBytesPerWord() {
688 return bytesPerWord;
689 }
690
691 public int getLogBytesPerWord() {
692 return logBytesPerWord;
693 }
694
695 /** Get minimum object alignment in bytes. */
696 public int getMinObjAlignmentInBytes() {
697 return minObjAlignmentInBytes;
698 }
699 public int getLogMinObjAlignmentInBytes() {
700 return logMinObjAlignmentInBytes;
701 }
702
703 public int getHeapWordSize() {
704 return heapWordSize;
705 }
706
707 public int getHeapOopSize() {
708 return heapOopSize;
709 }
710
711 public int getKlassPtrSize() {
712 return klassPtrSize;
713 }
714 /** Utility routine for getting data structure alignment correct */
715 public long alignUp(long size, long alignment) {
716 return (size + alignment - 1) & ~(alignment - 1);
717 }
718
719 /** Utility routine for getting data structure alignment correct */
720 public long alignDown(long size, long alignment) {
721 return size & ~(alignment - 1);
722 }
723
724 /** Utility routine for building an int from two "unsigned" 16-bit
725 shorts */
726 public int buildIntFromShorts(short low, short high) {
727 return (((int) high) << 16) | (((int) low) & 0xFFFF);
728 }
729
730 /** Utility routine for building a long from two "unsigned" 32-bit
731 ints in <b>platform-dependent</b> order */
732 public long buildLongFromIntsPD(int oneHalf, int otherHalf) {
733 if (isBigEndian) {
734 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL);
735 } else{
736 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL);
737 }
738 }
739
740 public TypeDataBase getTypeDataBase() {
741 return db;
742 }
743
744 public Universe getUniverse() {
745 if (universe == null) {
746 universe = new Universe();
747 }
748 return universe;
749 }
750
751 public ObjectHeap getObjectHeap() {
752 if (heap == null) {
753 heap = new ObjectHeap(db);
754 }
755 return heap;
756 }
757
758 public SystemDictionary getSystemDictionary() {
759 if (dict == null) {
760 dict = new SystemDictionary();
761 }
762 return dict;
763 }
764
765 public ClassLoaderDataGraph getClassLoaderDataGraph() {
766 if (cldGraph == null) {
767 cldGraph = new ClassLoaderDataGraph();
768 }
769 return cldGraph;
770 }
771
772 public Threads getThreads() {
773 if (threads == null) {
774 threads = new Threads();
775 }
776 return threads;
777 }
778
779 public ObjectSynchronizer getObjectSynchronizer() {
780 if (synchronizer == null) {
781 synchronizer = new ObjectSynchronizer();
782 }
783 return synchronizer;
784 }
785
786 public JNIHandles getJNIHandles() {
787 if (handles == null) {
788 handles = new JNIHandles();
789 }
790 return handles;
791 }
792
793 public Interpreter getInterpreter() {
794 if (interpreter == null) {
795 interpreter = new Interpreter();
796 }
797 return interpreter;
798 }
799
800 public StubRoutines getStubRoutines() {
801 if (stubRoutines == null) {
802 stubRoutines = new StubRoutines();
803 }
804 return stubRoutines;
805 }
806
807 public VMRegImpl getVMRegImplInfo() {
808 if (vmregImpl == null) {
809 vmregImpl = new VMRegImpl();
810 }
811 return vmregImpl;
812 }
813
814 public FileMapInfo getFileMapInfo() {
815 if (!isSharingEnabled()) {
816 return null;
817 }
818 if (fileMapInfo == null) {
819 fileMapInfo = new FileMapInfo();
820 }
821 return fileMapInfo;
822 }
823
824 public Bytes getBytes() {
825 if (bytes == null) {
826 bytes = new Bytes(debugger.getMachineDescription());
827 }
828 return bytes;
829 }
830
831 /** Returns true if this is a isBigEndian, false otherwise */
832 public boolean isBigEndian() {
833 return isBigEndian;
834 }
835
836 /** Returns true if JVMTI is supported, false otherwise */
837 public boolean isJvmtiSupported() {
838 return isJvmtiSupported;
839 }
840
841 /** Returns true if this is a "core" build, false if either C1 or C2
842 is present */
843 public boolean isCore() {
844 return (!(usingClientCompiler || usingServerCompiler));
845 }
846
847 /** Returns true if this is a C1 build, false otherwise */
848 public boolean isClientCompiler() {
849 return usingClientCompiler;
850 }
851
852 /** Returns true if this is a C2 build, false otherwise */
853 public boolean isServerCompiler() {
854 return usingServerCompiler;
855 }
856
857 /** Returns true if C2 derived pointer table should be used, false otherwise */
858 public boolean useDerivedPointerTable() {
859 return !disableDerivedPointerTableCheck;
860 }
861
862 /** Returns the code cache; should not be used if is core build */
863 public CodeCache getCodeCache() {
864 if (Assert.ASSERTS_ENABLED) {
865 Assert.that(!isCore(), "noncore builds only");
866 }
867 if (codeCache == null) {
868 codeCache = new CodeCache();
869 }
870 return codeCache;
871 }
872
873 /** Should only be called for C1 builds */
874 public Runtime1 getRuntime1() {
875 if (Assert.ASSERTS_ENABLED) {
876 Assert.that(isClientCompiler(), "C1 builds only");
877 }
878 if (runtime1 == null) {
879 runtime1 = new Runtime1();
880 }
881 return runtime1;
882 }
883
884 /** Test to see whether we're in debugging mode (NOTE: this really
885 should not be tested by this code; currently only used in
886 StackFrameStream) */
887 public boolean isDebugging() {
888 return (debugger != null);
889 }
890
891 /** This is only used by the debugging (i.e., non-runtime) system */
892 public JVMDebugger getDebugger() {
893 if (debugger == null) {
894 throw new RuntimeException("Attempt to use debugger in runtime system");
895 }
896 return debugger;
897 }
898
899 /** Indicates whether a given program counter is in Java code. This
900 includes but is not spanned by the interpreter and code cache.
901 Only used in the debugging system, for implementing
902 JavaThread.currentFrameGuess() on x86. */
903 public boolean isJavaPCDbg(Address addr) {
904 // FIXME: this is not a complete enough set: must include areas
905 // like vtable stubs
906 return (getInterpreter().contains(addr) ||
907 getCodeCache().contains(addr));
908 }
909
910 /** FIXME: figure out where to stick this */
911 public int getInvocationEntryBCI() {
912 return invocationEntryBCI;
913 }
914
915 // FIXME: figure out where to stick this
916 public boolean wizardMode() {
917 return true;
918 }
919
920 public ReversePtrs getRevPtrs() {
921 return revPtrs;
922 }
923
924 public void setRevPtrs(ReversePtrs rp) {
925 revPtrs = rp;
926 }
927
928 // returns null, if not available.
929 public String getVMRelease() {
930 return vmRelease;
931 }
932
933 // returns null, if not available.
934 public String getVMInternalInfo() {
935 return vmInternalInfo;
936 }
937
938 public int getReserveForAllocationPrefetch() {
939 return reserveForAllocationPrefetch;
940 }
941
942 public boolean isSharingEnabled() {
943 if (sharingEnabled == null) {
944 Address address = VM.getVM().getDebugger().lookup(null, "UseSharedSpaces");
945 if (address == null && getOS().equals("win32")) {
946 // On Win32 symbols are prefixed with the dll name. So look for
947 // UseSharedSpaces as a symbol in jvm.dll.
948 address = VM.getVM().getDebugger().lookup(null, "jvm!UseSharedSpaces");
949 }
950 sharingEnabled = address.getJBooleanAt(0);
951 }
952 return sharingEnabled.booleanValue();
953 }
954
955 public boolean isCompressedOopsEnabled() {
956 if (compressedOopsEnabled == null) {
957 Flag flag = getCommandLineFlag("UseCompressedOops");
958 compressedOopsEnabled = (flag == null) ? Boolean.FALSE:
959 (flag.getBool()? Boolean.TRUE: Boolean.FALSE);
960 }
961 return compressedOopsEnabled.booleanValue();
962 }
963
964 public boolean isCompressedKlassPointersEnabled() {
965 if (compressedKlassPointersEnabled == null) {
966 Flag flag = getCommandLineFlag("UseCompressedClassPointers");
967 compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE:
968 (flag.getBool()? Boolean.TRUE: Boolean.FALSE);
969 }
970 return compressedKlassPointersEnabled.booleanValue();
971 }
972
973 public int getObjectAlignmentInBytes() {
974 if (objectAlignmentInBytes == 0) {
975 Flag flag = getCommandLineFlag("ObjectAlignmentInBytes");
976 objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getInt();
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 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 }