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      }