Mercurial > hg > truffle
diff agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java @ 0:a61af66fc99e jdk7-b24
Initial load
author | duke |
---|---|
date | Sat, 01 Dec 2007 00:00:00 +0000 |
parents | |
children | ba764ed4b6f2 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/agent/src/share/classes/sun/jvm/hotspot/types/basic/BasicTypeDataBase.java Sat Dec 01 00:00:00 2007 +0000 @@ -0,0 +1,407 @@ +/* + * Copyright 2000-2004 Sun Microsystems, Inc. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + * + */ + +package sun.jvm.hotspot.types.basic; + +import java.util.*; +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.types.*; + +/** <P> This is a basic implementation of the TypeDataBase interface. + It allows an external type database builder to add types to be + consumed by a client through the Type interfaces. It has no + knowledge of symbol lookup; for example, the builder is + responsible for providing the addresses of static fields. </P> + + <P> Among other things, the database builder is responsible for + providing the Types for the Java primitive types, as well as their + sizes. </P> +*/ + +public class BasicTypeDataBase implements TypeDataBase { + private MachineDescription machDesc; + private VtblAccess vtblAccess; + /** Maps strings to Type objects. This does not contain the primitive types. */ + private Map nameToTypeMap = new HashMap(); + /** Maps strings to Integers, used for enums, etc. */ + private Map nameToIntConstantMap = new HashMap(); + /** Maps strings to Longs, used for 32/64-bit constants, etc. */ + private Map nameToLongConstantMap = new HashMap(); + /** Primitive types. */ + private Type jbooleanType; + private Type jbyteType; + private Type jcharType; + private Type jdoubleType; + private Type jfloatType; + private Type jintType; + private Type jlongType; + private Type jshortType; + + /** For debugging */ + private static final boolean DEBUG; + static { + DEBUG = System.getProperty("sun.jvm.hotspot.types.basic.BasicTypeDataBase.DEBUG") != null; + } + + public BasicTypeDataBase(MachineDescription machDesc, VtblAccess vtblAccess) { + this.machDesc = machDesc; + this.vtblAccess = vtblAccess; + } + + public Type lookupType(String cTypeName) { + return lookupType(cTypeName, true); + } + + public Type lookupType(String cTypeName, boolean throwException) { + Type type = (Type) nameToTypeMap.get(cTypeName); + if (type == null && throwException) { + throw new RuntimeException("No type named \"" + cTypeName + "\" in database"); + } + return type; + } + + public Integer lookupIntConstant(String constantName) { + return lookupIntConstant(constantName, true); + } + + public Integer lookupIntConstant(String constantName, boolean throwException) { + Integer i = (Integer) nameToIntConstantMap.get(constantName); + if (i == null) { + if (throwException) { + throw new RuntimeException("No integer constant named \"" + constantName + "\" present in type database"); + } + } + return i; + } + + public Long lookupLongConstant(String constantName) { + return lookupLongConstant(constantName, true); + } + + public Long lookupLongConstant(String constantName, boolean throwException) { + Long i = (Long) nameToLongConstantMap.get(constantName); + if (i == null) { + if (throwException) { + throw new RuntimeException("No long constant named \"" + constantName + "\" present in type database"); + } + } + return i; + } + + public Type getJBooleanType() { + return jbooleanType; + } + + public Type getJByteType() { + return jbyteType; + } + + public Type getJCharType() { + return jcharType; + } + + public Type getJDoubleType() { + return jdoubleType; + } + + public Type getJFloatType() { + return jfloatType; + } + + public Type getJIntType() { + return jintType; + } + + public Type getJLongType() { + return jlongType; + } + + public Type getJShortType() { + return jshortType; + } + + public long getAddressSize() { + return machDesc.getAddressSize(); + } + + public long getOopSize() { + return machDesc.getOopSize(); + } + + public boolean addressTypeIsEqualToType(Address addr, Type type) { + if (addr == null) { + return false; + } + + // This implementation should be suitably platform-independent; we + // search nearby memory for the vtbl value of the given type. + + Address vtblAddr = vtblAccess.getVtblForType(type); + + if (vtblAddr == null) { + // Type was not polymorphic, or an error occurred during lookup + if (DEBUG) { + System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: vtblAddr == null"); + } + + return false; + } + + // The first implementation searched three locations for this vtbl + // value; scanning through the entire object was considered, but + // we thought we knew where we were looking, and looking only in + // these specific locations should reduce the probability of + // mistaking random bits as a pointer (although, realistically + // speaking, the likelihood of finding a match between the bit + // pattern of, for example, a double and the vtbl is vanishingly + // small.) + // 1. The first word of the object (should handle MSVC++ as + // well as the SparcWorks compilers with compatibility set to + // v5.0 or greater) + // 2. and 3. The last two Address-aligned words of the part of + // the object defined by its topmost polymorphic superclass. + // This should handle the SparcWorks compilers, v4.2 or + // earlier, as well as any other compilers which place the vptr + // at the end of the user-defined fields of the first base + // class with virtual functions. + // + // Unfortunately this algorithm did not work properly for the + // specific case of the ThreadShadow/Thread inheritance situation, + // because the Solaris compiler seems to cleverly eliminate the + // vtbl for ThreadShadow since the only virtual is empty. (We + // should get rid of the ThreadShadow and fix the include + // databases, but need to postpone this for the present.) The + // current solution performs the three-location check for this + // class and all of its known superclasses rather than just the + // topmost polymorphic one. + + Type curType = type; + + try { + while (curType != null) { + // Using the size information we have for this type, check the + // three locations described above. + + // (1) + if (vtblAddr.equals(addr.getAddressAt(0))) { + return true; + } + + // (2) + long offset = curType.getSize(); + // I don't think this should be misaligned under any + // circumstances, but I'm not sure (FIXME: also not sure which + // way to go here, up or down -- assuming down) + offset -= (offset % getAddressSize()); + if (offset <= 0) { + return false; + } + if (vtblAddr.equals(addr.getAddressAt(offset))) { + return true; + } + offset -= getAddressSize(); + if (offset <= 0) { + return false; + } + if (vtblAddr.equals(addr.getAddressAt(offset))) { + return true; + } + + curType = curType.getSuperclass(); + } + } + catch (Exception e) { + // Any UnmappedAddressExceptions, etc. are a good indication + // that the pointer is not of the specified type + if (DEBUG) { + System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: exception occurred during lookup:"); + e.printStackTrace(); + } + + return false; + } + + if (DEBUG) { + System.err.println("BasicTypeDataBase.addressTypeIsEqualToType: all vptr tests failed for type " + + type.getName()); + } + + return false; + } + + public Type guessTypeForAddress(Address addr) { + for (Iterator iter = getTypes(); iter.hasNext(); ) { + Type t = (Type) iter.next(); + if (addressTypeIsEqualToType(addr, t)) { + return t; + } + } + return null; + } + + public long cIntegerTypeMaxValue(long sizeInBytes, boolean isUnsigned) { + return machDesc.cIntegerTypeMaxValue(sizeInBytes, isUnsigned); + } + + public long cIntegerTypeMinValue(long sizeInBytes, boolean isUnsigned) { + return machDesc.cIntegerTypeMinValue(sizeInBytes, isUnsigned); + } + + public Iterator getTypes() { + return nameToTypeMap.values().iterator(); + } + + public Iterator getIntConstants() { + return nameToIntConstantMap.keySet().iterator(); + } + + public Iterator getLongConstants() { + return nameToLongConstantMap.keySet().iterator(); + } + + //-------------------------------------------------------------------------------- + // Public routines only for use by the database builder + // + + /** This method should only be called by the builder of the + TypeDataBase and at most once */ + public void setJBooleanType(Type type) { + jbooleanType = type; + } + + /** This method should only be called by the builder of the + TypeDataBase and at most once */ + public void setJByteType(Type type) { + jbyteType = type; + } + + /** This method should only be called by the builder of the + TypeDataBase and at most once */ + public void setJCharType(Type type) { + jcharType = type; + } + + /** This method should only be called by the builder of the + TypeDataBase and at most once */ + public void setJDoubleType(Type type) { + jdoubleType = type; + } + + /** This method should only be called by the builder of the + TypeDataBase and at most once */ + public void setJFloatType(Type type) { + jfloatType = type; + } + + /** This method should only be called by the builder of the + TypeDataBase and at most once */ + public void setJIntType(Type type) { + jintType = type; + } + + /** This method should only be called by the builder of the + TypeDataBase and at most once */ + public void setJLongType(Type type) { + jlongType = type; + } + + /** This method should only be called by the builder of the + TypeDataBase and at most once */ + public void setJShortType(Type type) { + jshortType = type; + } + + /** This method should only be used by the builder of the + TypeDataBase. Throws a RuntimeException if a class with this + name was already present. */ + public void addType(Type type) { + if (nameToTypeMap.get(type.getName()) != null) { + throw new RuntimeException("type of name \"" + type.getName() + "\" already present"); + } + + nameToTypeMap.put(type.getName(), type); + } + + /** This method should only be used by the builder of the + TypeDataBase. Throws a RuntimeException if this class was not + present. */ + public void removeType(Type type) { + Type curType = (Type) nameToTypeMap.get(type.getName()); + if (curType == null) { + throw new RuntimeException("type of name \"" + type.getName() + "\" not present"); + } + + if (!curType.equals(type)) { + throw new RuntimeException("a different type of name \"" + type.getName() + "\" was present"); + } + + nameToTypeMap.remove(type.getName()); + } + + /** This method should only be used by the builder of the + TypeDataBase. Throws a RuntimeException if an integer constant + with this name was already present. */ + public void addIntConstant(String name, int value) { + if (nameToIntConstantMap.get(name) != null) { + throw new RuntimeException("int constant of name \"" + name + "\" already present"); + } + + nameToIntConstantMap.put(name, new Integer(value)); + } + + /** This method should only be used by the builder of the + TypeDataBase. Throws a RuntimeException if an integer constant + with this name was not present. */ + public void removeIntConstant(String name) { + Integer curConstant = (Integer) nameToIntConstantMap.get(name); + if (curConstant == null) { + throw new RuntimeException("int constant of name \"" + name + "\" not present"); + } + + nameToIntConstantMap.remove(name); + } + + /** This method should only be used by the builder of the + TypeDataBase. Throws a RuntimeException if a long constant with + this name was already present. */ + public void addLongConstant(String name, long value) { + if (nameToLongConstantMap.get(name) != null) { + throw new RuntimeException("long constant of name \"" + name + "\" already present"); + } + + nameToLongConstantMap.put(name, new Long(value)); + } + + /** This method should only be used by the builder of the + TypeDataBase. Throws a RuntimeException if a long constant with + this name was not present. */ + public void removeLongConstant(String name) { + Long curConstant = (Long) nameToLongConstantMap.get(name); + if (curConstant == null) { + throw new RuntimeException("long constant of name \"" + name + "\" not present"); + } + + nameToLongConstantMap.remove(name); + } +}