| /* |
| * Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.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.*; |
| import sun.jvm.hotspot.utilities.*; |
| |
| /** <P> This is a basic implementation of the Type interface which |
| should be complete enough to be portable across platforms. The |
| only issue will be the construction of these objects and their |
| components from the platform-specific debugging information; see |
| BasicTypeDataBase. </P> |
| |
| <P> There are two types of clients of this class. The first is |
| that which builds the TypeDatabase. This kind of client uses the |
| additional public methods beyond those in the Type interface to |
| properly configure the BasicType objects. The second is the |
| consumer of these types; this kind of client should deal only with |
| the Type interfaces. </P> */ |
| |
| public class BasicType implements Type { |
| protected BasicTypeDataBase db; |
| |
| private String name; |
| private long size; |
| private boolean isJavaPrimitiveType; |
| private boolean isOopType; |
| // These are only the fields defined in this class, not any of this |
| // class's superclasses. |
| private Map nameToFieldMap = new HashMap(); |
| private List fieldList = new LinkedList(); |
| // Superclass, or null if none. Primitive types do not have any |
| // inheritance relationship. |
| private Type superclass; |
| |
| /** superclass may be null */ |
| public BasicType(BasicTypeDataBase db, String name, Type superclass) { |
| if (name == null) { |
| throw new IllegalArgumentException("name may not be null"); |
| } |
| this.db = db; |
| this.name = name; |
| this.superclass = superclass; |
| } |
| |
| /** Equivalent to BasicType(db, name, null) */ |
| public BasicType(BasicTypeDataBase db, String name) { |
| this(db, name, null); |
| } |
| |
| public boolean equals(Object obj) { |
| if (obj == null) { |
| return false; |
| } |
| |
| if (!(obj instanceof BasicType)) { |
| return false; |
| } |
| |
| BasicType arg = (BasicType) obj; |
| |
| if (!name.equals(arg.name)) { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| public int hashCode() { |
| return name.hashCode(); |
| } |
| |
| public String toString() { |
| return name; |
| } |
| |
| public String getName() { |
| return name; |
| } |
| |
| /** This should only be called at most once, and only by the builder |
| of the type database */ |
| public void setSuperclass(Type superclass) { |
| this.superclass = superclass; |
| } |
| |
| public Type getSuperclass() { |
| return superclass; |
| } |
| |
| /** This should only be called at most once, and only by the builder |
| of the type database */ |
| public void setSize(long sizeInBytes) { |
| this.size = sizeInBytes; |
| } |
| |
| public long getSize() { |
| return size; |
| } |
| |
| /** Overridden by BasicCIntegerType */ |
| public boolean isCIntegerType() { |
| return false; |
| } |
| |
| public boolean isCStringType() { |
| if (isPointerType()) { |
| Type target = ((PointerType)this).getTargetType(); |
| return target.isCIntegerType() && |
| target.getName().equals("const char"); |
| } else { |
| return false; |
| } |
| } |
| |
| public boolean isJavaPrimitiveType() { |
| return isJavaPrimitiveType; |
| } |
| |
| /** This should only be called at most once, and only by the builder |
| of the type database */ |
| public void setIsJavaPrimitiveType(boolean isJavaPrimitiveType) { |
| this.isJavaPrimitiveType = isJavaPrimitiveType; |
| } |
| |
| public boolean isOopType() { |
| return isOopType; |
| } |
| |
| /** Overridden by BasicPointerType */ |
| public boolean isPointerType() { |
| return false; |
| } |
| |
| /** This should only be called at most once, and only by the builder |
| of the type database */ |
| public void setIsOopType(boolean isOopType) { |
| this.isOopType = isOopType; |
| } |
| |
| public Field getField(String fieldName, boolean searchSuperclassFields, |
| boolean throwExceptionIfNotFound) { |
| Field field = null; |
| if (nameToFieldMap != null) { |
| field = (Field) nameToFieldMap.get(fieldName); |
| |
| if (field != null) { |
| return field; |
| } |
| } |
| |
| if (searchSuperclassFields) { |
| if (superclass != null) { |
| field = superclass.getField(fieldName, searchSuperclassFields, false); |
| } |
| } |
| |
| if (field == null && throwExceptionIfNotFound) { |
| throw new RuntimeException("field \"" + fieldName + "\" not found in type " + name); |
| } |
| |
| return field; |
| } |
| |
| public Field getField(String fieldName, boolean searchSuperclassFields) { |
| return getField(fieldName, searchSuperclassFields, true); |
| } |
| |
| public Field getField(String fieldName) { |
| return getField(fieldName, true); |
| } |
| |
| public Field getField(String fieldName, Type declaredType, |
| boolean searchSuperclassFields) throws WrongTypeException { |
| Field res = getField(fieldName, searchSuperclassFields); |
| if (res == null) { |
| return null; |
| } |
| if (!res.getType().equals(declaredType)) { |
| throw new WrongTypeException("field \"" + fieldName + "\" in type " + name + |
| " is not of type " + declaredType + |
| ", but instead of type " + res.getType()); |
| } |
| return res; |
| } |
| |
| public Field getField(String fieldName, Type declaredType) throws WrongTypeException { |
| return getField(fieldName, declaredType, false); |
| } |
| |
| /** The returned iterator's "remove" method must not be called */ |
| public Iterator getFields() { |
| return new ConstIterator(fieldList.iterator()); |
| } |
| |
| //-------------------------------------------------------------------------------- |
| // Specialized field type accessors |
| // |
| |
| public JBooleanField getJBooleanField(String fieldName) throws WrongTypeException { |
| return (JBooleanField) getField(fieldName, db.getJBooleanType()); |
| } |
| |
| public JByteField getJByteField(String fieldName) throws WrongTypeException { |
| return (JByteField) getField(fieldName, db.getJByteType()); |
| } |
| |
| public JCharField getJCharField(String fieldName) throws WrongTypeException { |
| return (JCharField) getField(fieldName, db.getJCharType()); |
| } |
| |
| public JDoubleField getJDoubleField(String fieldName) throws WrongTypeException { |
| return (JDoubleField) getField(fieldName, db.getJDoubleType()); |
| } |
| |
| public JFloatField getJFloatField(String fieldName) throws WrongTypeException { |
| return (JFloatField) getField(fieldName, db.getJFloatType()); |
| } |
| |
| public JIntField getJIntField(String fieldName) throws WrongTypeException { |
| return (JIntField) getField(fieldName, db.getJIntType()); |
| } |
| |
| public JLongField getJLongField(String fieldName) throws WrongTypeException { |
| return (JLongField) getField(fieldName, db.getJLongType()); |
| } |
| |
| public JShortField getJShortField(String fieldName) throws WrongTypeException { |
| return (JShortField) getField(fieldName, db.getJShortType()); |
| } |
| |
| public CIntegerField getCIntegerField(String fieldName) throws WrongTypeException { |
| Field field = getField(fieldName); |
| if (!(field.getType() instanceof CIntegerType)) { |
| throw new WrongTypeException("field \"" + fieldName + "\" in type " + name + |
| " is not of C integer type, but instead of type " + |
| field.getType()); |
| } |
| return (CIntegerField) field; |
| } |
| |
| public OopField getOopField(String fieldName) throws WrongTypeException { |
| Field field = getField(fieldName); |
| if (!field.getType().isOopType()) { |
| throw new WrongTypeException("field \"" + fieldName + "\" in type " + name + |
| " is not of oop type, but instead of type " + |
| field.getType()); |
| } |
| return (OopField) field; |
| } |
| |
| public NarrowOopField getNarrowOopField(String fieldName) throws WrongTypeException { |
| return (NarrowOopField) new BasicNarrowOopField(getOopField(fieldName)); |
| } |
| |
| public AddressField getAddressField(String fieldName) { |
| // This type can not be inferred (for now), so provide a wrapper |
| Field field = getField(fieldName); |
| if (field == null) { |
| return null; |
| } |
| return new BasicAddressFieldWrapper(field); |
| } |
| |
| /** This method should only be used by the builder of the |
| TypeDataBase. Throws a RuntimeException if a field with this |
| name was already present in this class. */ |
| public void addField(Field field) { |
| if (nameToFieldMap.get(field.getName()) != null) { |
| throw new RuntimeException("field of name \"" + field.getName() + "\" already present in type " + this); |
| } |
| |
| nameToFieldMap.put(field.getName(), field); |
| fieldList.add(field); |
| } |
| |
| /** This method should only be used by the builder of the |
| TypeDataBase. Throws a RuntimeException if a field with this |
| name was not present in this class. */ |
| public void removeField(Field field) { |
| if (nameToFieldMap.remove(field.getName()) == null) { |
| throw new RuntimeException("field of name \"" + field.getName() + "\" was not present"); |
| } |
| fieldList.remove(field); |
| } |
| } |