duke@435: /*
coleenp@4037: * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
duke@435: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
duke@435: *
duke@435: * This code is free software; you can redistribute it and/or modify it
duke@435: * under the terms of the GNU General Public License version 2 only, as
duke@435: * published by the Free Software Foundation.
duke@435: *
duke@435: * This code is distributed in the hope that it will be useful, but WITHOUT
duke@435: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
duke@435: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
duke@435: * version 2 for more details (a copy is included in the LICENSE file that
duke@435: * accompanied this code).
duke@435: *
duke@435: * You should have received a copy of the GNU General Public License version
duke@435: * 2 along with this work; if not, write to the Free Software Foundation,
duke@435: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
duke@435: *
trims@1907: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
trims@1907: * or visit www.oracle.com if you need additional information or have any
trims@1907: * questions.
duke@435: *
duke@435: */
duke@435:
duke@435: package sun.jvm.hotspot.runtime;
duke@435:
duke@435: import java.io.*;
duke@435: import java.net.*;
duke@435: import java.util.*;
duke@435: import java.util.regex.*;
duke@435: import sun.jvm.hotspot.code.*;
duke@435: import sun.jvm.hotspot.c1.*;
never@3108: import sun.jvm.hotspot.code.*;
duke@435: import sun.jvm.hotspot.debugger.*;
duke@435: import sun.jvm.hotspot.interpreter.*;
duke@435: import sun.jvm.hotspot.memory.*;
duke@435: import sun.jvm.hotspot.oops.*;
duke@435: import sun.jvm.hotspot.types.*;
duke@435: import sun.jvm.hotspot.utilities.*;
coleenp@548: import sun.jvm.hotspot.runtime.*;
duke@435:
duke@435: /**
This class encapsulates the global state of the VM; the
duke@435: universe, object heap, interpreter, etc. It is a Singleton and
duke@435: must be initialized with a call to initialize() before calling
duke@435: getVM().
duke@435:
duke@435: Many auxiliary classes (i.e., most of the VMObjects) keep
duke@435: needed field offsets in the form of static Field objects. In a
duke@435: debugging system, the VM might be shutdown and re-initialized (on
duke@435: a differently-configured build, i.e., 32- vs. 64-bit), and all old
duke@435: cached state (including fields and field offsets) must be
duke@435: flushed.
duke@435:
duke@435: An Observer pattern is used to implement the initialization of
duke@435: such classes. Each such class, in its static initializer,
duke@435: registers an Observer with the VM class via
duke@435: VM.registerVMInitializedObserver(). This Observer is guaranteed to
duke@435: be notified whenever the VM is initialized (or re-initialized). To
duke@435: implement the first-time initialization, the observer is also
duke@435: notified when it registers itself with the VM. (For bootstrapping
duke@435: reasons, this implies that the constructor of VM can not
duke@435: instantiate any such objects, since VM.soleInstance will not have
duke@435: been set yet. This is a bootstrapping issue which may have to be
duke@435: revisited later.)
duke@435: */
duke@435:
duke@435: public class VM {
duke@435: private static VM soleInstance;
duke@435: private static List vmInitializedObservers = new ArrayList();
duke@435: private List vmResumedObservers = new ArrayList();
duke@435: private List vmSuspendedObservers = new ArrayList();
duke@435: private TypeDataBase db;
duke@435: private boolean isBigEndian;
duke@435: /** This is only present if in a debugging system */
duke@435: private JVMDebugger debugger;
duke@435: private long stackBias;
duke@435: private long logAddressSize;
duke@435: private Universe universe;
duke@435: private ObjectHeap heap;
duke@435: private SymbolTable symbols;
duke@435: private StringTable strings;
duke@435: private SystemDictionary dict;
duke@435: private Threads threads;
duke@435: private ObjectSynchronizer synchronizer;
duke@435: private JNIHandles handles;
duke@435: private Interpreter interpreter;
duke@435: private StubRoutines stubRoutines;
duke@435: private Bytes bytes;
never@3108:
duke@435: /** Flags indicating whether we are attached to a core, C1, or C2 build */
duke@435: private boolean usingClientCompiler;
duke@435: private boolean usingServerCompiler;
duke@435: /** alignment constants */
duke@435: private boolean isLP64;
duke@435: private int bytesPerLong;
coleenp@4037: private int bytesPerWord;
kvn@1926: private int objectAlignmentInBytes;
duke@435: private int minObjAlignmentInBytes;
coleenp@548: private int logMinObjAlignmentInBytes;
coleenp@548: private int heapWordSize;
coleenp@548: private int heapOopSize;
roland@4159: private int klassPtrSize;
coleenp@548: private int oopSize;
duke@435: /** This is only present in a non-core build */
duke@435: private CodeCache codeCache;
duke@435: /** This is only present in a C1 build */
duke@435: private Runtime1 runtime1;
duke@435: /** These constants come from globalDefinitions.hpp */
duke@435: private int invocationEntryBCI;
duke@435: private int invalidOSREntryBCI;
duke@435: private ReversePtrs revPtrs;
duke@435: private VMRegImpl vmregImpl;
stefank@4546: private int reserveForAllocationPrefetch;
duke@435:
duke@435: // System.getProperties from debuggee VM
duke@435: private Properties sysProps;
duke@435:
duke@435: // VM version strings come from Abstract_VM_Version class
duke@435: private String vmRelease;
duke@435: private String vmInternalInfo;
duke@435:
duke@435: private Flag[] commandLineFlags;
duke@435: private Map flagsMap;
duke@435:
duke@435: private static Type intxType;
duke@435: private static Type uintxType;
duke@435: private static CIntegerType boolType;
duke@435: private Boolean sharingEnabled;
coleenp@548: private Boolean compressedOopsEnabled;
roland@4159: private Boolean compressedKlassPointersEnabled;
duke@435:
duke@435: // command line flags supplied to VM - see struct Flag in globals.hpp
duke@435: public static final class Flag {
duke@435: private String type;
duke@435: private String name;
duke@435: private Address addr;
duke@435: private String kind;
never@3138: private int origin;
duke@435:
never@3138: private Flag(String type, String name, Address addr, String kind, int origin) {
duke@435: this.type = type;
duke@435: this.name = name;
duke@435: this.addr = addr;
duke@435: this.kind = kind;
never@3138: this.origin = origin;
duke@435: }
duke@435:
duke@435: public String getType() {
duke@435: return type;
duke@435: }
duke@435:
duke@435: public String getName() {
duke@435: return name;
duke@435: }
duke@435:
duke@435: public Address getAddress() {
duke@435: return addr;
duke@435: }
duke@435:
duke@435: public String getKind() {
duke@435: return kind;
duke@435: }
duke@435:
never@3138: public int getOrigin() {
never@3138: return origin;
never@3138: }
never@3138:
duke@435: public boolean isBool() {
duke@435: return type.equals("bool");
duke@435: }
duke@435:
duke@435: public boolean getBool() {
duke@435: if (Assert.ASSERTS_ENABLED) {
duke@435: Assert.that(isBool(), "not a bool flag!");
duke@435: }
duke@435: return addr.getCIntegerAt(0, boolType.getSize(), boolType.isUnsigned())
duke@435: != 0;
duke@435: }
duke@435:
duke@435: public boolean isIntx() {
duke@435: return type.equals("intx");
duke@435: }
duke@435:
duke@435: public long getIntx() {
duke@435: if (Assert.ASSERTS_ENABLED) {
duke@435: Assert.that(isIntx(), "not a intx flag!");
duke@435: }
duke@435: return addr.getCIntegerAt(0, intxType.getSize(), false);
duke@435: }
duke@435:
duke@435: public boolean isUIntx() {
duke@435: return type.equals("uintx");
duke@435: }
duke@435:
duke@435: public long getUIntx() {
duke@435: if (Assert.ASSERTS_ENABLED) {
duke@435: Assert.that(isUIntx(), "not a uintx flag!");
duke@435: }
duke@435: return addr.getCIntegerAt(0, uintxType.getSize(), true);
duke@435: }
duke@435:
duke@435: public String getValue() {
duke@435: if (isBool()) {
duke@435: return new Boolean(getBool()).toString();
duke@435: } else if (isIntx()) {
duke@435: return new Long(getIntx()).toString();
duke@435: } else if (isUIntx()) {
duke@435: return new Long(getUIntx()).toString();
duke@435: } else {
duke@435: return null;
duke@435: }
duke@435: }
duke@435: };
duke@435:
duke@435: private static void checkVMVersion(String vmRelease) {
duke@435: if (System.getProperty("sun.jvm.hotspot.runtime.VM.disableVersionCheck") == null) {
duke@435: // read sa build version.
duke@435: String versionProp = "sun.jvm.hotspot.runtime.VM.saBuildVersion";
duke@435: String saVersion = saProps.getProperty(versionProp);
duke@435: if (saVersion == null)
duke@435: throw new RuntimeException("Missing property " + versionProp);
duke@435:
duke@435: // Strip nonproduct VM version substring (note: saVersion doesn't have it).
duke@435: String vmVersion = vmRelease.replaceAll("(-fastdebug)|(-debug)|(-jvmg)|(-optimized)|(-profiled)","");
duke@435:
duke@435: if (saVersion.equals(vmVersion)) {
duke@435: // Exact match
duke@435: return;
duke@435: }
duke@435: if (saVersion.indexOf('-') == saVersion.lastIndexOf('-') &&
duke@435: vmVersion.indexOf('-') == vmVersion.lastIndexOf('-')) {
duke@435: // Throw exception if different release versions:
duke@435: // .-b
duke@435: throw new VMVersionMismatchException(saVersion, vmRelease);
duke@435: } else {
duke@435: // Otherwise print warning to allow mismatch not release versions
duke@435: // during development.
duke@435: System.err.println("WARNING: Hotspot VM version " + vmRelease +
duke@435: " does not match with SA version " + saVersion +
duke@435: "." + " You may see unexpected results. ");
duke@435: }
duke@435: } else {
duke@435: System.err.println("WARNING: You have disabled SA and VM version check. You may be " +
duke@435: "using incompatible version of SA and you may see unexpected " +
duke@435: "results.");
duke@435: }
duke@435: }
duke@435:
kevinw@5327: private static final boolean disableDerivedPointerTableCheck;
duke@435: private static final Properties saProps;
duke@435:
duke@435: static {
duke@435: saProps = new Properties();
duke@435: URL url = null;
duke@435: try {
duke@435: url = VM.class.getClassLoader().getResource("sa.properties");
duke@435: saProps.load(new BufferedInputStream(url.openStream()));
duke@435: } catch (Exception e) {
kevinw@5327: System.err.println("Unable to load properties " +
duke@435: (url == null ? "null" : url.toString()) +
duke@435: ": " + e.getMessage());
duke@435: }
duke@435:
kevinw@5327: disableDerivedPointerTableCheck = System.getProperty("sun.jvm.hotspot.runtime.VM.disableDerivedPointerTableCheck") != null;
duke@435: }
duke@435:
duke@435: private VM(TypeDataBase db, JVMDebugger debugger, boolean isBigEndian) {
duke@435: this.db = db;
duke@435: this.debugger = debugger;
duke@435: this.isBigEndian = isBigEndian;
duke@435:
duke@435: // Note that we don't construct universe, heap, threads,
duke@435: // interpreter, or stubRoutines here (any more). The current
duke@435: // initialization mechanisms require that the VM be completely set
duke@435: // up (i.e., out of its constructor, with soleInstance assigned)
duke@435: // before their static initializers are run.
duke@435:
duke@435: if (db.getAddressSize() == 4) {
duke@435: logAddressSize = 2;
duke@435: } else if (db.getAddressSize() == 8) {
duke@435: logAddressSize = 3;
duke@435: } else {
duke@435: throw new RuntimeException("Address size " + db.getAddressSize() + " not yet supported");
duke@435: }
duke@435:
duke@435: // read VM version info
duke@435: try {
duke@435: Type vmVersion = db.lookupType("Abstract_VM_Version");
duke@435: Address releaseAddr = vmVersion.getAddressField("_s_vm_release").getValue();
duke@435: vmRelease = CStringUtilities.getString(releaseAddr);
duke@435: Address vmInternalInfoAddr = vmVersion.getAddressField("_s_internal_vm_info_string").getValue();
duke@435: vmInternalInfo = CStringUtilities.getString(vmInternalInfoAddr);
stefank@4546:
stefank@4546: CIntegerType intType = (CIntegerType) db.lookupType("int");
stefank@4546: CIntegerField reserveForAllocationPrefetchField = vmVersion.getCIntegerField("_reserve_for_allocation_prefetch");
stefank@4546: reserveForAllocationPrefetch = (int)reserveForAllocationPrefetchField.getCInteger(intType);
duke@435: } catch (Exception exp) {
duke@435: throw new RuntimeException("can't determine target's VM version : " + exp.getMessage());
duke@435: }
duke@435:
duke@435: checkVMVersion(vmRelease);
duke@435:
duke@435: stackBias = db.lookupIntConstant("STACK_BIAS").intValue();
duke@435: invocationEntryBCI = db.lookupIntConstant("InvocationEntryBci").intValue();
duke@435: invalidOSREntryBCI = db.lookupIntConstant("InvalidOSREntryBci").intValue();
duke@435:
duke@435: // We infer the presence of C1 or C2 from a couple of fields we
duke@435: // already have present in the type database
duke@435: {
coleenp@4037: Type type = db.lookupType("Method");
duke@435: if (type.getField("_from_compiled_entry", false, false) == null) {
duke@435: // Neither C1 nor C2 is present
duke@435: usingClientCompiler = false;
duke@435: usingServerCompiler = false;
duke@435: } else {
duke@435: // Determine whether C2 is present
never@3143: if (db.lookupType("Matcher", false) != null) {
duke@435: usingServerCompiler = true;
duke@435: } else {
duke@435: usingClientCompiler = true;
duke@435: }
duke@435: }
duke@435: }
duke@435:
duke@435: if (debugger != null) {
duke@435: isLP64 = debugger.getMachineDescription().isLP64();
duke@435: }
duke@435: bytesPerLong = db.lookupIntConstant("BytesPerLong").intValue();
coleenp@4037: bytesPerWord = db.lookupIntConstant("BytesPerWord").intValue();
kvn@1931: heapWordSize = db.lookupIntConstant("HeapWordSize").intValue();
kvn@1931: oopSize = db.lookupIntConstant("oopSize").intValue();
kvn@1931:
kvn@1931: intxType = db.lookupType("intx");
kvn@1931: uintxType = db.lookupType("uintx");
kvn@1931: boolType = (CIntegerType) db.lookupType("bool");
kvn@1931:
kvn@1926: minObjAlignmentInBytes = getObjectAlignmentInBytes();
kvn@1926: if (minObjAlignmentInBytes == 8) {
kvn@1926: logMinObjAlignmentInBytes = 3;
kvn@1926: } else if (minObjAlignmentInBytes == 16) {
kvn@1926: logMinObjAlignmentInBytes = 4;
kvn@1926: } else {
kvn@1926: throw new RuntimeException("Object alignment " + minObjAlignmentInBytes + " not yet supported");
kvn@1926: }
kvn@1926:
poonam@1184: if (isCompressedOopsEnabled()) {
poonam@1184: // Size info for oops within java objects is fixed
poonam@1184: heapOopSize = (int)getIntSize();
poonam@1184: } else {
poonam@1184: heapOopSize = (int)getOopSize();
poonam@1184: }
roland@4159:
roland@4159: if (isCompressedKlassPointersEnabled()) {
roland@4159: klassPtrSize = (int)getIntSize();
roland@4159: } else {
roland@4159: klassPtrSize = (int)getOopSize(); // same as an oop
roland@4159: }
duke@435: }
duke@435:
duke@435: /** This could be used by a reflective runtime system */
duke@435: public static void initialize(TypeDataBase db, boolean isBigEndian) {
duke@435: if (soleInstance != null) {
duke@435: throw new RuntimeException("Attempt to initialize VM twice");
duke@435: }
duke@435: soleInstance = new VM(db, null, isBigEndian);
duke@435: for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
duke@435: ((Observer) iter.next()).update(null, null);
duke@435: }
duke@435: }
duke@435:
duke@435: /** This is used by the debugging system */
duke@435: public static void initialize(TypeDataBase db, JVMDebugger debugger) {
duke@435: if (soleInstance != null) {
kevinw@5327: // Using multiple SA Tool classes in the same process creates a call here.
kevinw@5327: return;
duke@435: }
duke@435: soleInstance = new VM(db, debugger, debugger.getMachineDescription().isBigEndian());
poonam@1124:
duke@435: for (Iterator iter = vmInitializedObservers.iterator(); iter.hasNext(); ) {
duke@435: ((Observer) iter.next()).update(null, null);
duke@435: }
poonam@1085:
roland@4159: debugger.putHeapConst(soleInstance.getHeapOopSize(), soleInstance.getKlassPtrSize(),
roland@4159: Universe.getNarrowOopBase(), Universe.getNarrowOopShift(),
roland@4159: Universe.getNarrowKlassBase(), Universe.getNarrowKlassShift());
duke@435: }
duke@435:
duke@435: /** This is used by the debugging system */
duke@435: public static void shutdown() {
duke@435: soleInstance = null;
duke@435: }
duke@435:
duke@435: /** This is used by both the debugger and any runtime system. It is
duke@435: the basic mechanism by which classes which mimic underlying VM
duke@435: functionality cause themselves to be initialized. The given
duke@435: observer will be notified (with arguments (null, null)) when the
duke@435: VM is re-initialized, as well as when it registers itself with
duke@435: the VM. */
duke@435: public static void registerVMInitializedObserver(Observer o) {
duke@435: vmInitializedObservers.add(o);
duke@435: o.update(null, null);
duke@435: }
duke@435:
duke@435: /** This is the primary accessor used by both the debugger and any
duke@435: potential runtime system */
duke@435: public static VM getVM() {
duke@435: if (soleInstance == null) {
duke@435: throw new RuntimeException("VM.initialize() was not yet called");
duke@435: }
duke@435: return soleInstance;
duke@435: }
duke@435:
duke@435: /** This is only used by the debugging system. The given observer
duke@435: will be notified if the underlying VM resumes execution. NOTE
duke@435: that the given observer is not triggered if the VM is currently
duke@435: running and therefore differs in behavior from {@link
duke@435: #registerVMInitializedObserver} (because of the possibility of
duke@435: race conditions if the observer is added while the VM is being
duke@435: suspended or resumed). */
duke@435: public void registerVMResumedObserver(Observer o) {
duke@435: vmResumedObservers.add(o);
duke@435: }
duke@435:
duke@435: /** This is only used by the debugging system. The given observer
duke@435: will be notified if the underlying VM suspends execution. NOTE
duke@435: that the given observer is not triggered if the VM is currently
duke@435: suspended and therefore differs in behavior from {@link
duke@435: #registerVMInitializedObserver} (because of the possibility of
duke@435: race conditions if the observer is added while the VM is being
duke@435: suspended or resumed). */
duke@435: public void registerVMSuspendedObserver(Observer o) {
duke@435: vmSuspendedObservers.add(o);
duke@435: }
duke@435:
duke@435: /** This is only used by the debugging system. Informs all
duke@435: registered resumption observers that the VM has been resumed.
duke@435: The application is responsible for actually having performed the
duke@435: resumption. No OopHandles must be used after this point, as they
duke@435: may move in the target address space due to garbage
duke@435: collection. */
duke@435: public void fireVMResumed() {
duke@435: for (Iterator iter = vmResumedObservers.iterator(); iter.hasNext(); ) {
duke@435: ((Observer) iter.next()).update(null, null);
duke@435: }
duke@435: }
duke@435:
duke@435: /** This is only used by the debugging system. Informs all
duke@435: registered suspension observers that the VM has been suspended.
duke@435: The application is responsible for actually having performed the
duke@435: suspension. Garbage collection must be forbidden at this point;
duke@435: for example, a JPDA-level suspension is not adequate since the
duke@435: VM thread may still be running. */
duke@435: public void fireVMSuspended() {
duke@435: for (Iterator iter = vmSuspendedObservers.iterator(); iter.hasNext(); ) {
duke@435: ((Observer) iter.next()).update(null, null);
duke@435: }
duke@435: }
duke@435:
duke@435: /** Returns the OS this VM is running on. Notice that by delegating
duke@435: to the debugger we can transparently support remote
duke@435: debugging. */
duke@435: public String getOS() {
duke@435: if (debugger != null) {
duke@435: return debugger.getOS();
duke@435: }
duke@435: return PlatformInfo.getOS();
duke@435: }
duke@435:
duke@435: /** Returns the CPU this VM is running on. Notice that by delegating
duke@435: to the debugger we can transparently support remote
duke@435: debugging. */
duke@435: public String getCPU() {
duke@435: if (debugger != null) {
duke@435: return debugger.getCPU();
duke@435: }
duke@435: return PlatformInfo.getCPU();
duke@435: }
duke@435:
duke@435: public Type lookupType(String cTypeName) {
duke@435: return db.lookupType(cTypeName);
duke@435: }
duke@435:
duke@435: public Integer lookupIntConstant(String name) {
duke@435: return db.lookupIntConstant(name);
duke@435: }
duke@435:
minqi@4093: // Convenience function for conversions
minqi@4093: static public long getAddressValue(Address addr) {
minqi@4093: return VM.getVM().getDebugger().getAddressValue(addr);
minqi@4093: }
minqi@4093:
duke@435: public long getAddressSize() {
duke@435: return db.getAddressSize();
duke@435: }
duke@435:
duke@435: public long getOopSize() {
coleenp@548: return oopSize;
duke@435: }
duke@435:
duke@435: public long getLogAddressSize() {
duke@435: return logAddressSize;
duke@435: }
duke@435:
coleenp@548: public long getIntSize() {
coleenp@548: return db.getJIntType().getSize();
coleenp@548: }
coleenp@548:
duke@435: /** NOTE: this offset is in BYTES in this system! */
duke@435: public long getStackBias() {
duke@435: return stackBias;
duke@435: }
duke@435:
duke@435: /** Indicates whether the underlying machine supports the LP64 data
duke@435: model. This is needed for conditionalizing code in a few places */
duke@435: public boolean isLP64() {
duke@435: if (Assert.ASSERTS_ENABLED) {
duke@435: Assert.that(isDebugging(), "Debugging system only for now");
duke@435: }
duke@435: return isLP64;
duke@435: }
duke@435:
duke@435: /** Get bytes-per-long == long/double natural alignment. */
duke@435: public int getBytesPerLong() {
duke@435: return bytesPerLong;
duke@435: }
duke@435:
coleenp@4037: public int getBytesPerWord() {
coleenp@4037: return bytesPerWord;
coleenp@4037: }
coleenp@4037:
duke@435: /** Get minimum object alignment in bytes. */
duke@435: public int getMinObjAlignmentInBytes() {
duke@435: return minObjAlignmentInBytes;
duke@435: }
coleenp@548: public int getLogMinObjAlignmentInBytes() {
coleenp@548: return logMinObjAlignmentInBytes;
coleenp@548: }
duke@435:
coleenp@548: public int getHeapWordSize() {
coleenp@548: return heapWordSize;
coleenp@548: }
coleenp@548:
coleenp@548: public int getHeapOopSize() {
coleenp@548: return heapOopSize;
coleenp@548: }
roland@4159:
roland@4159: public int getKlassPtrSize() {
roland@4159: return klassPtrSize;
roland@4159: }
duke@435: /** Utility routine for getting data structure alignment correct */
duke@435: public long alignUp(long size, long alignment) {
duke@435: return (size + alignment - 1) & ~(alignment - 1);
duke@435: }
duke@435:
duke@435: /** Utility routine for getting data structure alignment correct */
duke@435: public long alignDown(long size, long alignment) {
duke@435: return size & ~(alignment - 1);
duke@435: }
duke@435:
duke@435: /** Utility routine for building an int from two "unsigned" 16-bit
duke@435: shorts */
duke@435: public int buildIntFromShorts(short low, short high) {
duke@435: return (((int) high) << 16) | (((int) low) & 0xFFFF);
duke@435: }
duke@435:
duke@435: /** Utility routine for building a long from two "unsigned" 32-bit
duke@435: ints in platform-dependent order */
duke@435: public long buildLongFromIntsPD(int oneHalf, int otherHalf) {
duke@435: if (isBigEndian) {
duke@435: return (((long) otherHalf) << 32) | (((long) oneHalf) & 0x00000000FFFFFFFFL);
duke@435: } else{
duke@435: return (((long) oneHalf) << 32) | (((long) otherHalf) & 0x00000000FFFFFFFFL);
duke@435: }
duke@435: }
duke@435:
duke@435: public TypeDataBase getTypeDataBase() {
duke@435: return db;
duke@435: }
duke@435:
duke@435: public Universe getUniverse() {
duke@435: if (universe == null) {
duke@435: universe = new Universe();
duke@435: }
duke@435: return universe;
duke@435: }
duke@435:
duke@435: public ObjectHeap getObjectHeap() {
duke@435: if (heap == null) {
duke@435: heap = new ObjectHeap(db);
duke@435: }
duke@435: return heap;
duke@435: }
duke@435:
duke@435: public SymbolTable getSymbolTable() {
duke@435: if (symbols == null) {
duke@435: symbols = SymbolTable.getTheTable();
duke@435: }
duke@435: return symbols;
duke@435: }
duke@435:
duke@435: public StringTable getStringTable() {
duke@435: if (strings == null) {
duke@435: strings = StringTable.getTheTable();
duke@435: }
duke@435: return strings;
duke@435: }
duke@435:
duke@435: public SystemDictionary getSystemDictionary() {
duke@435: if (dict == null) {
duke@435: dict = new SystemDictionary();
duke@435: }
duke@435: return dict;
duke@435: }
duke@435:
duke@435: public Threads getThreads() {
duke@435: if (threads == null) {
duke@435: threads = new Threads();
duke@435: }
duke@435: return threads;
duke@435: }
duke@435:
duke@435: public ObjectSynchronizer getObjectSynchronizer() {
duke@435: if (synchronizer == null) {
duke@435: synchronizer = new ObjectSynchronizer();
duke@435: }
duke@435: return synchronizer;
duke@435: }
duke@435:
duke@435: public JNIHandles getJNIHandles() {
duke@435: if (handles == null) {
duke@435: handles = new JNIHandles();
duke@435: }
duke@435: return handles;
duke@435: }
duke@435:
duke@435: public Interpreter getInterpreter() {
duke@435: if (interpreter == null) {
duke@435: interpreter = new Interpreter();
duke@435: }
duke@435: return interpreter;
duke@435: }
duke@435:
duke@435: public StubRoutines getStubRoutines() {
duke@435: if (stubRoutines == null) {
duke@435: stubRoutines = new StubRoutines();
duke@435: }
duke@435: return stubRoutines;
duke@435: }
duke@435:
duke@435: public VMRegImpl getVMRegImplInfo() {
duke@435: if (vmregImpl == null) {
duke@435: vmregImpl = new VMRegImpl();
duke@435: }
duke@435: return vmregImpl;
duke@435: }
duke@435:
duke@435: public Bytes getBytes() {
duke@435: if (bytes == null) {
duke@435: bytes = new Bytes(debugger.getMachineDescription());
duke@435: }
duke@435: return bytes;
duke@435: }
duke@435:
kvn@766: /** Returns true if this is a isBigEndian, false otherwise */
kvn@766: public boolean isBigEndian() {
kvn@766: return isBigEndian;
kvn@766: }
kvn@766:
duke@435: /** Returns true if this is a "core" build, false if either C1 or C2
duke@435: is present */
duke@435: public boolean isCore() {
duke@435: return (!(usingClientCompiler || usingServerCompiler));
duke@435: }
duke@435:
duke@435: /** Returns true if this is a C1 build, false otherwise */
duke@435: public boolean isClientCompiler() {
duke@435: return usingClientCompiler;
duke@435: }
duke@435:
duke@435: /** Returns true if this is a C2 build, false otherwise */
duke@435: public boolean isServerCompiler() {
duke@435: return usingServerCompiler;
duke@435: }
duke@435:
duke@435: /** Returns true if C2 derived pointer table should be used, false otherwise */
duke@435: public boolean useDerivedPointerTable() {
kevinw@5327: return !disableDerivedPointerTableCheck;
duke@435: }
duke@435:
duke@435: /** Returns the code cache; should not be used if is core build */
duke@435: public CodeCache getCodeCache() {
duke@435: if (Assert.ASSERTS_ENABLED) {
duke@435: Assert.that(!isCore(), "noncore builds only");
duke@435: }
duke@435: if (codeCache == null) {
duke@435: codeCache = new CodeCache();
duke@435: }
duke@435: return codeCache;
duke@435: }
duke@435:
duke@435: /** Should only be called for C1 builds */
duke@435: public Runtime1 getRuntime1() {
duke@435: if (Assert.ASSERTS_ENABLED) {
duke@435: Assert.that(isClientCompiler(), "C1 builds only");
duke@435: }
duke@435: if (runtime1 == null) {
duke@435: runtime1 = new Runtime1();
duke@435: }
duke@435: return runtime1;
duke@435: }
duke@435:
duke@435: /** Test to see whether we're in debugging mode (NOTE: this really
duke@435: should not be tested by this code; currently only used in
duke@435: StackFrameStream) */
duke@435: public boolean isDebugging() {
duke@435: return (debugger != null);
duke@435: }
duke@435:
duke@435: /** This is only used by the debugging (i.e., non-runtime) system */
duke@435: public JVMDebugger getDebugger() {
duke@435: if (debugger == null) {
duke@435: throw new RuntimeException("Attempt to use debugger in runtime system");
duke@435: }
duke@435: return debugger;
duke@435: }
duke@435:
duke@435: /** Indicates whether a given program counter is in Java code. This
duke@435: includes but is not spanned by the interpreter and code cache.
duke@435: Only used in the debugging system, for implementing
duke@435: JavaThread.currentFrameGuess() on x86. */
duke@435: public boolean isJavaPCDbg(Address addr) {
duke@435: // FIXME: this is not a complete enough set: must include areas
duke@435: // like vtable stubs
duke@435: return (getInterpreter().contains(addr) ||
duke@435: getCodeCache().contains(addr));
duke@435: }
duke@435:
duke@435: /** FIXME: figure out where to stick this */
duke@435: public int getInvocationEntryBCI() {
duke@435: return invocationEntryBCI;
duke@435: }
duke@435:
duke@435: /** FIXME: figure out where to stick this */
duke@435: public int getInvalidOSREntryBCI() {
duke@435: return invalidOSREntryBCI;
duke@435: }
duke@435:
duke@435: // FIXME: figure out where to stick this
duke@435: public boolean wizardMode() {
duke@435: return true;
duke@435: }
duke@435:
duke@435: public ReversePtrs getRevPtrs() {
duke@435: return revPtrs;
duke@435: }
duke@435:
duke@435: public void setRevPtrs(ReversePtrs rp) {
duke@435: revPtrs = rp;
duke@435: }
duke@435:
duke@435: // returns null, if not available.
duke@435: public String getVMRelease() {
duke@435: return vmRelease;
duke@435: }
duke@435:
duke@435: // returns null, if not available.
duke@435: public String getVMInternalInfo() {
duke@435: return vmInternalInfo;
duke@435: }
duke@435:
stefank@4546: public int getReserveForAllocationPrefetch() {
stefank@4546: return reserveForAllocationPrefetch;
stefank@4546: }
stefank@4546:
duke@435: public boolean isSharingEnabled() {
duke@435: if (sharingEnabled == null) {
duke@435: Flag flag = getCommandLineFlag("UseSharedSpaces");
duke@435: sharingEnabled = (flag == null)? Boolean.FALSE :
duke@435: (flag.getBool()? Boolean.TRUE: Boolean.FALSE);
duke@435: }
duke@435: return sharingEnabled.booleanValue();
duke@435: }
duke@435:
coleenp@548: public boolean isCompressedOopsEnabled() {
coleenp@548: if (compressedOopsEnabled == null) {
coleenp@548: Flag flag = getCommandLineFlag("UseCompressedOops");
coleenp@548: compressedOopsEnabled = (flag == null) ? Boolean.FALSE:
coleenp@548: (flag.getBool()? Boolean.TRUE: Boolean.FALSE);
coleenp@548: }
coleenp@548: return compressedOopsEnabled.booleanValue();
coleenp@548: }
duke@435:
roland@4159: public boolean isCompressedKlassPointersEnabled() {
roland@4159: if (compressedKlassPointersEnabled == null) {
ehelin@5694: Flag flag = getCommandLineFlag("UseCompressedClassPointers");
roland@4159: compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE:
coleenp@4037: (flag.getBool()? Boolean.TRUE: Boolean.FALSE);
coleenp@4037: }
roland@4159: return compressedKlassPointersEnabled.booleanValue();
coleenp@4037: }
coleenp@4037:
kvn@1926: public int getObjectAlignmentInBytes() {
kvn@1926: if (objectAlignmentInBytes == 0) {
kvn@1926: Flag flag = getCommandLineFlag("ObjectAlignmentInBytes");
kvn@1926: objectAlignmentInBytes = (flag == null) ? 8 : (int)flag.getIntx();
kvn@1926: }
kvn@1926: return objectAlignmentInBytes;
kvn@1926: }
kvn@1926:
sla@4606: /** Indicates whether Thread-Local Allocation Buffers are used */
sla@4606: public boolean getUseTLAB() {
sla@4606: Flag flag = getCommandLineFlag("UseTLAB");
sla@4606: return (flag == null) ? false: flag.getBool();
sla@4606: }
sla@4606:
duke@435: // returns null, if not available.
duke@435: public Flag[] getCommandLineFlags() {
duke@435: if (commandLineFlags == null) {
duke@435: readCommandLineFlags();
duke@435: }
duke@435:
duke@435: return commandLineFlags;
duke@435: }
duke@435:
duke@435: public Flag getCommandLineFlag(String name) {
duke@435: if (flagsMap == null) {
duke@435: flagsMap = new HashMap();
duke@435: Flag[] flags = getCommandLineFlags();
duke@435: for (int i = 0; i < flags.length; i++) {
duke@435: flagsMap.put(flags[i].getName(), flags[i]);
duke@435: }
duke@435: }
duke@435: return (Flag) flagsMap.get(name);
duke@435: }
duke@435:
duke@435: private void readCommandLineFlags() {
duke@435: // get command line flags
duke@435: TypeDataBase db = getTypeDataBase();
never@3138: Type flagType = db.lookupType("Flag");
never@3138: int numFlags = (int) flagType.getCIntegerField("numFlags").getValue();
never@3138: // NOTE: last flag contains null values.
never@3138: commandLineFlags = new Flag[numFlags - 1];
duke@435:
never@3138: Address flagAddr = flagType.getAddressField("flags").getValue();
duke@435:
never@3138: AddressField typeFld = flagType.getAddressField("type");
never@3138: AddressField nameFld = flagType.getAddressField("name");
never@3138: AddressField addrFld = flagType.getAddressField("addr");
never@3138: AddressField kindFld = flagType.getAddressField("kind");
never@3138: CIntField originFld = new CIntField(flagType.getCIntegerField("origin"), 0);
duke@435:
never@3138: long flagSize = flagType.getSize(); // sizeof(Flag)
duke@435:
never@3138: // NOTE: last flag contains null values.
never@3138: for (int f = 0; f < numFlags - 1; f++) {
never@3138: String type = CStringUtilities.getString(typeFld.getValue(flagAddr));
never@3138: String name = CStringUtilities.getString(nameFld.getValue(flagAddr));
never@3138: Address addr = addrFld.getValue(flagAddr);
never@3138: String kind = CStringUtilities.getString(kindFld.getValue(flagAddr));
never@3138: int origin = (int)originFld.getValue(flagAddr);
never@3138: commandLineFlags[f] = new Flag(type, name, addr, kind, origin);
never@3138: flagAddr = flagAddr.addOffsetTo(flagSize);
never@3138: }
duke@435:
never@3138: // sort flags by name
never@3138: Arrays.sort(commandLineFlags, new Comparator() {
never@3138: public int compare(Object o1, Object o2) {
never@3138: Flag f1 = (Flag) o1;
never@3138: Flag f2 = (Flag) o2;
never@3138: return f1.getName().compareTo(f2.getName());
never@3138: }
never@3138: });
duke@435: }
duke@435:
duke@435: public String getSystemProperty(String key) {
duke@435: Properties props = getSystemProperties();
duke@435: return (props != null)? props.getProperty(key) : null;
duke@435: }
duke@435:
duke@435: public Properties getSystemProperties() {
duke@435: if (sysProps == null) {
duke@435: readSystemProperties();
duke@435: }
duke@435: return sysProps;
duke@435: }
duke@435:
duke@435: private void readSystemProperties() {
never@2693: final InstanceKlass systemKls = getSystemDictionary().getSystemKlass();
never@2693: systemKls.iterateStaticFields(new DefaultOopVisitor() {
never@2693: ObjectReader objReader = new ObjectReader();
never@2693: public void doOop(sun.jvm.hotspot.oops.OopField field, boolean isVMField) {
never@2693: if (field.getID().getName().equals("props")) {
never@2693: try {
never@2693: sysProps = (Properties) objReader.readObject(field.getValue(getObj()));
never@2693: } catch (Exception e) {
never@2693: e.printStackTrace();
never@2693: }
never@2693: }
never@2693: }
never@2693: });
duke@435: }
duke@435: }