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