1 cananian 1.1.4.1 // DataClaz.java, created Mon Oct 11 12:01:55 1999 by cananian 2 cananian 1.1.4.1 // Copyright (C) 1999 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.1.4.1 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1.4.1 package harpoon.Backend.Runtime1; 5 cananian 1.1.4.1 6 cananian 1.1.4.1 import harpoon.Analysis.ClassHierarchy; 7 cananian 1.1.4.1 import harpoon.Backend.Generic.Frame; 8 kkz 1.1.4.10 import harpoon.Backend.Maps.FieldMap; 9 cananian 1.1.4.1 import harpoon.Backend.Maps.MethodMap; 10 cananian 1.1.4.1 import harpoon.Backend.Maps.NameMap; 11 cananian 1.1.4.1 import harpoon.ClassFile.HClass; 12 cananian 1.1.4.1 import harpoon.ClassFile.HConstructor; 13 cananian 1.1.4.1 import harpoon.ClassFile.HDataElement; 14 kkz 1.1.4.10 import harpoon.ClassFile.HField; 15 cananian 1.1.4.12 import harpoon.ClassFile.HInitializer; 16 cananian 1.1.4.1 import harpoon.ClassFile.HMethod; 17 cananian 1.1.4.1 import harpoon.IR.Tree.Stm; 18 cananian 1.1.4.4 import harpoon.IR.Tree.ALIGN; 19 cananian 1.1.4.1 import harpoon.IR.Tree.CONST; 20 cananian 1.1.4.8 import harpoon.IR.Tree.DATUM; 21 cananian 1.1.4.1 import harpoon.IR.Tree.LABEL; 22 cananian 1.1.4.1 import harpoon.IR.Tree.NAME; 23 cananian 1.1.4.1 import harpoon.IR.Tree.SEGMENT; 24 cananian 1.1.4.1 import harpoon.Util.HClassUtil; 25 cananian 1.1.4.1 import harpoon.Util.Util; 26 cananian 1.1.4.1 27 cananian 1.1.4.1 import java.lang.reflect.Modifier; 28 cananian 1.1.4.1 import java.util.ArrayList; 29 cananian 1.1.4.1 import java.util.Arrays; 30 cananian 1.1.4.1 import java.util.Collections; 31 cananian 1.1.4.1 import java.util.Comparator; 32 cananian 1.1.4.1 import java.util.HashSet; 33 cananian 1.1.4.1 import java.util.List; 34 cananian 1.1.4.1 import java.util.ListIterator; 35 cananian 1.1.4.1 import java.util.Iterator; 36 cananian 1.1.4.1 import java.util.Set; 37 cananian 1.1.4.1 /** 38 cananian 1.1.4.1 * <code>DataClaz</code> lays out the claz tables, including the 39 cananian 1.1.4.1 * interface and class method dispatch tables. 40 cananian 1.1.4.1 * 41 cananian 1.1.4.1 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 42 cananian 1.7 * @version $Id: DataClaz.java,v 1.7 2004/02/08 05:09:43 cananian Exp $ 43 cananian 1.1.4.1 */ 44 cananian 1.1.4.1 public class DataClaz extends Data { 45 cananian 1.1.4.1 final TreeBuilder m_tb; 46 cananian 1.1.4.1 final NameMap m_nm; 47 cananian 1.1.4.1 48 cananian 1.1.4.1 /** Creates a <code>ClassData</code>. */ 49 cananian 1.3.2.3 public DataClaz(Frame f, HClass hc, ClassHierarchy ch, 50 cananian 1.3.2.3 Runtime.ExtraClazInfo eci) { 51 cananian 1.1.4.1 super("class-data", hc, f); 52 cananian 1.1.4.27 this.m_nm = f.getRuntime().getNameMap(); 53 cananian 1.1.4.27 this.m_tb = (TreeBuilder) f.getRuntime().getTreeBuilder(); 54 kkz 1.1.4.26 this.BITS_IN_GC_BITMAP = 8 * m_tb.POINTER_SIZE; 55 cananian 1.3.2.3 this.root = build(f, hc, ch, eci); 56 cananian 1.1.4.1 } 57 cananian 1.1.4.1 58 cananian 1.3.2.3 private HDataElement build(Frame f, HClass hc, ClassHierarchy ch, 59 cananian 1.3.2.3 Runtime.ExtraClazInfo eci) { 60 cananian 1.3.2.2 List<Stm> stmlist = new ArrayList<Stm>(); 61 cananian 1.1.4.1 // write the appropriate segment header 62 cananian 1.1.4.1 stmlist.add(new SEGMENT(tf, null, SEGMENT.CLASS)); 63 cananian 1.6 // align things on pointer-size boundary. 64 cananian 1.6 stmlist.add(new ALIGN(tf, null, f.pointersAreLong() ? 8 : 4)); 65 cananian 1.1.4.1 // first comes the interface method table. 66 cananian 1.1.4.1 if (!hc.isInterface()) { 67 cananian 1.1.4.1 Stm s = interfaceMethods(hc, ch); 68 cananian 1.1.4.1 if (s!=null) stmlist.add(s); 69 cananian 1.1.4.1 } 70 cananian 1.1.4.1 // this is where the class pointer points. 71 cananian 1.1.4.1 stmlist.add(new LABEL(tf, null, m_nm.label(hc), true)); 72 cananian 1.1.4.3 // class info points at a class object for this class 73 cananian 1.1.4.3 // (which is generated in DataReflection1) 74 cananian 1.1.4.8 stmlist.add(_DATUM(m_nm.label(hc, "classobj"))); 75 cananian 1.1.4.1 // component type pointer. 76 cananian 1.1.4.1 if (hc.isArray()) 77 cananian 1.1.4.8 stmlist.add(_DATUM(m_nm.label(hc.getComponentType()))); 78 cananian 1.1.4.1 else 79 cananian 1.1.4.8 stmlist.add(_DATUM(new CONST(tf, null))); 80 cananian 1.1.4.1 // the interface list is generated elsewhere 81 cananian 1.1.4.8 stmlist.add(_DATUM(m_nm.label(hc, "interfaces"))); 82 cananian 1.1.4.5 // object size. 83 kkz 1.1.4.20 int size = 84 kkz 1.1.4.20 (!hc.isPrimitive()) ? 85 kkz 1.1.4.20 (m_tb.objectSize(hc) + m_tb.OBJECT_HEADER_SIZE) : 86 kkz 1.1.4.20 (hc==HClass.Double||hc==HClass.Long) ? m_tb.LONG_WORD_SIZE : 87 kkz 1.1.4.20 (hc==HClass.Int||hc==HClass.Float) ? m_tb.WORD_SIZE : 88 kkz 1.1.4.20 (hc==HClass.Short||hc==HClass.Char) ? 2 : 1; 89 cananian 1.1.4.8 stmlist.add(_DATUM(new CONST(tf, null, size))); 90 cananian 1.5 // class depth. 91 cananian 1.5 int depth = m_tb.cdm.classDepth(hc); 92 cananian 1.5 if (HClassUtil.baseClass(hc).isInterface()) depth=0;// mark interface[] 93 cananian 1.5 stmlist.add(_DATUM(new CONST(tf, null, m_tb.POINTER_SIZE * depth))); 94 kkz 1.1.4.10 // bitmap for gc or pointer to bitmap 95 kkz 1.1.4.29 stmlist.add(gc(f, hc)); 96 cananian 1.3.2.3 // extra claz info (defined by runtime's subclass, if any) 97 cananian 1.3.2.3 if (eci!=null) { 98 cananian 1.3.2.3 Stm s = eci.emit(tf, f, hc, ch); 99 cananian 1.3.2.3 if (s!=null) stmlist.add(s); 100 cananian 1.3.2.3 } 101 cananian 1.1.4.1 // class display 102 cananian 1.1.4.1 stmlist.add(display(hc, ch)); 103 cananian 1.1.4.1 // now class method table. 104 cananian 1.1.4.1 if (!hc.isInterface()) { 105 cananian 1.1.4.1 Stm s = classMethods(hc, ch); 106 cananian 1.1.4.1 if (s!=null) stmlist.add(s); 107 cananian 1.1.4.1 } 108 cananian 1.1.4.1 return (HDataElement) Stm.toStm(stmlist); 109 kkz 1.1.4.10 } 110 kkz 1.1.4.10 111 kkz 1.1.4.26 // the number of bits in the in-line gc bitmap is platform-dependent 112 kkz 1.1.4.26 final int BITS_IN_GC_BITMAP; 113 kkz 1.1.4.25 114 kkz 1.1.4.10 /** Make gc bitmap or pointer to bitmap. */ 115 kkz 1.1.4.29 private Stm gc(Frame f, HClass hc) { 116 kkz 1.1.4.28 // use object size (w/ header) to determine how many bits we need (round up) 117 kkz 1.1.4.28 int bitsNeeded = (m_tb.objectSize(hc) + m_tb.OBJECT_HEADER_SIZE + m_tb.POINTER_SIZE - 1)/m_tb.POINTER_SIZE; 118 kkz 1.1.4.26 // for arrays we keep an extra bit for the array elements 119 kkz 1.1.4.26 if (hc.isArray()) 120 kkz 1.1.4.26 bitsNeeded++; 121 kkz 1.1.4.26 if (bitsNeeded > BITS_IN_GC_BITMAP) { // auxiliary table for large objects 122 kkz 1.1.4.29 return gcaux(f, hc, bitsNeeded); 123 kkz 1.1.4.18 } else { // in-line bitmap for small objects 124 cananian 1.3.2.2 final List<HField> fields = m_tb.cfm.fieldList(hc); 125 kkz 1.1.4.25 long bitmap = 0; 126 cananian 1.3.2.2 for (Iterator<HField> it=fields.iterator(); it.hasNext(); ) { 127 cananian 1.3.2.2 final HField hf = it.next(); 128 kkz 1.1.4.18 final HClass type = hf.getType(); 129 kkz 1.1.4.28 final int fieldOffset = m_tb.cfm.fieldOffset(hf) + m_tb.OBJECT_HEADER_SIZE; 130 kkz 1.1.4.18 // non-aligned objects should never be pointers 131 kkz 1.1.4.18 if (fieldOffset%m_tb.POINTER_SIZE != 0) { 132 cananian 1.3.2.1 assert type.isPrimitive(); 133 kkz 1.1.4.10 continue; 134 kkz 1.1.4.10 } 135 kkz 1.1.4.10 if (!type.isPrimitive()) { 136 kkz 1.1.4.18 final int i = fieldOffset/m_tb.POINTER_SIZE; 137 cananian 1.3.2.1 assert i >= 0 && i < BITS_IN_GC_BITMAP; 138 kkz 1.1.4.18 bitmap |= (1 << i); 139 kkz 1.1.4.10 } 140 kkz 1.1.4.10 } 141 kkz 1.1.4.26 // for arrays, we use the bit at the end of the bitmap 142 kkz 1.1.4.26 // for the array elements so the GC doesn't have to look 143 kkz 1.1.4.26 // into the component claz 144 kkz 1.1.4.26 if (hc.isArray() && !hc.getComponentType().isPrimitive()) 145 kkz 1.1.4.26 bitmap |= (1 << (bitsNeeded - 1)); 146 kkz 1.1.4.26 // write out in-line bitmap 147 cananian 1.3.2.2 final List<Stm> stmlist = new ArrayList<Stm>(); 148 kkz 1.1.4.18 if (f.pointersAreLong()) { 149 kkz 1.1.4.10 stmlist.add(_DATUM(new CONST(tf, null, bitmap))); 150 kkz 1.1.4.18 } else { 151 kkz 1.1.4.10 stmlist.add(_DATUM(new CONST(tf, null, (int)bitmap))); 152 kkz 1.1.4.18 } 153 kkz 1.1.4.10 return Stm.toStm(stmlist); 154 kkz 1.1.4.10 } 155 kkz 1.1.4.13 } 156 kkz 1.1.4.13 // Make auxiliary gc bitmap 157 kkz 1.1.4.29 private Stm gcaux(Frame f, HClass hc, int bitsNeeded) { 158 kkz 1.1.4.29 // calculate how many bitmaps we need 159 kkz 1.1.4.29 final int bitmapsNeeded = (bitsNeeded + BITS_IN_GC_BITMAP - 1)/BITS_IN_GC_BITMAP; 160 kkz 1.1.4.29 // create an array containing the needed bitmaps 161 kkz 1.1.4.29 final long bitmaps[] = new long[bitmapsNeeded]; 162 kkz 1.1.4.29 // iterate through the fields 163 cananian 1.3.2.2 final List<HField> fields = m_tb.cfm.fieldList(hc); 164 cananian 1.3.2.2 for (Iterator<HField> it = fields.iterator(); it.hasNext(); ) { 165 cananian 1.3.2.2 final HField hf = it.next(); 166 kkz 1.1.4.29 final HClass type = hf.getType(); 167 kkz 1.1.4.10 if (!type.isPrimitive()) { 168 kkz 1.1.4.29 final int fo = m_tb.cfm.fieldOffset(hf) + m_tb.OBJECT_HEADER_SIZE; 169 kkz 1.1.4.29 // non-primitive fields contain pointers and should be aligned 170 cananian 1.3.2.1 assert fo%m_tb.POINTER_SIZE == 0; 171 kkz 1.1.4.29 // calculate the bit position corresponding to this field 172 kkz 1.1.4.29 final int bp = fo/m_tb.POINTER_SIZE; 173 cananian 1.3.2.1 assert bp < bitsNeeded; 174 kkz 1.1.4.29 bitmaps[bp/BITS_IN_GC_BITMAP] |= (1 << (bp%BITS_IN_GC_BITMAP)); 175 kkz 1.1.4.10 } 176 kkz 1.1.4.10 } 177 kkz 1.1.4.29 // handle arrays 178 kkz 1.1.4.29 if (hc.isArray() && !hc.getComponentType().isPrimitive()) 179 kkz 1.1.4.29 bitmaps[bitmapsNeeded-1] |= (1 << ((bitsNeeded - 1)%BITS_IN_GC_BITMAP)); 180 kkz 1.1.4.29 // check whether there are any pointers 181 kkz 1.1.4.29 boolean atomic = true; 182 kkz 1.1.4.29 for (int i = 0; i < bitmapsNeeded; i++) { 183 kkz 1.1.4.29 if (bitmaps[i] != 0) { 184 kkz 1.1.4.29 atomic = false; 185 kkz 1.1.4.29 break; 186 kkz 1.1.4.18 } 187 kkz 1.1.4.28 } 188 cananian 1.3.2.2 final List<Stm> stmlist = new ArrayList<Stm>(); 189 kkz 1.1.4.28 if (atomic) { 190 kkz 1.1.4.29 // write NULL to the in-line bitmap to indicate no pointers 191 kkz 1.1.4.28 if (f.pointersAreLong()) 192 kkz 1.1.4.28 stmlist.add(_DATUM(new CONST(tf, null, (long)0))); 193 kkz 1.1.4.28 else 194 kkz 1.1.4.28 stmlist.add(_DATUM(new CONST(tf, null, (int)0))); 195 kkz 1.1.4.29 } else { 196 kkz 1.1.4.29 // large object, encoded in auxiliary table 197 kkz 1.1.4.29 stmlist.add(_DATUM(m_nm.label(hc, "gc_aux"))); 198 kkz 1.1.4.29 // switch to GC segment 199 kkz 1.1.4.29 stmlist.add(new SEGMENT(tf, null, SEGMENT.GC)); 200 kkz 1.1.4.29 // align things on word boundary. 201 cananian 1.6 stmlist.add(new ALIGN(tf, null, f.pointersAreLong() ? 8 : 4)); 202 kkz 1.1.4.29 stmlist.add(new LABEL(tf, null, m_nm.label(hc, "gc_aux"), true)); 203 kkz 1.1.4.29 // write out the bitmaps 204 kkz 1.1.4.29 if (f.pointersAreLong()) { 205 kkz 1.1.4.29 for (int i = 0; i < bitmapsNeeded; i++) 206 kkz 1.1.4.29 stmlist.add(_DATUM(new CONST(tf, null, bitmaps[i]))); 207 kkz 1.1.4.29 } else { 208 kkz 1.1.4.29 for (int i = 0; i < bitmapsNeeded; i++) 209 kkz 1.1.4.29 stmlist.add(_DATUM(new CONST(tf, null, (int)bitmaps[i]))); 210 kkz 1.1.4.29 } 211 kkz 1.1.4.29 // switch back to CLASS segment 212 kkz 1.1.4.29 stmlist.add(new SEGMENT(tf, null, SEGMENT.CLASS)); 213 kkz 1.1.4.29 // align things on word boundary. 214 cananian 1.6 stmlist.add(new ALIGN(tf, null, f.pointersAreLong() ? 8 : 4)); 215 kkz 1.1.4.18 } 216 kkz 1.1.4.10 return Stm.toStm(stmlist); 217 cananian 1.1.4.1 } 218 cananian 1.1.4.1 219 cananian 1.1.4.1 /** Make class display table. */ 220 cananian 1.1.4.1 private Stm display(HClass hc, ClassHierarchy ch) { 221 cananian 1.3.2.2 List<HClass> clslist = new ArrayList<HClass>(); 222 cananian 1.1.4.1 // we're going to build the list top-down and then reverse it. 223 cananian 1.1.4.1 if (hc.isArray()) { // arrays are special. 224 cananian 1.1.4.1 HClass base = HClassUtil.baseClass(hc); 225 cananian 1.1.4.1 int dims = HClassUtil.dims(hc); 226 cananian 1.1.4.24 // (interface arrays inherit from Object[]..[], but 227 cananian 1.1.4.24 // the interface array itself shouldn't appear in the display) 228 cananian 1.1.4.24 if (base.isInterface()) base=linker.forName("java.lang.Object"); 229 cananian 1.1.4.1 230 cananian 1.1.4.1 // first step down the base class inheritance hierarchy. 231 cananian 1.1.4.1 for (HClass hcp = base; hcp!=null; hcp=hcp.getSuperclass()) 232 cananian 1.1.4.15 clslist.add(HClassUtil.arrayClass(linker, hcp, dims)); 233 cananian 1.1.4.1 // now down the Object array hierarchy. 234 cananian 1.1.4.9 HClass hcO = linker.forName("java.lang.Object"); 235 cananian 1.1.4.1 for (dims--; dims>=0; dims--) 236 cananian 1.1.4.15 clslist.add(HClassUtil.arrayClass(linker, hcO, dims)); 237 cananian 1.1.4.1 // done. 238 cananian 1.1.4.22 } else if (!hc.isInterface() && !hc.isPrimitive()) { 239 cananian 1.1.4.22 // step down the inheritance hierarchy. 240 cananian 1.1.4.1 for (HClass hcp = hc; hcp!=null; hcp=hcp.getSuperclass()) 241 cananian 1.1.4.1 clslist.add(hcp); 242 cananian 1.1.4.1 } 243 cananian 1.1.4.1 // now reverse list. 244 cananian 1.1.4.1 Collections.reverse(clslist); 245 cananian 1.1.4.1 // okay, root should always be java.lang.Object. 246 cananian 1.3.2.1 assert hc.isInterface() || hc.isPrimitive() || 247 cananian 1.3.2.1 clslist.get(0)==linker.forName("java.lang.Object"); 248 cananian 1.1.4.1 // make statements. 249 cananian 1.3.2.2 List<Stm> stmlist = new ArrayList<Stm>(m_tb.cdm.maxDepth()+1); 250 cananian 1.3.2.2 for (Iterator<HClass> it=clslist.iterator(); it.hasNext(); ) 251 cananian 1.3.2.2 stmlist.add(_DATUM(m_nm.label(it.next()))); 252 cananian 1.1.4.7 while (stmlist.size() <= m_tb.cdm.maxDepth()) 253 cananian 1.1.4.8 stmlist.add(_DATUM(new CONST(tf, null))); // pad with nulls. 254 cananian 1.3.2.1 assert stmlist.size() == m_tb.cdm.maxDepth()+1; 255 cananian 1.1.4.1 return Stm.toStm(stmlist); 256 cananian 1.1.4.1 } 257 cananian 1.1.4.1 /** Make class methods table. */ 258 cananian 1.1.4.1 private Stm classMethods(HClass hc, ClassHierarchy ch) { 259 cananian 1.1.4.1 // collect all the methods. 260 cananian 1.3.2.2 List<HMethod> methods = 261 cananian 1.3.2.2 new ArrayList<HMethod>(Arrays.asList(hc.getMethods())); 262 cananian 1.1.4.1 // weed out non-virtual methods. 263 cananian 1.3.2.2 for (Iterator<HMethod> it=methods.iterator(); it.hasNext(); ) { 264 cananian 1.3.2.2 HMethod hm = it.next(); 265 cananian 1.3.2.4 assert !hm.isInterfaceMethod() : 266 cananian 1.3.2.4 "getMethods() on "+hc+" returned an *interface* method: "+hm+ 267 cananian 1.3.2.4 " / method list: "+methods; 268 cananian 1.1.4.1 if (hm.isStatic() || hm instanceof HConstructor || 269 cananian 1.1.4.1 Modifier.isPrivate(hm.getModifiers())) 270 cananian 1.1.4.1 it.remove(); 271 cananian 1.1.4.1 } 272 cananian 1.1.4.1 // sort the methods using class method map. 273 cananian 1.1.4.1 final MethodMap cmm = m_tb.cmm; 274 cananian 1.3.2.2 Collections.sort(methods, new Comparator<HMethod>() { 275 cananian 1.3.2.2 public int compare(HMethod hm1, HMethod hm2) { 276 cananian 1.1.4.1 int i1 = cmm.methodOrder(hm1); 277 cananian 1.1.4.1 int i2 = cmm.methodOrder(hm2); 278 cananian 1.1.4.1 return i1 - i2; 279 cananian 1.1.4.1 } 280 cananian 1.1.4.1 }); 281 cananian 1.1.4.1 // make stms. 282 cananian 1.3.2.2 List<Stm> stmlist = new ArrayList<Stm>(methods.size()); 283 cananian 1.3.2.2 Set<HMethod> callable = ch.callableMethods(); 284 cananian 1.1.4.1 int order=0; 285 cananian 1.3.2.2 for (Iterator<HMethod> it=methods.iterator(); it.hasNext(); order++) { 286 cananian 1.3.2.2 HMethod hm = it.next(); 287 cananian 1.3.2.1 assert cmm.methodOrder(hm)==order; // should be no gaps. 288 cananian 1.1.4.14 if (callable.contains(hm) && 289 cananian 1.1.4.14 !Modifier.isAbstract(hm.getModifiers())) 290 cananian 1.1.4.8 stmlist.add(_DATUM(m_nm.label(hm))); 291 cananian 1.1.4.1 else 292 cananian 1.1.4.8 stmlist.add(_DATUM(new CONST(tf, null))); // null pointer 293 cananian 1.1.4.1 } 294 cananian 1.1.4.1 return Stm.toStm(stmlist); 295 cananian 1.1.4.1 } 296 cananian 1.1.4.17 /* XXX UGLY UGLY: some bug in the relinker makes methods comparisons 297 cananian 1.1.4.17 * bogus sometimes. This is a hack to work around the problem so that 298 cananian 1.1.4.17 * we can benchmark properly: we should really fix the relinker. 299 cananian 1.1.4.17 * Even the property we're using here is stolen from ClassFile.Loader, 300 cananian 1.1.4.17 * where it specifies that Linkers should be re-serialized as Relinkers, 301 cananian 1.1.4.17 * another hack designed to avoid needing to run Alex's analysis using 302 cananian 1.1.4.17 * a (historically buggy) relinker. CSA. */ 303 cananian 1.1.4.17 private static final boolean relinkerHack = 304 cananian 1.1.4.17 System.getProperty("harpoon.relinker.hack", "no") 305 cananian 1.1.4.17 .equalsIgnoreCase("yes"); 306 cananian 1.1.4.1 /** Make interface methods table. */ 307 cananian 1.1.4.1 private Stm interfaceMethods(HClass hc, ClassHierarchy ch) { 308 cananian 1.1.4.1 // collect all interfaces implemented by this class 309 cananian 1.3.2.2 Set<HClass> interfaces = new HashSet<HClass>(); 310 cananian 1.1.4.1 for (HClass hcp=hc; hcp!=null; hcp=hcp.getSuperclass()) 311 cananian 1.1.4.1 interfaces.addAll(Arrays.asList(hcp.getInterfaces())); 312 cananian 1.1.4.17 if (!relinkerHack) // XXX EVIL: see above. 313 cananian 1.1.4.17 interfaces.retainAll(ch.classes()); 314 cananian 1.1.4.1 // all methods included in these interfaces. 315 cananian 1.3.2.2 Set<HMethod> methods = new HashSet<HMethod>(); 316 cananian 1.3.2.2 for (Iterator<HClass> it=interfaces.iterator(); it.hasNext(); ) 317 cananian 1.3.2.2 methods.addAll(Arrays.asList(it.next().getMethods())); 318 cananian 1.1.4.17 if (!relinkerHack) // XXX EVIL: see above. 319 cananian 1.1.4.17 methods.retainAll(ch.callableMethods()); 320 cananian 1.1.4.1 // double-check that these are all interface methods 321 cananian 1.1.4.12 // (also discard class initializers from the list) 322 cananian 1.1.4.23 // (also discard inherited methods of java.lang.Object) 323 cananian 1.3.2.2 for (Iterator<HMethod> it=methods.iterator(); it.hasNext(); ) { 324 cananian 1.3.2.2 HMethod hm = it.next(); 325 cananian 1.1.4.12 if (hm instanceof HInitializer) it.remove(); 326 cananian 1.1.4.23 else if (hm.getDeclaringClass().getName() 327 cananian 1.1.4.23 .equals("java.lang.Object")) it.remove(); 328 cananian 1.3.2.1 else assert hm.isInterfaceMethod(); 329 cananian 1.1.4.12 } 330 cananian 1.1.4.1 // remove duplicates (two methods with same signature) 331 cananian 1.1.4.31 // pre-load sigs with methods of java.lang.Object to make sure 332 cananian 1.1.4.31 // inherited methods of Object don't make it into the methods 333 cananian 1.1.4.31 // set. 334 cananian 1.3.2.2 Set<String> sigs = new HashSet<String>(); 335 cananian 1.7 for (HMethod hm : linker.forName("java.lang.Object").getMethods()) { 336 cananian 1.1.4.31 String sig = hm.getName() + hm.getDescriptor(); 337 cananian 1.1.4.31 sigs.add(sig); 338 cananian 1.1.4.31 } 339 cananian 1.3.2.2 for (Iterator<HMethod> it=methods.iterator(); it.hasNext(); ) { 340 cananian 1.3.2.2 HMethod hm = it.next(); 341 cananian 1.1.4.1 String sig = hm.getName() + hm.getDescriptor(); 342 cananian 1.1.4.1 if (sigs.contains(sig)) it.remove(); 343 cananian 1.1.4.1 else sigs.add(sig); 344 cananian 1.1.4.6 } 345 cananian 1.1.4.6 // remove methods which are not actually callable in this class. 346 cananian 1.3.2.2 for (Iterator<HMethod> it=methods.iterator(); it.hasNext(); ) { 347 cananian 1.3.2.2 HMethod hm = it.next(); 348 cananian 1.1.4.6 HMethod cm = hc.getMethod(hm.getName(), hm.getDescriptor()); 349 cananian 1.1.4.14 if (!ch.callableMethods().contains(cm) || 350 cananian 1.1.4.14 Modifier.isAbstract(cm.getModifiers())) 351 cananian 1.1.4.6 it.remove(); 352 cananian 1.1.4.1 } 353 cananian 1.1.4.1 // okay, now sort by InterfaceMethodMap ordering. 354 cananian 1.1.4.1 final MethodMap imm = m_tb.imm; 355 cananian 1.3.2.2 List<HMethod> ordered = new ArrayList<HMethod>(methods); 356 cananian 1.3.2.2 Collections.sort(ordered, new Comparator<HMethod>() { 357 cananian 1.3.2.2 public int compare(HMethod hm1, HMethod hm2) { 358 cananian 1.1.4.1 int i1 = imm.methodOrder(hm1); 359 cananian 1.1.4.1 int i2 = imm.methodOrder(hm2); 360 cananian 1.1.4.1 return i1 - i2; 361 cananian 1.1.4.1 } 362 cananian 1.1.4.1 }); 363 cananian 1.1.4.1 // okay, output in reverse order: 364 cananian 1.3.2.2 List<Stm> stmlist = new ArrayList<Stm>(ordered.size()); 365 cananian 1.1.4.1 int last_order = -1; 366 cananian 1.3.2.2 for (ListIterator<HMethod> it=ordered.listIterator(ordered.size()); 367 cananian 1.1.4.1 it.hasPrevious(); ) { 368 cananian 1.3.2.2 HMethod hm = it.previous(); 369 cananian 1.1.4.1 int this_order = imm.methodOrder(hm); 370 cananian 1.1.4.1 if (last_order!=-1) { 371 cananian 1.3.2.1 assert this_order < last_order; // else not ordered 372 cananian 1.1.4.1 for (int i=last_order-1; i > this_order; i--) 373 cananian 1.1.4.8 stmlist.add(_DATUM(new CONST(tf, null))); // null 374 cananian 1.1.4.1 } 375 cananian 1.1.4.1 // look up name of class method with this signature 376 cananian 1.1.4.1 HMethod cm = hc.getMethod(hm.getName(), hm.getDescriptor()); 377 cananian 1.1.4.1 // add entry for this method to table. 378 cananian 1.1.4.8 stmlist.add(_DATUM(m_nm.label(cm))); 379 cananian 1.1.4.1 last_order = this_order; 380 cananian 1.1.4.1 } 381 cananian 1.1.4.1 if (last_order!=-1) { 382 cananian 1.3.2.1 assert last_order>=0; 383 cananian 1.1.4.1 for (int i=last_order; i > 0; i--) 384 cananian 1.1.4.8 stmlist.add(_DATUM(new CONST(tf, null))); 385 cananian 1.1.4.1 } 386 cananian 1.1.4.1 // done! 387 cananian 1.1.4.1 return Stm.toStm(stmlist); 388 cananian 1.1.4.1 } 389 cananian 1.2 }