1/* 2 * Copyright (c) 2000, 2008, 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 25package sun.jvm.hotspot.types.basic; 26 27import java.util.*; 28import sun.jvm.hotspot.debugger.*; 29import sun.jvm.hotspot.types.*; 30import sun.jvm.hotspot.utilities.*; 31 32/** <P> This is a basic implementation of the Type interface which 33 should be complete enough to be portable across platforms. The 34 only issue will be the construction of these objects and their 35 components from the platform-specific debugging information; see 36 BasicTypeDataBase. </P> 37 38 <P> There are two types of clients of this class. The first is 39 that which builds the TypeDatabase. This kind of client uses the 40 additional public methods beyond those in the Type interface to 41 properly configure the BasicType objects. The second is the 42 consumer of these types; this kind of client should deal only with 43 the Type interfaces. </P> */ 44 45public class BasicType implements Type { 46 protected BasicTypeDataBase db; 47 48 private String name; 49 private long size; 50 private boolean isJavaPrimitiveType; 51 private boolean isOopType; 52 // These are only the fields defined in this class, not any of this 53 // class's superclasses. 54 private Map nameToFieldMap = new HashMap(); 55 private List fieldList = new LinkedList(); 56 // Superclass, or null if none. Primitive types do not have any 57 // inheritance relationship. 58 private Type superclass; 59 60 /** superclass may be null */ 61 public BasicType(BasicTypeDataBase db, String name, Type superclass) { 62 if (name == null) { 63 throw new IllegalArgumentException("name may not be null"); 64 } 65 this.db = db; 66 this.name = name; 67 this.superclass = superclass; 68 } 69 70 /** Equivalent to BasicType(db, name, null) */ 71 public BasicType(BasicTypeDataBase db, String name) { 72 this(db, name, null); 73 } 74 75 public boolean equals(Object obj) { 76 if (obj == null) { 77 return false; 78 } 79 80 if (!(obj instanceof BasicType)) { 81 return false; 82 } 83 84 BasicType arg = (BasicType) obj; 85 86 if (!name.equals(arg.name)) { 87 return false; 88 } 89 90 return true; 91 } 92 93 public int hashCode() { 94 return name.hashCode(); 95 } 96 97 public String toString() { 98 return name; 99 } 100 101 public String getName() { 102 return name; 103 } 104 105 /** This should only be called at most once, and only by the builder 106 of the type database */ 107 public void setSuperclass(Type superclass) { 108 this.superclass = superclass; 109 } 110 111 public Type getSuperclass() { 112 return superclass; 113 } 114 115 /** This should only be called at most once, and only by the builder 116 of the type database */ 117 public void setSize(long sizeInBytes) { 118 this.size = sizeInBytes; 119 } 120 121 public long getSize() { 122 return size; 123 } 124 125 /** Overridden by BasicCIntegerType */ 126 public boolean isCIntegerType() { 127 return false; 128 } 129 130 public boolean isCStringType() { 131 if (isPointerType()) { 132 Type target = ((PointerType)this).getTargetType(); 133 return target.isCIntegerType() && 134 target.getName().equals("const char"); 135 } else { 136 return false; 137 } 138 } 139 140 public boolean isJavaPrimitiveType() { 141 return isJavaPrimitiveType; 142 } 143 144 /** This should only be called at most once, and only by the builder 145 of the type database */ 146 public void setIsJavaPrimitiveType(boolean isJavaPrimitiveType) { 147 this.isJavaPrimitiveType = isJavaPrimitiveType; 148 } 149 150 public boolean isOopType() { 151 return isOopType; 152 } 153 154 /** Overridden by BasicPointerType */ 155 public boolean isPointerType() { 156 return false; 157 } 158 159 /** This should only be called at most once, and only by the builder 160 of the type database */ 161 public void setIsOopType(boolean isOopType) { 162 this.isOopType = isOopType; 163 } 164 165 public Field getField(String fieldName, boolean searchSuperclassFields, 166 boolean throwExceptionIfNotFound) { 167 Field field = null; 168 if (nameToFieldMap != null) { 169 field = (Field) nameToFieldMap.get(fieldName); 170 171 if (field != null) { 172 return field; 173 } 174 } 175 176 if (searchSuperclassFields) { 177 if (superclass != null) { 178 field = superclass.getField(fieldName, searchSuperclassFields, false); 179 } 180 } 181 182 if (field == null && throwExceptionIfNotFound) { 183 throw new RuntimeException("field \"" + fieldName + "\" not found in type " + name); 184 } 185 186 return field; 187 } 188 189 public Field getField(String fieldName, boolean searchSuperclassFields) { 190 return getField(fieldName, searchSuperclassFields, true); 191 } 192 193 public Field getField(String fieldName) { 194 return getField(fieldName, true); 195 } 196 197 public Field getField(String fieldName, Type declaredType, 198 boolean searchSuperclassFields) throws WrongTypeException { 199 Field res = getField(fieldName, searchSuperclassFields); 200 if (res == null) { 201 return null; 202 } 203 if (!res.getType().equals(declaredType)) { 204 throw new WrongTypeException("field \"" + fieldName + "\" in type " + name + 205 " is not of type " + declaredType + 206 ", but instead of type " + res.getType()); 207 } 208 return res; 209 } 210 211 public Field getField(String fieldName, Type declaredType) throws WrongTypeException { 212 return getField(fieldName, declaredType, false); 213 } 214 215 /** The returned iterator's "remove" method must not be called */ 216 public Iterator getFields() { 217 return new ConstIterator(fieldList.iterator()); 218 } 219 220 //-------------------------------------------------------------------------------- 221 // Specialized field type accessors 222 // 223 224 public JBooleanField getJBooleanField(String fieldName) throws WrongTypeException { 225 return (JBooleanField) getField(fieldName, db.getJBooleanType()); 226 } 227 228 public JByteField getJByteField(String fieldName) throws WrongTypeException { 229 return (JByteField) getField(fieldName, db.getJByteType()); 230 } 231 232 public JCharField getJCharField(String fieldName) throws WrongTypeException { 233 return (JCharField) getField(fieldName, db.getJCharType()); 234 } 235 236 public JDoubleField getJDoubleField(String fieldName) throws WrongTypeException { 237 return (JDoubleField) getField(fieldName, db.getJDoubleType()); 238 } 239 240 public JFloatField getJFloatField(String fieldName) throws WrongTypeException { 241 return (JFloatField) getField(fieldName, db.getJFloatType()); 242 } 243 244 public JIntField getJIntField(String fieldName) throws WrongTypeException { 245 return (JIntField) getField(fieldName, db.getJIntType()); 246 } 247 248 public JLongField getJLongField(String fieldName) throws WrongTypeException { 249 return (JLongField) getField(fieldName, db.getJLongType()); 250 } 251 252 public JShortField getJShortField(String fieldName) throws WrongTypeException { 253 return (JShortField) getField(fieldName, db.getJShortType()); 254 } 255 256 public CIntegerField getCIntegerField(String fieldName) throws WrongTypeException { 257 Field field = getField(fieldName); 258 if (!(field.getType() instanceof CIntegerType)) { 259 throw new WrongTypeException("field \"" + fieldName + "\" in type " + name + 260 " is not of C integer type, but instead of type " + 261 field.getType()); 262 } 263 return (CIntegerField) field; 264 } 265 266 public OopField getOopField(String fieldName) throws WrongTypeException { 267 Field field = getField(fieldName); 268 if (!field.getType().isOopType()) { 269 throw new WrongTypeException("field \"" + fieldName + "\" in type " + name + 270 " is not of oop type, but instead of type " + 271 field.getType()); 272 } 273 return (OopField) field; 274 } 275 276 public NarrowOopField getNarrowOopField(String fieldName) throws WrongTypeException { 277 return (NarrowOopField) new BasicNarrowOopField(getOopField(fieldName)); 278 } 279 280 public AddressField getAddressField(String fieldName) { 281 // This type can not be inferred (for now), so provide a wrapper 282 Field field = getField(fieldName); 283 if (field == null) { 284 return null; 285 } 286 return new BasicAddressFieldWrapper(field); 287 } 288 289 /** This method should only be used by the builder of the 290 TypeDataBase. Throws a RuntimeException if a field with this 291 name was already present in this class. */ 292 public void addField(Field field) { 293 if (nameToFieldMap.get(field.getName()) != null) { 294 throw new RuntimeException("field of name \"" + field.getName() + "\" already present in type " + this); 295 } 296 297 nameToFieldMap.put(field.getName(), field); 298 fieldList.add(field); 299 } 300 301 /** This method should only be used by the builder of the 302 TypeDataBase. Throws a RuntimeException if a field with this 303 name was not present in this class. */ 304 public void removeField(Field field) { 305 if (nameToFieldMap.remove(field.getName()) == null) { 306 throw new RuntimeException("field of name \"" + field.getName() + "\" was not present"); 307 } 308 fieldList.remove(field); 309 } 310} 311