1 cananian 1.1.2.1 // HClassInfo.java, created Wed Jan 13 17:09:19 1999 by duncan 2 cananian 1.1.2.2 // Copyright (C) 1998 Duncan Bryce <duncan@lcs.mit.edu> 3 cananian 1.1.2.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.2.1 package harpoon.Interpret.Tree; 5 cananian 1.1.2.1 6 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 7 cananian 1.1.2.1 import harpoon.ClassFile.HField; 8 cananian 1.1.2.1 import harpoon.ClassFile.HMember; 9 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 10 cananian 1.1.2.1 import harpoon.Util.HClassUtil; 11 cananian 1.1.2.1 12 cananian 1.1.2.1 import java.util.HashMap; 13 cananian 1.1.2.1 import java.util.Map; 14 cananian 1.1.2.1 15 cananian 1.1.2.1 /** 16 cananian 1.1.2.1 * The <code>HClassInfo</code> class provides various useful bits of 17 cananian 1.1.2.1 * information about an <code>HClass</code>. 18 cananian 1.1.2.1 * 19 cananian 1.1.2.2 * @author Duncan Bryce <duncan@lcs.mit.edu> 20 cananian 1.2 * @version $Id: HClassInfo.java,v 1.2 2002/02/25 21:05:50 cananian Exp $ 21 cananian 1.1.2.1 * @see harpoon.ClassFile.HClass 22 cananian 1.1.2.1 */ 23 cananian 1.1.2.1 class HClassInfo 24 cananian 1.1.2.1 { 25 cananian 1.1.2.1 private HCIMap m_hcim = new HCIMap(); 26 cananian 1.1.2.1 27 cananian 1.1.2.1 /** 28 cananian 1.1.2.1 * @return the depth of <code>hc</code> in the class hierarchy 29 cananian 1.1.2.1 */ 30 cananian 1.1.2.1 public int depth(HClass hc) { 31 cananian 1.1.2.1 return m_hcim.get(hc).depth(); 32 cananian 1.1.2.1 } 33 cananian 1.1.2.1 34 cananian 1.1.2.1 /** 35 cananian 1.1.2.1 * @return the offset of of <code>hf</code> from the initial field. 36 cananian 1.1.2.1 * For instance, if <code>hf</code> is the 3rd field in its class, 37 cananian 1.1.2.1 * <code>getFieldOffset</code> returns 2. 38 cananian 1.1.2.1 */ 39 cananian 1.1.2.1 public int getFieldOffset(HField hf) { 40 cananian 1.1.2.1 return m_hcim.get(hf.getDeclaringClass()).getOffset(hf); 41 cananian 1.1.2.1 } 42 cananian 1.1.2.1 43 cananian 1.1.2.1 /** 44 cananian 1.1.2.1 * @return the offset of of <code>hm</code> from the initial method. 45 cananian 1.1.2.1 * For instance, if <code>hm</code> is the 3rd method in its class, 46 cananian 1.1.2.1 * <code>getMethodOffset()</code> returns 2. 47 cananian 1.1.2.1 */ 48 cananian 1.1.2.1 public int getMethodOffset(HMethod hm) { 49 cananian 1.1.2.1 return m_hcim.get(hm.getDeclaringClass()).getOffset(hm); 50 cananian 1.1.2.1 } 51 cananian 1.1.2.1 52 cananian 1.1.2.1 /** 53 cananian 1.1.2.1 * @return a String representation of this HClassInfo object 54 cananian 1.1.2.1 */ 55 cananian 1.1.2.1 public String toString() { return m_hcim.toString(); } 56 cananian 1.1.2.1 57 cananian 1.1.2.1 /** 58 cananian 1.1.2.1 * @return a String representation of the information stored 59 cananian 1.1.2.1 * about <code>hc</code> 60 cananian 1.1.2.1 */ 61 cananian 1.1.2.1 public String toString(HClass hc) { return m_hcim.get(hc).toString(); } 62 cananian 1.1.2.1 63 cananian 1.1.2.1 final class HCIMap { 64 cananian 1.1.2.1 private Map m_table = new HashMap(); 65 cananian 1.1.2.1 66 cananian 1.1.2.1 HCIUnit get(HClass hc) { 67 cananian 1.1.2.1 HCIUnit hciu; 68 cananian 1.1.2.1 HClass superclass; 69 cananian 1.1.2.1 HCIUnit superclassInfo; 70 cananian 1.1.2.1 71 cananian 1.1.2.1 hciu = (HCIUnit)m_table.get(hc); 72 cananian 1.1.2.1 if (hciu == null) { 73 cananian 1.1.2.1 if (hc.isArray()) { // Treat arrays differently 74 cananian 1.1.2.1 int dims = HClassUtil.dims(hc); 75 cananian 1.1.2.1 HClass baseclass = HClassUtil.baseClass(hc); 76 cananian 1.1.2.1 // hc is not primitive, so hc.getLinker() is safe. 77 cananian 1.1.2.1 superclass = 78 cananian 1.1.2.1 baseclass.isPrimitive() ? 79 cananian 1.1.2.1 hc.getLinker().forName("java.lang.Object") 80 cananian 1.1.2.1 : (baseclass.getDescriptor() 81 cananian 1.1.2.1 .equals("Ljava/lang/Object;") ? 82 cananian 1.1.2.1 (HClassUtil.arrayClass(hc.getLinker(), 83 cananian 1.1.2.1 baseclass, dims-1)) 84 cananian 1.1.2.1 : HClassUtil.arrayClass(hc.getLinker(), 85 cananian 1.1.2.1 baseclass.getSuperclass(), 86 cananian 1.1.2.1 dims)); 87 cananian 1.1.2.1 } 88 cananian 1.1.2.1 else { superclass = hc.getSuperclass(); } 89 cananian 1.1.2.1 if (superclass != null) { 90 cananian 1.1.2.1 superclassInfo = get(superclass); 91 cananian 1.1.2.1 hciu = new HCIUnit(hc, superclassInfo); 92 cananian 1.1.2.1 } 93 cananian 1.1.2.1 else { 94 cananian 1.1.2.1 hciu = new HCIUnit(hc); 95 cananian 1.1.2.1 } 96 cananian 1.1.2.1 m_table.put(hc, hciu); 97 cananian 1.1.2.1 } 98 cananian 1.1.2.1 return hciu; 99 cananian 1.1.2.1 } 100 cananian 1.1.2.1 101 cananian 1.1.2.1 public String toString() { return m_table.toString(); } 102 cananian 1.1.2.1 } 103 cananian 1.1.2.1 } 104 cananian 1.1.2.1 105 cananian 1.1.2.1 106 cananian 1.1.2.1 class HCIUnit { 107 cananian 1.1.2.1 108 cananian 1.1.2.1 private HMemberMap m_memberMap; 109 cananian 1.1.2.1 private int m_currentFieldOffset = 0; 110 cananian 1.1.2.1 private int m_currentMethodOffset = 0; 111 cananian 1.1.2.1 private static int m_currentStaticFieldOffset = 0; 112 cananian 1.1.2.1 private int m_depth; 113 cananian 1.1.2.1 114 cananian 1.1.2.1 // Constructor used for classes extending another class 115 cananian 1.1.2.1 // (i.e. anything other than class Object) 116 cananian 1.1.2.1 HCIUnit(HClass hc, HCIUnit scInfo) { 117 cananian 1.1.2.1 m_depth = scInfo.depth() + 1; 118 cananian 1.1.2.1 m_currentMethodOffset = scInfo.m_currentMethodOffset; 119 cananian 1.1.2.1 m_currentFieldOffset = scInfo.m_currentFieldOffset; 120 cananian 1.1.2.1 m_memberMap = new HMemberMap(scInfo.m_memberMap); 121 cananian 1.1.2.1 extend(hc); 122 cananian 1.1.2.1 } 123 cananian 1.1.2.1 124 cananian 1.1.2.1 // Constructor used for classes which don't extend anything 125 cananian 1.1.2.1 // (Object) 126 cananian 1.1.2.1 HCIUnit(HClass hc) { 127 cananian 1.1.2.1 m_depth = 0; 128 cananian 1.1.2.1 m_memberMap = new HMemberMap(); 129 cananian 1.1.2.1 extend(hc); 130 cananian 1.1.2.1 } 131 cananian 1.1.2.1 132 cananian 1.1.2.1 int depth() { return m_depth; } 133 cananian 1.1.2.1 134 cananian 1.1.2.1 int getOffset(HMember hm) { return m_memberMap.get(hm); } 135 cananian 1.1.2.1 136 cananian 1.1.2.1 private void extend(HClass hc) { 137 cananian 1.1.2.1 HField[] hFields = hc.getDeclaredFields(); 138 cananian 1.1.2.1 for (int i = 0; i < hFields.length; i++) { 139 cananian 1.1.2.1 if (hFields[i].isStatic()) 140 cananian 1.1.2.1 m_currentStaticFieldOffset = 141 cananian 1.1.2.1 m_memberMap.map(hFields[i], m_currentStaticFieldOffset); 142 cananian 1.1.2.1 else 143 cananian 1.1.2.1 m_currentFieldOffset = 144 cananian 1.1.2.1 m_memberMap.map(hFields[i], m_currentFieldOffset); 145 cananian 1.1.2.1 } 146 cananian 1.1.2.1 147 cananian 1.1.2.1 HMethod[] hMethods = hc.getDeclaredMethods(); 148 cananian 1.1.2.1 for (int i = 0; i < hMethods.length; i++) { 149 cananian 1.1.2.1 m_currentMethodOffset = 150 cananian 1.1.2.1 m_memberMap.map(hMethods[i], m_currentMethodOffset); 151 cananian 1.1.2.1 } 152 cananian 1.1.2.1 } 153 cananian 1.1.2.1 154 cananian 1.1.2.1 public String toString() { return m_memberMap.toString(); } 155 cananian 1.1.2.1 156 cananian 1.1.2.1 // Used to map HMethods and HFields to offsets 157 cananian 1.1.2.1 final class HMemberMap { 158 cananian 1.1.2.1 private Map m_table; 159 cananian 1.1.2.1 160 cananian 1.1.2.1 HMemberMap() { m_table = new HashMap(); } 161 cananian 1.1.2.1 162 cananian 1.1.2.1 HMemberMap(HMemberMap map) { m_table = new HashMap(map.m_table); } 163 cananian 1.1.2.1 164 cananian 1.1.2.1 int map(HField hf, int next) { 165 cananian 1.1.2.1 m_table.put(hf, new Integer(next++)); 166 cananian 1.1.2.1 return next; 167 cananian 1.1.2.1 } 168 cananian 1.1.2.1 169 cananian 1.1.2.1 int map(HMethod hm, int next) { 170 cananian 1.1.2.1 int offset; 171 cananian 1.1.2.1 String sig = getSignature(hm); 172 cananian 1.1.2.1 173 cananian 1.1.2.1 if (m_table.get(sig) == null) { 174 cananian 1.1.2.1 // Method does not override anything 175 cananian 1.1.2.1 offset = next++; 176 cananian 1.1.2.1 } 177 cananian 1.1.2.1 else { 178 cananian 1.1.2.1 HMethod scMethod = (HMethod)(m_table.get(sig)); 179 cananian 1.1.2.1 offset = ((Integer)m_table.get(scMethod)).intValue(); 180 cananian 1.1.2.1 } 181 cananian 1.1.2.1 182 cananian 1.1.2.1 m_table.put(sig, hm); 183 cananian 1.1.2.1 m_table.put(hm, new Integer(offset)); 184 cananian 1.1.2.1 185 cananian 1.1.2.1 return next; 186 cananian 1.1.2.1 } 187 cananian 1.1.2.1 188 cananian 1.1.2.1 int get(HMember hm) { 189 cananian 1.1.2.1 return (m_table.containsKey(hm) ? 190 cananian 1.1.2.1 ((Integer)m_table.get(hm)).intValue() : 191 cananian 1.1.2.1 Integer.MIN_VALUE); 192 cananian 1.1.2.1 } 193 cananian 1.1.2.1 194 cananian 1.1.2.1 private String getSignature(HMethod hm) { 195 cananian 1.1.2.1 HClass[] paramTypes; 196 cananian 1.1.2.1 StringBuffer sb; 197 cananian 1.1.2.1 198 cananian 1.1.2.1 sb = new StringBuffer(""); 199 cananian 1.1.2.1 sb.append(hm.getName()); 200 cananian 1.1.2.1 paramTypes = hm.getParameterTypes(); 201 cananian 1.1.2.1 for (int i = 0; i < paramTypes.length; i++) 202 cananian 1.1.2.1 sb.append(paramTypes[i].toString()); 203 cananian 1.1.2.1 return sb.toString(); 204 cananian 1.1.2.1 } 205 cananian 1.1.2.1 206 cananian 1.1.2.1 public String toString() { return m_table.toString(); } 207 cananian 1.1.2.1 } 208 cananian 1.2 }