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     }