0
|
1 /*
|
|
2 * Copyright 2000-2007 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
|
20 * CA 95054 USA or visit www.sun.com if you need additional information or
|
|
21 * have any 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.debugger.*;
|
|
34 import sun.jvm.hotspot.interpreter.*;
|
|
35 import sun.jvm.hotspot.memory.*;
|
|
36 import sun.jvm.hotspot.oops.*;
|
|
37 import sun.jvm.hotspot.types.*;
|
|
38 import sun.jvm.hotspot.utilities.*;
|
|
39
|
|
40 /** <P> This class encapsulates the global state of the VM; the
|
|
41 universe, object heap, interpreter, etc. It is a Singleton and
|
|
42 must be initialized with a call to initialize() before calling
|
|
43 getVM(). </P>
|
|
44
|
|
45 <P> Many auxiliary classes (i.e., most of the VMObjects) keep
|
|
46 needed field offsets in the form of static Field objects. In a
|
|
47 debugging system, the VM might be shutdown and re-initialized (on
|
|
48 a differently-configured build, i.e., 32- vs. 64-bit), and all old
|
|
49 cached state (including fields and field offsets) must be
|
|
50 flushed. </P>
|
|
51
|
|
52 <P> An Observer pattern is used to implement the initialization of
|
|
53 such classes. Each such class, in its static initializer,
|
|
54 registers an Observer with the VM class via
|
|
55 VM.registerVMInitializedObserver(). This Observer is guaranteed to
|
|
56 be notified whenever the VM is initialized (or re-initialized). To
|
|
57 implement the first-time initialization, the observer is also
|
|
58 notified when it registers itself with the VM. (For bootstrapping
|
|
59 reasons, this implies that the constructor of VM can not
|
|
60 instantiate any such objects, since VM.soleInstance will not have
|
|
61 been set yet. This is a bootstrapping issue which may have to be
|
|
62 revisited later.) </P>
|
|
63 */
|
|
64
|
|
65 public class VM {
|
|
66 private static VM soleInstance;
|
|
67 private static List vmInitializedObservers = new ArrayList();
|
|
68 private List vmResumedObservers = new ArrayList();
|
|
69 private List vmSuspendedObservers = new ArrayList();
|
|
70 private TypeDataBase db;
|
|
71 private boolean isBigEndian;
|
|
72 /** This is only present if in a debugging system */
|
|
73 private JVMDebugger debugger;
|
|
74 private long stackBias;
|
|
75 private long logAddressSize;
|
|
76 private Universe universe;
|
|
77 private ObjectHeap heap;
|
|
78 private SymbolTable symbols;
|
|
79 private StringTable strings;
|
|
80 private SystemDictionary dict;
|
|
81 private Threads threads;
|
|
82 private ObjectSynchronizer synchronizer;
|
|
83 private JNIHandles handles;
|
|
84 private Interpreter interpreter;
|
|
85 private StubRoutines stubRoutines;
|
|
86 private Bytes bytes;
|
|
87 /** Flags indicating whether we are attached to a core, C1, or C2 build */
|
|
88 private boolean usingClientCompiler;
|
|
89 private boolean usingServerCompiler;
|
|
90 /** Flag indicating whether UseTLAB is turned on */
|
|
91 private boolean useTLAB;
|
|
92 /** alignment constants */
|
|
93 private boolean isLP64;
|
|
94 private int bytesPerLong;
|
|
95 private int minObjAlignmentInBytes;
|
|
96 /** This is only present in a non-core build */
|
|
97 private CodeCache codeCache;
|
|
98 /** This is only present in a C1 build */
|
|
99 private Runtime1 runtime1;
|
|
100 /** These constants come from globalDefinitions.hpp */
|
|
101 private int invocationEntryBCI;
|
|
102 private int invalidOSREntryBCI;
|
|
103 private ReversePtrs revPtrs;
|
|
104 private VMRegImpl vmregImpl;
|
|
105
|
|
106 // System.getProperties from debuggee VM
|
|
107 private Properties sysProps;
|
|
108
|
|
109 // VM version strings come from Abstract_VM_Version class
|
|
110 private String vmRelease;
|
|
111 private String vmInternalInfo;
|
|
112
|
|
113 private Flag[] commandLineFlags;
|
|
114 private Map flagsMap;
|
|
115
|
|
116 private static Type intxType;
|
|
117 private static Type uintxType;
|
|
118 private static CIntegerType boolType;
|
|
119 private Boolean sharingEnabled;
|
|
120
|
|
121 // command line flags supplied to VM - see struct Flag in globals.hpp
|
|
122 public static final class Flag {
|
|
123 private String type;
|
|
124 private String name;
|
|
125 private Address addr;
|
|
126 private String kind;
|
|
127
|
|
128 private Flag(String type, String name, Address addr, String kind) {
|
|
129 this.type = type;
|
|
130 this.name = name;
|
|
131 this.addr = addr;
|
|
132 this.kind = kind;
|
|
133 }
|
|
134
|
|
135 public String getType() {
|
|
136 return type;
|
|
137 }
|
|
138
|
|
139 public String getName() {
|
|
140 return name;
|
|
141 }
|
|
142
|
|
143 public Address getAddress() {
|
|
144 return addr;
|
|
145 }
|
|
146
|
|
147 public String getKind() {
|
|
148 return kind;
|
|
149 }
|
|
150
|
|
151 public boolean isBool() {
|
|
152 return type.equals("bool");
|
|
153 }
|
|
154
|
|
155 public boolean getBool() {
|
|
156 if (Assert.ASSERTS_ENABLED) {
|
|
157 Assert.that(isBool(), "not a bool flag!");
|
|
158 }
|
|
159 return addr.getCIntegerAt(0, boolType.getSize(), boolType.isUnsigned())
|
|
160 != 0;
|
|
161 }
|
|
162
|
|
163 public boolean isIntx() {
|
|
164 return type.equals("intx");
|
|
165 }
|
|
166
|
|
167 public long getIntx() {
|
|
168 if (Assert.ASSERTS_ENABLED) {
|
|
169 Assert.that(isIntx(), "not a intx flag!");
|
|
170 }
|
|
171 return addr.getCIntegerAt(0, intxType.getSize(), false);
|
|
172 }
|
|
173
|
|
174 public boolean isUIntx() {
|
|
175 return type.equals("uintx");
|
|
176 }
|
|
177
|
|
178 public long getUIntx() {
|
|
179 if (Assert.ASSERTS_ENABLED) {
|
|
180 Assert.that(isUIntx(), "not a uintx flag!");
|
|
181 }
|
|
182 return addr.getCIntegerAt(0, uintxType.getSize(), true);
|
|
183 }
|
|
184
|
|
185 public String getValue() {
|
|
186 if (isBool()) {
|
|
187 return new Boolean(getBool()).toString();
|
|
188 } else if (isIntx()) {
|
|
189 return new Long(getIntx()).toString();
|
|
190 } else if (isUIntx()) {
|
|
191 return new Long(getUIntx()).toString();
|
|
192 } else {
|
|
193 return null;
|
|
194 }
|
|
195 }
|
|
196 };
|
|
197
|
|
198 private static void checkVMVersion(String vmRelease) {
|
|
199 if (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null) {
|
|
200 // read sa build version.
|
|
201 String versionProp = "sun.jvm.hotspot.runtime.VM.saBuildVersion";
|
|
202 String saVersion = saProps.getProperty(versionProp);
|
|
203 if (saVersion == null)
|
|
204 throw new RuntimeException("Missing property " + versionProp);
|
|
205
|
|
206 // Strip nonproduct VM version substring (note: saVersion doesn't have it).
|
|
207 String vmVersion = vmRelease.replaceAll("(-fastdebug)|(-debug)|(-jvmg)|(-optimized)|(-profiled)","");
|
|
208
|
|
209 if (saVersion.equals(vmVersion)) {
|
|
210 // Exact match
|
|
211 return;
|
|
212 }
|
|
213 if (saVersion.indexOf('-') == saVersion.lastIndexOf('-') &&
|
|
214 vmVersion.indexOf('-') == vmVersion.lastIndexOf('-')) {
|
|
215 // Throw exception if different release versions:
|
|
216 // <major>.<minor>-b<n>
|
|
217 throw new VMVersionMismatchException(saVersion, vmRelease);
|
|
218 } else {
|
|
219 // Otherwise print warning to allow mismatch not release versions
|
|
220 // during development.
|
|
221 System.err.println("WARNING: Hotspot VM version " + vmRelease +
|
|
222 " does not match with SA version " + saVersion +
|
|
223 "." + " You may see unexpected results. ");
|
|
224 }
|
|
225 } else {
|
|
226 System.err.println("WARNING: You have disabled SA and VM version check. You may be " +
|
|
227 "using incompatible version of SA and you may see unexpected " +
|
|
228 "results.");
|
|
229 }
|
|
230 }
|
|
231
|
|
232 private static final boolean disableDerivedPrinterTableCheck;
|
|
233 private static final Properties saProps;
|
|
234
|
|
235 static {
|
|
236 saProps = new Properties();
|
|
237 URL url = null;
|
|
238 try {
|
|
239 url = VM.class.getClassLoader().getResource("sa.properties");
|
|
240 saProps.load(new BufferedInputStream(url.openStream()));
|
|
241 } catch (Exception e) {
|
|
242 throw new RuntimeException("Unable to load properties " +
|
|
243 (url == null ? "null" : url.toString()) +
|
|
244 ": " + e.getMessage());
|
|
245 }
|
|
246
|
|
247 disableDerivedPrinterTableCheck = System.getProperty("sun.jvm.hotspot.runtime.VM.disableDerivedPointerTableCheck") != null;
|
|
248 }
|
|
249
|
|
250 private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) {
|
|
251 this.db = db;
|
|
252 this.debugger = debugger;
|
|
253 this.isBigEndian = isBigEndian;
|
|
254
|
|
255 // Note that we don't construct universe, heap, threads,
|
|
256 // interpreter, or stubRoutines here (any more). The current
|
|
257 // initialization mechanisms require that the VM be completely set
|
|
258 // up (i.e., out of its constructor, with soleInstance assigned)
|
|
259 // before their static initializers are run.
|
|
260
|
|
261 if (db.getAddressSize() == 4) {
|
|
262 logAddressSize = 2;
|
|
263 } else if (db.getAddressSize() == 8) {
|
|
264 logAddressSize = 3;
|
|
265 } else {
|
|
266 throw new RuntimeException("Address size " + db.getAddressSize() + " not yet supported");
|
|
267 }
|
|
268
|
|
269 // read VM version info
|
|
270 try {
|
|
271 Type vmVersion = db.lookupType("Abstract_VM_Version");
|
|
272 Address releaseAddr = vmVersion.getAddressField("_s_vm_release").getValue();
|
|
273 vmRelease = CStringUtilities.getString(releaseAddr);
|
|
274 Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue();
|
|
275 vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr);
|
|
276 } catch (Exception exp) {
|
|
277 throw new RuntimeException("can't determine target's VM version : " + exp.getMessage());
|
|
278 }
|
|
279
|
|
280 checkVMVersion(vmRelease);
|
|
281
|
|
282 stackBias = db.lookupIntConstant("STACK_BIAS").intValue();
|
|
283 invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue();
|
|
284 invalidOSREntryBCI = db.lookupIntConstant("InvalidOSREntryBci").intValue();
|
|
285
|
|
286 // We infer the presence of C1 or C2 from a couple of fields we
|
|
287 // already have present in the type database
|
|
288 {
|
|
289 Type type = db.lookupType("methodOopDesc");
|
|
290 if (type.getField("_from_compiled_entry", false, false) == null) {
|
|
291 // Neither C1 nor C2 is present
|
|
292 usingClientCompiler = false;
|
|
293 usingServerCompiler = false;
|
|
294 } else {
|
|
295 // Determine whether C2 is present
|
|
296 if (type.getField("_interpreter_invocation_count", false, false) != null) {
|
|
297 usingServerCompiler = true;
|
|
298 } else {
|
|
299 usingClientCompiler = true;
|
|
300 }
|
|
301 }
|
|
302 }
|
|
303
|
|
304 useTLAB = (db.lookupIntConstant("UseTLAB").intValue() != 0);
|
|
305
|
|
306 if (debugger != null) {
|
|
307 isLP64 = debugger.getMachineDescription().isLP64();
|
|
308 }
|
|
309 bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue();
|
|
310 minObjAlignmentInBytes = db.lookupIntConstant("MinObjAlignmentInBytes").intValue();
|
|
311
|
|
312 intxType = db.lookupType("intx");
|
|
313 uintxType = db.lookupType("uintx");
|
|
314 boolType = (CIntegerType) db.lookupType("bool");
|
|
315 }
|
|
316
|
|
317 /** This could be used by a reflective runtime system */
|
|
318 public static void initialize(TypeDataBase db, boolean isBigEndian) {
|
|
319 if (soleInstance != null) {
|
|
320 throw new RuntimeException("Attempt to initialize VM twice");
|
|
321 }
|
|
322 soleInstance = new VM(db, null, isBigEndian);
|
|
323 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
|
|
324 ((Observer) iter.next()).update(null, null);
|
|
325 }
|
|
326 }
|
|
327
|
|
328 /** This is used by the debugging system */
|
|
329 public static void initialize(TypeDataBase db, JVMDebugger debugger) {
|
|
330 if (soleInstance != null) {
|
|
331 throw new RuntimeException("Attempt to initialize VM twice");
|
|
332 }
|
|
333 soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian());
|
|
334 for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
|
|
335 ((Observer) iter.next()).update(null, null);
|
|
336 }
|
|
337 }
|
|
338
|
|
339 /** This is used by the debugging system */
|
|
340 public static void shutdown() {
|
|
341 soleInstance = null;
|
|
342 }
|
|
343
|
|
344 /** This is used by both the debugger and any runtime system. It is
|
|
345 the basic mechanism by which classes which mimic underlying VM
|
|
346 functionality cause themselves to be initialized. The given
|
|
347 observer will be notified (with arguments (null, null)) when the
|
|
348 VM is re-initialized, as well as when it registers itself with
|
|
349 the VM. */
|
|
350 public static void registerVMInitializedObserver(Observer o) {
|
|
351 vmInitializedObservers.add(o);
|
|
352 o.update(null, null);
|
|
353 }
|
|
354
|
|
355 /** This is the primary accessor used by both the debugger and any
|
|
356 potential runtime system */
|
|
357 public static VM getVM() {
|
|
358 if (soleInstance == null) {
|
|
359 throw new RuntimeException("VM.initialize() was not yet called");
|
|
360 }
|
|
361 return soleInstance;
|
|
362 }
|
|
363
|
|
364 /** This is only used by the debugging system. The given observer
|
|
365 will be notified if the underlying VM resumes execution. NOTE
|
|
366 that the given observer is not triggered if the VM is currently
|
|
367 running and therefore differs in behavior from {@link
|
|
368 #registerVMInitializedObserver} (because of the possibility of
|
|
369 race conditions if the observer is added while the VM is being
|
|
370 suspended or resumed). */
|
|
371 public void registerVMResumedObserver(Observer o) {
|
|
372 vmResumedObservers.add(o);
|
|
373 }
|
|
374
|
|
375 /** This is only used by the debugging system. The given observer
|
|
376 will be notified if the underlying VM suspends execution. NOTE
|
|
377 that the given observer is not triggered if the VM is currently
|
|
378 suspended and therefore differs in behavior from {@link
|
|
379 #registerVMInitializedObserver} (because of the possibility of
|
|
380 race conditions if the observer is added while the VM is being
|
|
381 suspended or resumed). */
|
|
382 public void registerVMSuspendedObserver(Observer o) {
|
|
383 vmSuspendedObservers.add(o);
|
|
384 }
|
|
385
|
|
386 /** This is only used by the debugging system. Informs all
|
|
387 registered resumption observers that the VM has been resumed.
|
|
388 The application is responsible for actually having performed the
|
|
389 resumption. No OopHandles must be used after this point, as they
|
|
390 may move in the target address space due to garbage
|
|
391 collection. */
|
|
392 public void fireVMResumed() {
|
|
393 for (Iterator iter = vmResumedObservers.iterator(); iter.hasNext(); ) {
|
|
394 ((Observer) iter.next()).update(null, null);
|
|
395 }
|
|
396 }
|
|
397
|
|
398 /** This is only used by the debugging system. Informs all
|
|
399 registered suspension observers that the VM has been suspended.
|
|
400 The application is responsible for actually having performed the
|
|
401 suspension. Garbage collection must be forbidden at this point;
|
|
402 for example, a JPDA-level suspension is not adequate since the
|
|
403 VM thread may still be running. */
|
|
404 public void fireVMSuspended() {
|
|
405 for (Iterator iter = vmSuspendedObservers.iterator(); iter.hasNext(); ) {
|
|
406 ((Observer) iter.next()).update(null, null);
|
|
407 }
|
|
408 }
|
|
409
|
|
410 /** Returns the OS this VM is running on. Notice that by delegating
|
|
411 to the debugger we can transparently support remote
|
|
412 debugging. */
|
|
413 public String getOS() {
|
|
414 if (debugger != null) {
|
|
415 return debugger.getOS();
|
|
416 }
|
|
417 return PlatformInfo.getOS();
|
|
418 }
|
|
419
|
|
420 /** Returns the CPU this VM is running on. Notice that by delegating
|
|
421 to the debugger we can transparently support remote
|
|
422 debugging. */
|
|
423 public String getCPU() {
|
|
424 if (debugger != null) {
|
|
425 return debugger.getCPU();
|
|
426 }
|
|
427 return PlatformInfo.getCPU();
|
|
428 }
|
|
429
|
|
430 public Type lookupType(String cTypeName) {
|
|
431 return db.lookupType(cTypeName);
|
|
432 }
|
|
433
|
|
434 public Integer lookupIntConstant(String name) {
|
|
435 return db.lookupIntConstant(name);
|
|
436 }
|
|
437
|
|
438 public long getAddressSize() {
|
|
439 return db.getAddressSize();
|
|
440 }
|
|
441
|
|
442 public long getOopSize() {
|
|
443 return db.getOopSize();
|
|
444 }
|
|
445
|
|
446 public long getLogAddressSize() {
|
|
447 return logAddressSize;
|
|
448 }
|
|
449
|
|
450 /** NOTE: this offset is in BYTES in this system! */
|
|
451 public long getStackBias() {
|
|
452 return stackBias;
|
|
453 }
|
|
454
|
|
455 /** Indicates whether the underlying machine supports the LP64 data
|
|
456 model. This is needed for conditionalizing code in a few places */
|
|
457 public boolean isLP64() {
|
|
458 if (Assert.ASSERTS_ENABLED) {
|
|
459 Assert.that(isDebugging(), "Debugging system only for now");
|
|
460 }
|
|
461 return isLP64;
|
|
462 }
|
|
463
|
|
464 /** Get bytes-per-long == long/double natural alignment. */
|
|
465 public int getBytesPerLong() {
|
|
466 return bytesPerLong;
|
|
467 }
|
|
468
|
|
469 /** Get minimum object alignment in bytes. */
|
|
470 public int getMinObjAlignmentInBytes() {
|
|
471 return minObjAlignmentInBytes;
|
|
472 }
|
|
473
|
|
474 /** Utility routine for getting data structure alignment correct */
|
|
475 public long alignUp(long size, long alignment) {
|
|
476 return (size + alignment - 1) & ~(alignment - 1);
|
|
477 }
|
|
478
|
|
479 /** Utility routine for getting data structure alignment correct */
|
|
480 public long alignDown(long size, long alignment) {
|
|
481 return size & ~(alignment - 1);
|
|
482 }
|
|
483
|
|
484 /** Utility routine for building an int from two "unsigned" 16-bit
|
|
485 shorts */
|
|
486 public int buildIntFromShorts(short low, short high) {
|
|
487 return (((int) high) << 16) | (((int) low) & 0xFFFF);
|
|
488 }
|
|
489
|
|
490 /** Utility routine for building a long from two "unsigned" 32-bit
|
|
491 ints in <b>platform-dependent</b> order */
|
|
492 public long buildLongFromIntsPD(int oneHalf, int otherHalf) {
|
|
493 if (isBigEndian) {
|
|
494 return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL);
|
|
495 } else{
|
|
496 return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL);
|
|
497 }
|
|
498 }
|
|
499
|
|
500 /** Indicates whether Thread-Local Allocation Buffers are used */
|
|
501 public boolean getUseTLAB() {
|
|
502 return useTLAB;
|
|
503 }
|
|
504
|
|
505 public TypeDataBase getTypeDataBase() {
|
|
506 return db;
|
|
507 }
|
|
508
|
|
509 public Universe getUniverse() {
|
|
510 if (universe == null) {
|
|
511 universe = new Universe();
|
|
512 }
|
|
513 return universe;
|
|
514 }
|
|
515
|
|
516 public ObjectHeap getObjectHeap() {
|
|
517 if (heap == null) {
|
|
518 heap = new ObjectHeap(db);
|
|
519 }
|
|
520 return heap;
|
|
521 }
|
|
522
|
|
523 public SymbolTable getSymbolTable() {
|
|
524 if (symbols == null) {
|
|
525 symbols = SymbolTable.getTheTable();
|
|
526 }
|
|
527 return symbols;
|
|
528 }
|
|
529
|
|
530 public StringTable getStringTable() {
|
|
531 if (strings == null) {
|
|
532 strings = StringTable.getTheTable();
|
|
533 }
|
|
534 return strings;
|
|
535 }
|
|
536
|
|
537 public SystemDictionary getSystemDictionary() {
|
|
538 if (dict == null) {
|
|
539 dict = new SystemDictionary();
|
|
540 }
|
|
541 return dict;
|
|
542 }
|
|
543
|
|
544 public Threads getThreads() {
|
|
545 if (threads == null) {
|
|
546 threads = new Threads();
|
|
547 }
|
|
548 return threads;
|
|
549 }
|
|
550
|
|
551 public ObjectSynchronizer getObjectSynchronizer() {
|
|
552 if (synchronizer == null) {
|
|
553 synchronizer = new ObjectSynchronizer();
|
|
554 }
|
|
555 return synchronizer;
|
|
556 }
|
|
557
|
|
558 public JNIHandles getJNIHandles() {
|
|
559 if (handles == null) {
|
|
560 handles = new JNIHandles();
|
|
561 }
|
|
562 return handles;
|
|
563 }
|
|
564
|
|
565 public Interpreter getInterpreter() {
|
|
566 if (interpreter == null) {
|
|
567 interpreter = new Interpreter();
|
|
568 }
|
|
569 return interpreter;
|
|
570 }
|
|
571
|
|
572 public StubRoutines getStubRoutines() {
|
|
573 if (stubRoutines == null) {
|
|
574 stubRoutines = new StubRoutines();
|
|
575 }
|
|
576 return stubRoutines;
|
|
577 }
|
|
578
|
|
579 public VMRegImpl getVMRegImplInfo() {
|
|
580 if (vmregImpl == null) {
|
|
581 vmregImpl = new VMRegImpl();
|
|
582 }
|
|
583 return vmregImpl;
|
|
584 }
|
|
585
|
|
586 public Bytes getBytes() {
|
|
587 if (bytes == null) {
|
|
588 bytes = new Bytes(debugger.getMachineDescription());
|
|
589 }
|
|
590 return bytes;
|
|
591 }
|
|
592
|
|
593 /** Returns true if this is a "core" build, false if either C1 or C2
|
|
594 is present */
|
|
595 public boolean isCore() {
|
|
596 return (!(usingClientCompiler || usingServerCompiler));
|
|
597 }
|
|
598
|
|
599 /** Returns true if this is a C1 build, false otherwise */
|
|
600 public boolean isClientCompiler() {
|
|
601 return usingClientCompiler;
|
|
602 }
|
|
603
|
|
604 /** Returns true if this is a C2 build, false otherwise */
|
|
605 public boolean isServerCompiler() {
|
|
606 return usingServerCompiler;
|
|
607 }
|
|
608
|
|
609 /** Returns true if C2 derived pointer table should be used, false otherwise */
|
|
610 public boolean useDerivedPointerTable() {
|
|
611 return !disableDerivedPrinterTableCheck;
|
|
612 }
|
|
613
|
|
614 /** Returns the code cache; should not be used if is core build */
|
|
615 public CodeCache getCodeCache() {
|
|
616 if (Assert.ASSERTS_ENABLED) {
|
|
617 Assert.that(!isCore(), "noncore builds only");
|
|
618 }
|
|
619 if (codeCache == null) {
|
|
620 codeCache = new CodeCache();
|
|
621 }
|
|
622 return codeCache;
|
|
623 }
|
|
624
|
|
625 /** Should only be called for C1 builds */
|
|
626 public Runtime1 getRuntime1() {
|
|
627 if (Assert.ASSERTS_ENABLED) {
|
|
628 Assert.that(isClientCompiler(), "C1 builds only");
|
|
629 }
|
|
630 if (runtime1 == null) {
|
|
631 runtime1 = new Runtime1();
|
|
632 }
|
|
633 return runtime1;
|
|
634 }
|
|
635
|
|
636 /** Test to see whether we're in debugging mode (NOTE: this really
|
|
637 should not be tested by this code; currently only used in
|
|
638 StackFrameStream) */
|
|
639 public boolean isDebugging() {
|
|
640 return (debugger != null);
|
|
641 }
|
|
642
|
|
643 /** This is only used by the debugging (i.e., non-runtime) system */
|
|
644 public JVMDebugger getDebugger() {
|
|
645 if (debugger == null) {
|
|
646 throw new RuntimeException("Attempt to use debugger in runtime system");
|
|
647 }
|
|
648 return debugger;
|
|
649 }
|
|
650
|
|
651 /** Indicates whether a given program counter is in Java code. This
|
|
652 includes but is not spanned by the interpreter and code cache.
|
|
653 Only used in the debugging system, for implementing
|
|
654 JavaThread.currentFrameGuess() on x86. */
|
|
655 public boolean isJavaPCDbg(Address addr) {
|
|
656 // FIXME: this is not a complete enough set: must include areas
|
|
657 // like vtable stubs
|
|
658 return (getInterpreter().contains(addr) ||
|
|
659 getCodeCache().contains(addr));
|
|
660 }
|
|
661
|
|
662 /** FIXME: figure out where to stick this */
|
|
663 public int getInvocationEntryBCI() {
|
|
664 return invocationEntryBCI;
|
|
665 }
|
|
666
|
|
667 /** FIXME: figure out where to stick this */
|
|
668 public int getInvalidOSREntryBCI() {
|
|
669 return invalidOSREntryBCI;
|
|
670 }
|
|
671
|
|
672 // FIXME: figure out where to stick this
|
|
673 public boolean wizardMode() {
|
|
674 return true;
|
|
675 }
|
|
676
|
|
677 public ReversePtrs getRevPtrs() {
|
|
678 return revPtrs;
|
|
679 }
|
|
680
|
|
681 public void setRevPtrs(ReversePtrs rp) {
|
|
682 revPtrs = rp;
|
|
683 }
|
|
684
|
|
685 // returns null, if not available.
|
|
686 public String getVMRelease() {
|
|
687 return vmRelease;
|
|
688 }
|
|
689
|
|
690 // returns null, if not available.
|
|
691 public String getVMInternalInfo() {
|
|
692 return vmInternalInfo;
|
|
693 }
|
|
694
|
|
695 public boolean isSharingEnabled() {
|
|
696 if (sharingEnabled == null) {
|
|
697 Flag flag = getCommandLineFlag("UseSharedSpaces");
|
|
698 sharingEnabled = (flag == null)? Boolean.FALSE :
|
|
699 (flag.getBool()? Boolean.TRUE: Boolean.FALSE);
|
|
700 }
|
|
701 return sharingEnabled.booleanValue();
|
|
702 }
|
|
703
|
|
704
|
|
705 // returns null, if not available.
|
|
706 public Flag[] getCommandLineFlags() {
|
|
707 if (commandLineFlags == null) {
|
|
708 readCommandLineFlags();
|
|
709 }
|
|
710
|
|
711 return commandLineFlags;
|
|
712 }
|
|
713
|
|
714 public Flag getCommandLineFlag(String name) {
|
|
715 if (flagsMap == null) {
|
|
716 flagsMap = new HashMap();
|
|
717 Flag[] flags = getCommandLineFlags();
|
|
718 for (int i = 0; i < flags.length; i++) {
|
|
719 flagsMap.put(flags[i].getName(), flags[i]);
|
|
720 }
|
|
721 }
|
|
722 return (Flag) flagsMap.get(name);
|
|
723 }
|
|
724
|
|
725 private void readCommandLineFlags() {
|
|
726 // get command line flags
|
|
727 TypeDataBase db = getTypeDataBase();
|
|
728 try {
|
|
729 Type flagType = db.lookupType("Flag");
|
|
730 int numFlags = (int) flagType.getCIntegerField("numFlags").getValue();
|
|
731 // NOTE: last flag contains null values.
|
|
732 commandLineFlags = new Flag[numFlags - 1];
|
|
733
|
|
734 Address flagAddr = flagType.getAddressField("flags").getValue();
|
|
735
|
|
736 AddressField typeFld = flagType.getAddressField("type");
|
|
737 AddressField nameFld = flagType.getAddressField("name");
|
|
738 AddressField addrFld = flagType.getAddressField("addr");
|
|
739 AddressField kindFld = flagType.getAddressField("kind");
|
|
740
|
|
741 long flagSize = flagType.getSize(); // sizeof(Flag)
|
|
742
|
|
743 // NOTE: last flag contains null values.
|
|
744 for (int f = 0; f < numFlags - 1; f++) {
|
|
745 String type = CStringUtilities.getString(typeFld.getValue(flagAddr));
|
|
746 String name = CStringUtilities.getString(nameFld.getValue(flagAddr));
|
|
747 Address addr = addrFld.getValue(flagAddr);
|
|
748 String kind = CStringUtilities.getString(kindFld.getValue(flagAddr));
|
|
749 commandLineFlags[f] = new Flag(type, name, addr, kind);
|
|
750 flagAddr = flagAddr.addOffsetTo(flagSize);
|
|
751 }
|
|
752
|
|
753 // sort flags by name
|
|
754 Arrays.sort(commandLineFlags, new Comparator() {
|
|
755 public int compare(Object o1, Object o2) {
|
|
756 Flag f1 = (Flag) o1;
|
|
757 Flag f2 = (Flag) o2;
|
|
758 return f1.getName().compareTo(f2.getName());
|
|
759 }
|
|
760 });
|
|
761 } catch (Exception exp) {
|
|
762 // ignore. may be older version. command line flags not available.
|
|
763 }
|
|
764 }
|
|
765
|
|
766 public String getSystemProperty(String key) {
|
|
767 Properties props = getSystemProperties();
|
|
768 return (props != null)? props.getProperty(key) : null;
|
|
769 }
|
|
770
|
|
771 public Properties getSystemProperties() {
|
|
772 if (sysProps == null) {
|
|
773 readSystemProperties();
|
|
774 }
|
|
775 return sysProps;
|
|
776 }
|
|
777
|
|
778 private void readSystemProperties() {
|
|
779 InstanceKlass systemKls = getSystemDictionary().getSystemKlass();
|
|
780 systemKls.iterate(new DefaultOopVisitor() {
|
|
781 ObjectReader objReader = new ObjectReader();
|
|
782 public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) {
|
|
783 if (field.getID().getName().equals("props")) {
|
|
784 try {
|
|
785 sysProps = (Properties) objReader.readObject(field.getValue(getObj()));
|
|
786 } catch (Exception e) {
|
|
787 if (Assert.ASSERTS_ENABLED) {
|
|
788 e.printStackTrace();
|
|
789 }
|
|
790 }
|
|
791 }
|
|
792 }
|
|
793 }, false);
|
|
794 }
|
|
795 }
|