1 cananian 1.1.2.1 // OffsetMap32.java, created Wed Feb 3 18:43:47 1999 by duncan 2 cananian 1.1.2.1 // 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.Analysis.ClassHierarchy; 7 cananian 1.1.2.1 import harpoon.Backend.Analysis.InterfaceMethodMap; 8 cananian 1.1.2.1 import harpoon.ClassFile.HClass; 9 cananian 1.1.2.1 import harpoon.ClassFile.HField; 10 cananian 1.1.2.1 import harpoon.ClassFile.HMethod; 11 cananian 1.1.2.1 import harpoon.Backend.Maps.ClassDepthMap; 12 cananian 1.1.2.1 import harpoon.Backend.Maps.MethodMap; 13 cananian 1.1.2.1 import harpoon.Temp.Label; 14 cananian 1.1.2.1 import harpoon.Util.Util; 15 cananian 1.1.2.1 16 cananian 1.1.2.1 import java.util.ArrayList; 17 cananian 1.1.2.1 import java.util.Collections; 18 cananian 1.1.2.1 import java.util.HashMap; 19 cananian 1.1.2.1 import java.util.Iterator; 20 cananian 1.1.2.1 import java.util.List; 21 cananian 1.1.2.1 import java.util.Map; 22 cananian 1.1.2.1 import java.util.NoSuchElementException; 23 cananian 1.1.2.1 import java.util.Set; 24 cananian 1.1.2.1 import java.util.StringTokenizer; 25 cananian 1.1.2.1 26 cananian 1.1.2.1 /** 27 cananian 1.1.2.1 * The <code>OffsetMap32</code> class implements the abstract methods of 28 cananian 1.1.2.1 * <code>OffsetMap</code>, specializing them for 32-bit architectures. 29 cananian 1.1.2.1 * For reference, <code>OffsetMap32</code> specifies the following 30 cananian 1.1.2.1 * layouts: 31 cananian 1.1.2.1 * 32 cananian 1.1.2.1 * <br><b>Object instance layout:</b> 33 cananian 1.1.2.1 * <pre> 34 cananian 1.1.2.1 * -8 hashcode 35 cananian 1.1.2.1 * -4 clazz ptr 36 cananian 1.1.2.1 * 0 non-static field 0 37 cananian 1.1.2.1 * 4 non-static field 1 38 cananian 1.1.2.1 * ... 39 cananian 1.1.2.1 * 4*(n-1) non-static field n-1 40 cananian 1.1.2.1 * </pre> 41 cananian 1.1.2.1 * 42 cananian 1.1.2.1 * <br><b>Array instance layout:</b> 43 cananian 1.1.2.1 * <pre> 44 cananian 1.1.2.1 * -12 length 45 cananian 1.1.2.1 * -8 hashcode 46 cananian 1.1.2.1 * -4 clazz ptr 47 cananian 1.1.2.1 * 0 array element 0 48 cananian 1.1.2.1 * 4 array element 1 49 cananian 1.1.2.1 * ... 50 cananian 1.1.2.1 * 4*(n-1) array element n-1 51 cananian 1.1.2.1 * </pre> 52 cananian 1.1.2.1 * 53 cananian 1.1.2.1 * <br><b>Static class layout:</b> 54 cananian 1.1.2.1 * <pre> 55 cananian 1.1.2.1 * -4*(n+1) interface method n-1 56 cananian 1.1.2.1 * ... 57 cananian 1.1.2.1 * -16 interface method 1 58 cananian 1.1.2.1 * -12 interface method 0 59 cananian 1.1.2.1 * -8 component type (NULL if not array) 60 cananian 1.1.2.1 * -4 interface list ptr 61 cananian 1.1.2.1 * 0 display 0 62 cananian 1.1.2.1 * 4 display 1 63 cananian 1.1.2.1 * ... 64 cananian 1.1.2.1 * 4*MAXcd display max class depth 65 cananian 1.1.2.1 * 4*MAXcd+4 class method 0 66 cananian 1.1.2.1 * 4*MAXcd+8 class method 1 67 cananian 1.1.2.1 * ... 68 cananian 1.1.2.1 * 4*MAXcd+4*(n-1) class method n-1 69 cananian 1.1.2.1 * </pre> 70 cananian 1.1.2.1 * 71 cananian 1.1.2.1 * <br><i>However</i>, this layout is most definitely subject to change, 72 cananian 1.1.2.1 * so no implementation should rely on it. 73 cananian 1.1.2.1 * 74 cananian 1.1.2.1 * 75 cananian 1.1.2.1 * @author Duncan Bryce <duncan@lcs.mit.edu> 76 cananian 1.6 * @version $Id: OffsetMap32.java,v 1.6 2004/02/08 03:21:34 cananian Exp $ 77 cananian 1.1.2.1 */ 78 cananian 1.1.2.1 class OffsetMap32 extends OffsetMap 79 cananian 1.1.2.1 { 80 cananian 1.1.2.1 public static final int WORDSIZE = 4; 81 cananian 1.1.2.1 82 cananian 1.1.2.1 private ClassDepthMap cdm; 83 cananian 1.1.2.1 private FieldMap fm; 84 cananian 1.1.2.1 private HClassInfo hci; 85 cananian 1.1.2.1 private InterfaceMethodMap imm; 86 cananian 1.1.2.1 private MethodMap cmm; 87 cananian 1.1.2.1 88 cananian 1.1.2.1 private Map fields = new HashMap(); 89 cananian 1.1.2.1 90 cananian 1.1.2.1 /** Class constructor */ 91 cananian 1.1.2.1 public OffsetMap32(ClassHierarchy ch) { 92 cananian 1.3.2.1 assert ch!=null : "Class hierarchy must be non-null"; 93 cananian 1.1.2.1 94 cananian 1.1.2.1 this.hci = new HClassInfo(); 95 cananian 1.1.2.1 96 cananian 1.1.2.1 int _maxDepth = 0; 97 cananian 1.6 for (Object hcO : ch.classes()){ 98 cananian 1.6 HClass hc = (HClass) hcO; 99 cananian 1.1.2.1 int depth = hci.depth(hc); 100 cananian 1.1.2.1 _maxDepth = (depth>_maxDepth) ? depth : _maxDepth; 101 cananian 1.1.2.1 } 102 cananian 1.1.2.1 final int maxDepth = _maxDepth; 103 cananian 1.1.2.1 104 cananian 1.1.2.1 this.cdm = new ClassDepthMap() { 105 cananian 1.1.2.1 public int classDepth(HClass hc) { return hci.depth(hc); } 106 cananian 1.1.2.1 public int maxDepth() { return maxDepth; } 107 cananian 1.1.2.1 }; 108 cananian 1.1.2.1 this.fm = new FieldMap() { 109 cananian 1.1.2.1 public int fieldOrder(HField hf) {return hci.getFieldOffset(hf);} 110 cananian 1.1.2.1 }; 111 cananian 1.1.2.1 this.imm = new InterfaceMethodMap 112 cananian 1.5 (new net.cscott.jutil.IteratorEnumerator(ch.classes().iterator())); 113 cananian 1.1.2.1 this.cmm = new MethodMap() { 114 cananian 1.1.2.1 public int methodOrder(HMethod hm){return hci.getMethodOffset(hm);} 115 cananian 1.1.2.1 }; 116 cananian 1.1.2.1 } 117 cananian 1.1.2.1 118 cananian 1.1.2.1 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 119 cananian 1.1.2.1 * * 120 cananian 1.1.2.1 * Implementation of offset methods * 121 cananian 1.1.2.1 * * 122 cananian 1.1.2.1 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ 123 cananian 1.1.2.1 124 cananian 1.1.2.1 /** Returns the offset of the class pointer */ 125 cananian 1.1.2.1 public int clazzPtrOffset(HClass hc) { 126 cananian 1.3.2.1 assert !hc.isPrimitive(); 127 cananian 1.1.2.1 return -1 * WORDSIZE; 128 cananian 1.1.2.1 } 129 cananian 1.1.2.1 130 cananian 1.1.2.1 /** If hc is an array type, returns the offset of its component 131 cananian 1.1.2.1 * type's class pointer */ 132 cananian 1.1.2.1 public int componentTypeOffset(HClass hc) { 133 cananian 1.1.2.1 return -1 * WORDSIZE; 134 cananian 1.1.2.1 } 135 cananian 1.1.2.1 136 cananian 1.1.2.1 /** Returns the size of the display information */ 137 cananian 1.1.2.1 public int displaySize() { 138 cananian 1.1.2.1 return cdm.maxDepth() * WORDSIZE; 139 cananian 1.1.2.1 } 140 cananian 1.1.2.1 141 cananian 1.1.2.1 /** Returns the offset of the first array element if hc is an array 142 cananian 1.1.2.1 * type, otherwise generates an assertion failure */ 143 cananian 1.1.2.1 public int elementsOffset(HClass hc) { 144 cananian 1.3.2.1 assert hc.isArray(); 145 cananian 1.1.2.1 return 1 * WORDSIZE; 146 cananian 1.1.2.1 } 147 cananian 1.1.2.1 148 cananian 1.1.2.1 /** Returns the offset of the first field in an object of the 149 cananian 1.1.2.1 * specified type */ 150 cananian 1.1.2.1 public int fieldsOffset(HClass hc) { 151 cananian 1.3.2.1 assert (!hc.isPrimitive()) && 152 cananian 1.1.2.1 (!hc.isArray()) && 153 cananian 1.3.2.1 (!hc.isInterface()); 154 cananian 1.1.2.1 return 0; 155 cananian 1.1.2.1 } 156 cananian 1.1.2.1 157 cananian 1.1.2.1 /** Returns the offset of the hashcode of the specified object */ 158 cananian 1.1.2.1 public int hashCodeOffset(HClass hc) { 159 cananian 1.3.2.1 assert !hc.isPrimitive(); 160 cananian 1.1.2.1 return -2 * WORDSIZE; 161 cananian 1.1.2.1 } 162 cananian 1.1.2.1 163 cananian 1.1.2.1 /** If hc is a class type, or an interface, returns the offset from 164 cananian 1.1.2.1 * the class pointer of the pointer to implemented interfaces */ 165 cananian 1.1.2.1 public int interfaceListOffset(HClass hc) { 166 cananian 1.3.2.1 assert !hc.isPrimitive(); 167 cananian 1.1.2.1 return -2 * WORDSIZE; 168 cananian 1.1.2.1 } 169 cananian 1.1.2.1 170 cananian 1.1.2.1 /** If hc is an array type, returns the offset of its length field */ 171 cananian 1.1.2.1 public int lengthOffset(HClass hc) { 172 cananian 1.3.2.1 assert hc.isArray() || hc.isInterface(); 173 cananian 1.1.2.1 return 0; 174 cananian 1.1.2.1 } 175 cananian 1.1.2.1 176 cananian 1.1.2.1 /** Returns the offset from the class pointer of this class's pointer 177 cananian 1.1.2.1 * in the display */ 178 cananian 1.1.2.1 public int offset(HClass hc) { 179 cananian 1.3.2.1 assert !hc.isPrimitive() && !hc.isInterface(); 180 cananian 1.1.2.1 return cdm.classDepth(hc) * WORDSIZE; 181 cananian 1.1.2.1 } 182 cananian 1.1.2.1 183 cananian 1.1.2.1 private interface ComparableHField extends Comparable { 184 cananian 1.1.2.1 public HField getField(); 185 cananian 1.1.2.1 } 186 cananian 1.1.2.1 187 cananian 1.1.2.1 /** Returns the offset from the object reference of the specified 188 cananian 1.1.2.1 * non-static field */ 189 cananian 1.1.2.1 public int offset(HField hf) { 190 cananian 1.3.2.1 assert !hf.isStatic(); 191 cananian 1.1.2.1 192 cananian 1.1.2.1 final HClass hc; 193 cananian 1.1.2.1 Iterator allFields; 194 cananian 1.1.2.1 List orderedFields; 195 cananian 1.1.2.1 int offset = 0; 196 cananian 1.1.2.1 197 cananian 1.1.2.1 if (!this.fields.containsKey(hf)) { 198 cananian 1.1.2.1 hc = hf.getDeclaringClass(); 199 cananian 1.1.2.1 allFields = new Iterator() { 200 cananian 1.1.2.1 private HClass cls = hc; 201 cananian 1.1.2.1 private HField[] fields = hc.getDeclaredFields(); 202 cananian 1.1.2.1 private int index = 0; 203 cananian 1.1.2.1 public void remove() 204 cananian 1.1.2.1 { throw new UnsupportedOperationException(); } 205 cananian 1.1.2.1 public boolean hasNext() { 206 cananian 1.1.2.1 if (index<fields.length) return true; 207 cananian 1.1.2.1 else { 208 cananian 1.1.2.1 if (cls==null) return false; 209 cananian 1.1.2.1 for (HClass sCls=cls.getSuperclass(); sCls!=null; 210 cananian 1.1.2.1 sCls=sCls.getSuperclass()) 211 cananian 1.1.2.1 if (sCls.getDeclaredFields().length != 0) 212 cananian 1.1.2.1 return true; 213 cananian 1.1.2.1 return false; 214 cananian 1.1.2.1 } 215 cananian 1.1.2.1 } 216 cananian 1.1.2.1 public Object next() { 217 cananian 1.1.2.1 if (index<fields.length) { 218 cananian 1.1.2.1 return fields[index++]; 219 cananian 1.1.2.1 } 220 cananian 1.1.2.1 else { 221 cananian 1.1.2.1 cls = cls.getSuperclass(); 222 cananian 1.1.2.1 if (cls==null) throw new NoSuchElementException(); 223 cananian 1.1.2.1 else { index=0; fields = cls.getDeclaredFields(); 224 cananian 1.1.2.1 return next(); } 225 cananian 1.1.2.1 } 226 cananian 1.1.2.1 } 227 cananian 1.1.2.1 }; 228 cananian 1.1.2.1 orderedFields = new ArrayList(); 229 cananian 1.1.2.1 for (Iterator i=allFields; i.hasNext();) { 230 cananian 1.1.2.1 final HField nextField = (HField)i.next(); 231 cananian 1.1.2.1 if (!nextField.isStatic()) 232 cananian 1.1.2.1 orderedFields.add(new ComparableHField() { 233 cananian 1.1.2.1 public HField getField() { return nextField; } 234 cananian 1.1.2.1 public int compareTo(Object o) { 235 cananian 1.1.2.1 HField hfo = ((ComparableHField)o).getField(); 236 cananian 1.1.2.1 int thisOrder = fm.fieldOrder(nextField); 237 cananian 1.1.2.1 int hfOrder = fm.fieldOrder(hfo); 238 cananian 1.1.2.1 return (thisOrder>hfOrder) ? 1 : 239 cananian 1.1.2.1 (thisOrder==hfOrder) ? 0 : -1; 240 cananian 1.1.2.1 } 241 cananian 1.1.2.1 }); 242 cananian 1.1.2.1 } 243 cananian 1.1.2.1 Collections.sort(orderedFields); 244 cananian 1.1.2.1 for (Iterator i=orderedFields.iterator(); i.hasNext();) { 245 cananian 1.1.2.1 HField hfield = ((ComparableHField)i.next()).getField(); 246 cananian 1.1.2.1 HClass type = hfield.getType(); 247 cananian 1.1.2.1 this.fields.put(hfield, new Integer(offset)); 248 cananian 1.1.2.1 // No inlining 249 cananian 1.1.2.1 offset += ((type==HClass.Long)||(type==HClass.Double)) ? 8 : 4; 250 cananian 1.1.2.1 } 251 cananian 1.1.2.1 } 252 cananian 1.1.2.1 253 cananian 1.1.2.1 return ((Integer)this.fields.get(hf)).intValue(); 254 cananian 1.1.2.1 } 255 cananian 1.1.2.1 256 cananian 1.1.2.1 257 cananian 1.1.2.1 /** Returns the offset from the class pointer of the specified 258 cananian 1.1.2.1 * non-static method */ 259 cananian 1.1.2.1 public int offset(HMethod hm) { 260 cananian 1.3.2.1 assert hm != null && !hm.isStatic(); 261 cananian 1.1.2.1 HClass hc = hm.getDeclaringClass(); 262 cananian 1.1.2.1 if (hc.isInterface()) 263 cananian 1.1.2.1 return -WORDSIZE * (imm.methodOrder(hm)*WORDSIZE) - (2*WORDSIZE); 264 cananian 1.1.2.1 else 265 cananian 1.1.2.1 return (cmm.methodOrder(hm)*WORDSIZE) + displaySize(); 266 cananian 1.1.2.1 } 267 cananian 1.1.2.1 268 cananian 1.1.2.1 /** Returns the size of the specified class */ 269 cananian 1.1.2.1 public int size(HClass hc) { 270 cananian 1.3.2.1 assert !hc.isInterface(); 271 cananian 1.1.2.1 272 cananian 1.1.2.1 if (hc.isPrimitive()) { 273 cananian 1.1.2.1 return hc==HClass.Long || hc==HClass.Double ? 8 : 4; 274 cananian 1.1.2.1 } 275 cananian 1.1.2.1 else if (hc.isArray()) { 276 cananian 1.1.2.1 // The size of an array instance is determined by the number of 277 cananian 1.1.2.1 // elements it has, and therefore cannot be determined by this 278 cananian 1.1.2.1 // method. 279 cananian 1.3.2.1 assert false : "Size of array does not depend on its class!"; 280 cananian 1.1.2.1 return -1; 281 cananian 1.1.2.1 } 282 cananian 1.1.2.1 else { 283 cananian 1.1.2.1 int size = 2 * WORDSIZE; // Includes hashcode & classptr 284 cananian 1.1.2.1 HField[] hf = hc.getDeclaredFields(); 285 cananian 1.1.2.1 for (int i=0; i<hf.length; i++) { 286 cananian 1.1.2.1 HClass type = hf[i].getType(); 287 cananian 1.1.2.1 size += hf[i].isStatic() ? 0 : 288 cananian 1.1.2.1 (type==HClass.Long || type==HClass.Double) ? 8 : 4; 289 cananian 1.1.2.1 } 290 cananian 1.1.2.1 return size; 291 cananian 1.1.2.1 } 292 cananian 1.1.2.1 } 293 cananian 1.1.2.1 294 cananian 1.1.2.1 public int wordsize() { return WORDSIZE; } 295 cananian 1.1.2.1 296 cananian 1.1.2.1 // stub for old FieldMap interface 297 cananian 1.1.2.1 abstract class FieldMap { 298 cananian 1.1.2.1 public abstract int fieldOrder(HField hf); 299 cananian 1.1.2.1 } 300 cananian 1.2 }