1 cananian 1.1.2.1 // CloneImplementer.java, created Wed Jan 17 21:15:00 2001 by cananian
  2 cananian 1.1.2.1 // Copyright (C) 2000 C. Scott Ananian <cananian@alumni.princeton.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.Analysis.Transactions;
  5 cananian 1.1.2.1 
  6 cananian 1.7     import harpoon.Analysis.DefaultAllocationInformationMap;
  7 cananian 1.1.2.1 import harpoon.ClassFile.DuplicateMemberException;
  8 cananian 1.1.2.1 import harpoon.ClassFile.HClass;
  9 cananian 1.1.2.1 import harpoon.ClassFile.HClassMutator;
 10 cananian 1.1.2.1 import harpoon.ClassFile.HCode;
 11 cananian 1.1.2.1 import harpoon.ClassFile.HCodeFactory;
 12 cananian 1.1.2.1 import harpoon.ClassFile.HField;
 13 cananian 1.1.2.1 import harpoon.ClassFile.HMethod;
 14 cananian 1.1.2.1 import harpoon.ClassFile.HMethodMutator;
 15 cananian 1.1.2.1 import harpoon.ClassFile.Linker;
 16 cananian 1.5     import harpoon.ClassFile.NoSuchClassException;
 17 cananian 1.1.2.1 import harpoon.IR.Quads.AGET;
 18 cananian 1.1.2.1 import harpoon.IR.Quads.ALENGTH;
 19 cananian 1.1.2.1 import harpoon.IR.Quads.ANEW;
 20 cananian 1.1.2.1 import harpoon.IR.Quads.ASET;
 21 cananian 1.1.2.1 import harpoon.IR.Quads.CALL;
 22 cananian 1.1.2.1 import harpoon.IR.Quads.CJMP;
 23 cananian 1.1.2.1 import harpoon.IR.Quads.CONST;
 24 cananian 1.1.2.1 import harpoon.IR.Quads.FOOTER;
 25 cananian 1.1.2.1 import harpoon.IR.Quads.GET;
 26 cananian 1.1.2.1 import harpoon.IR.Quads.HEADER;
 27 cananian 1.1.2.1 import harpoon.IR.Quads.METHOD;
 28 cananian 1.1.2.1 import harpoon.IR.Quads.NEW;
 29 cananian 1.1.2.1 import harpoon.IR.Quads.OPER;
 30 cananian 1.1.2.1 import harpoon.IR.Quads.PHI;
 31 cananian 1.1.2.1 import harpoon.IR.Quads.Qop;
 32 cananian 1.1.2.1 import harpoon.IR.Quads.Quad;
 33 cananian 1.1.2.1 import harpoon.IR.Quads.QuadFactory;
 34 cananian 1.1.2.1 import harpoon.IR.Quads.QuadSSI;
 35 cananian 1.1.2.1 import harpoon.IR.Quads.RETURN;
 36 cananian 1.1.2.1 import harpoon.IR.Quads.SET;
 37 cananian 1.1.2.1 import harpoon.IR.Quads.THROW;
 38 cananian 1.1.2.1 import harpoon.Temp.Temp;
 39 cananian 1.1.2.1 import harpoon.Util.Util;
 40 cananian 1.1.2.1 
 41 cananian 1.1.2.1 import java.lang.reflect.Modifier;
 42 cananian 1.1.2.1 import java.util.ArrayList;
 43 cananian 1.1.2.1 import java.util.Arrays;
 44 cananian 1.1.2.1 import java.util.HashMap;
 45 cananian 1.1.2.1 import java.util.Iterator;
 46 cananian 1.1.2.1 import java.util.List;
 47 cananian 1.1.2.1 import java.util.Map;
 48 cananian 1.1.2.1 import java.util.Set;
 49 cananian 1.1.2.1 /**
 50 cananian 1.1.2.1  * <code>CloneImplementer</code> adds synthetic specialized implementations
 51 cananian 1.1.2.1  * for all clone methods.  This works around the incomplete field type
 52 cananian 1.1.2.1  * information available to the runtime, as well as making clone() methods
 53 cananian 1.1.2.1  * a little more amenable to standard analysis.  (OK, the field type
 54 cananian 1.1.2.1  * information isn't really *incomplete* as much as it is *inefficient to
 55 cananian 1.1.2.1  * access* in the way we'd like to.)
 56 cananian 1.1.2.1  * <p>
 57 cananian 1.1.2.1  * Arguably, this class should belong in the
 58 cananian 1.1.2.1  * <code>harpoon.Analysis.Quads</code> package, but we'll leave it
 59 cananian 1.1.2.1  * here until someone other than the Transactions transformation
 60 cananian 1.1.2.1  * needs it.
 61 cananian 1.1.2.1  * <p>
 62 cananian 1.1.2.1  * Implementation details: a specialized method called
 63 cananian 1.1.2.1  * <code>$clone$()</code> is created in all known classes.  The
 64 cananian 1.1.2.1  * existing native <code>clone()</code> methods are made non-native
 65 cananian 1.1.2.1  * and given implementations which redirect to the virtual
 66 cananian 1.1.2.1  * <code>$clone$()</code> method.
 67 cananian 1.1.2.1  * 
 68 cananian 1.1.2.1  * @author  C. Scott Ananian <cananian@alumni.princeton.edu>
 69 cananian 1.8      * @version $Id: CloneImplementer.java,v 1.8 2004/02/08 03:20:25 cananian Exp $
 70 cananian 1.1.2.1  * @see harpoon.IR.Quads.CloneSynthesizer */
 71 cananian 1.1.2.1 public class CloneImplementer implements HCodeFactory, java.io.Serializable {
 72 cananian 1.1.2.1     /** CONSTANTS */
 73 cananian 1.1.2.1     /** Name of usual "clone" method. */
 74 cananian 1.1.2.1     private final static String CLONE_NAME = "clone";
 75 cananian 1.1.2.1     /** Name of our synthesized "$clone$" method. */
 76 cananian 1.1.2.1     private final static String CLONEX_NAME = "$clone$";
 77 cananian 1.1.2.1     /** Descriptor of all clone methods. */
 78 cananian 1.1.2.1     private final static String CLONE_DESC = "()Ljava/lang/Object;";
 79 cananian 1.5         /** Descriptor of the GNU Classpath clone method. */
 80 cananian 1.5         private final static String GNUCP_CLONE_DESC =
 81 cananian 1.5             "(Ljava/lang/Cloneable;)Ljava/lang/Object;";
 82 cananian 1.1.2.1     /** Modifiers of all standard clone methods. */
 83 cananian 1.1.2.1     private final static int    CLONE_MODS = Modifier.PROTECTED;
 84 cananian 1.5         /** Descriptor of java.lang.VMObject (GNU Classpath only) */
 85 cananian 1.5         private final static String GNUCP_VMOBJ_DESC = "Ljava/lang/VMObject;";
 86 cananian 1.1.2.1     /** Descriptor of java.lang.Object */
 87 cananian 1.1.2.1     private final static String OBJ_DESC = "Ljava/lang/Object;";
 88 cananian 1.1.2.1     /** Descriptor of Object[] */
 89 cananian 1.1.2.1     private final static String OBJARR_DESC = "[Ljava/lang/Object;";
 90 cananian 1.1.2.1     /** Parent code factory. */
 91 cananian 1.1.2.1     final HCodeFactory parent;
 92 cananian 1.1.2.1     /** Representation cache. */
 93 cananian 1.6         final Map<HMethod,HCode> cache = new HashMap<HMethod,HCode>();
 94 cananian 1.1.2.1 
 95 cananian 1.1.2.1      /** Creates a <code>CloneImplementer</code> based on the
 96 cananian 1.1.2.1       *  given <code>HCodeFactory</code>, which must produce
 97 cananian 1.1.2.1       *  some QuadSSI form. */
 98 cananian 1.1.2.1     public CloneImplementer(HCodeFactory parent, Linker l, Set knownClasses) { 
 99 cananian 1.3.2.1         assert parent.getCodeName().equals(QuadSSI.codename);
100 cananian 1.1.2.1         this.parent = parent;
101 cananian 1.1.2.3         HClass HCobject = l.forName("java.lang.Object");
102 cananian 1.1.2.3         HClass HCcloneable = l.forName("java.lang.Cloneable");
103 cananian 1.1.2.1         /* okay, we need to add clone() methods to all of the knownClasses */
104 cananian 1.8             for (Object hcO : knownClasses) {
105 cananian 1.8                 HClass hc = (HClass) hcO;
106 cananian 1.1.2.2             if (hc.isPrimitive() || hc.isInterface()) continue;
107 cananian 1.1.2.3             if (!hc.equals(HCobject) && !hc.isInstanceOf(HCcloneable))
108 cananian 1.1.2.3                 continue; // non-cloneable objects get the default impl.
109 cananian 1.1.2.1             try {
110 cananian 1.1.2.1                 HMethod hm =
111 cananian 1.1.2.1                     hc.getMutator().addDeclaredMethod(CLONEX_NAME, CLONE_DESC);
112 cananian 1.1.2.1                 hm.getMutator().setModifiers(CLONE_MODS);
113 cananian 1.1.2.1                 hm.getMutator().setSynthetic(false);
114 cananian 1.1.2.1             } catch(DuplicateMemberException dme) {
115 cananian 1.3.2.1                 assert false : "Can't create "+CLONEX_NAME+" in "+hc;
116 cananian 1.1.2.1             }
117 cananian 1.6                 // for compatibility with other transformations that may
118 cananian 1.6                 // add fields, cache away the declared fields of this class
119 cananian 1.6                 for (; hc!=null; hc=hc.getSuperclass())
120 cananian 1.6                     declaredFieldMap.put(hc,Arrays.asList(hc.getDeclaredFields()));
121 cananian 1.1.2.1         }
122 cananian 1.1.2.1         /* 'un-native-ify' standard clone() methods (incl prim arrays)  */
123 cananian 1.1.2.1         String descs[] = new String[] {
124 cananian 1.1.2.1             "[Z", "[B", "[S", "[I", "[J", "[F", "[D", "[C",
125 cananian 1.1.2.1             OBJ_DESC, OBJARR_DESC
126 cananian 1.1.2.1         };
127 cananian 1.1.2.1         for (int i=0; i<descs.length; i++)
128 cananian 1.1.2.1             l.forDescriptor(descs[i]).getMethod(CLONE_NAME, CLONE_DESC)
129 cananian 1.1.2.1                 .getMutator().removeModifiers(Modifier.NATIVE);
130 cananian 1.5             // classpath compatibility.
131 cananian 1.5             try {
132 cananian 1.5                 l.forDescriptor(GNUCP_VMOBJ_DESC)
133 cananian 1.5                     .getMethod(CLONE_NAME, GNUCP_CLONE_DESC)
134 cananian 1.5                     .getMutator().removeModifiers(Modifier.NATIVE);
135 cananian 1.5             } catch (NoSuchClassException e) { /* not using classpath */ }
136 cananian 1.1.2.1         /* done */
137 cananian 1.1.2.1     }
138 cananian 1.1.2.1     public String getCodeName() { return parent.getCodeName(); }
139 cananian 1.1.2.1     public void clear(HMethod m) { cache.remove(m); parent.clear(m); }
140 cananian 1.1.2.1     public HCode convert(HMethod m) {
141 cananian 1.1.2.1         // check cache first
142 cananian 1.6             if (cache.containsKey(m))
143 cananian 1.6                 /* do nothing; cache already contains appropriate HCode */;
144 cananian 1.1.2.1         // now see if we need to synthesize a code for this method.
145 cananian 1.6             else if (m.getName().equals(CLONE_NAME) &&
146 cananian 1.1.2.1             m.getDescriptor().equals(CLONE_DESC) &&
147 cananian 1.1.2.1             (m.getDeclaringClass().getDescriptor().equals(OBJ_DESC) ||
148 cananian 1.1.2.1              m.getDeclaringClass().isArray()))
149 cananian 1.6                 cache.put(m, new CloneRedirectCode(m));
150 cananian 1.5             // classpath compatibility: VMObject.clone()
151 cananian 1.6             else if (m.getName().equals(CLONE_NAME) &&
152 cananian 1.5                 m.getDescriptor().equals(GNUCP_CLONE_DESC) &&
153 cananian 1.5                 m.getDeclaringClass().getDescriptor().equals(GNUCP_VMOBJ_DESC))
154 cananian 1.6                 cache.put(m, new CloneRedirectCode(m));
155 cananian 1.5             // okay, now implement $clone$
156 cananian 1.6             else if (m.getName().equals(CLONEX_NAME) &&
157 cananian 1.1.2.1             m.getDescriptor().equals(CLONE_DESC)) {
158 cananian 1.1.2.3             if (m.getDeclaringClass().getDescriptor().equals(OBJ_DESC))
159 cananian 1.6                     cache.put(m, new NotCloneableCode(m));
160 cananian 1.1.2.3             else if (m.getDeclaringClass().isArray())
161 cananian 1.6                     cache.put(m, new ArrayCloneCode(m));
162 cananian 1.1.2.1             else
163 cananian 1.6                     cache.put(m, new ObjectCloneCode
164 cananian 1.6                               (m, fields(m.getDeclaringClass())));
165 cananian 1.6             } else  // not synthetic: use parent's code.
166 cananian 1.6                 cache.put(m, parent.convert(m));
167 cananian 1.6             return cache.get(m);
168 cananian 1.1.2.1     }
169 cananian 1.1.2.2     /** this method just redirects to Object.$clone$() */
170 cananian 1.1.2.1     private static class CloneRedirectCode extends QuadSSI {
171 cananian 1.1.2.1         CloneRedirectCode(HMethod m) {
172 cananian 1.1.2.1             super(m, null);
173 cananian 1.1.2.1             HMethod hm = m.getDeclaringClass().getLinker()
174 cananian 1.1.2.1                 .forDescriptor(OBJ_DESC).getMethod(CLONEX_NAME, CLONE_DESC);
175 cananian 1.1.2.1             Temp thisT = new Temp(qf.tempFactory(), "this");
176 cananian 1.1.2.1             Temp retvT = new Temp(qf.tempFactory(), "retval");
177 cananian 1.1.2.1             Temp retxT = new Temp(qf.tempFactory(), "retex");
178 cananian 1.1.2.1             Quad q0 = new HEADER(qf, null);
179 cananian 1.1.2.1             Quad q1 = new METHOD(qf, null, new Temp[] { thisT }, 1);
180 cananian 1.1.2.1             Quad q2 = new CALL(qf, null, hm, new Temp[] { thisT },
181 cananian 1.1.2.1                                retvT, retxT, true, true, new Temp[0]);
182 cananian 1.1.2.1             Quad q3 = new RETURN(qf, null, retvT);
183 cananian 1.1.2.1             Quad q4 = new THROW(qf, null, retxT);
184 cananian 1.1.2.1             Quad qF = new FOOTER(qf, null, 3);
185 cananian 1.1.2.1             Quad.addEdge(q0, 0, qF, 0);
186 cananian 1.1.2.2             Quad.addEdge(q0, 1, q1, 0);
187 cananian 1.1.2.1             Quad.addEdge(q1, 0, q2, 0);
188 cananian 1.1.2.1             Quad.addEdge(q2, 0, q3, 0);
189 cananian 1.1.2.1             Quad.addEdge(q2, 1, q4, 0);
190 cananian 1.1.2.1             Quad.addEdge(q3, 0, qF, 1);
191 cananian 1.1.2.1             Quad.addEdge(q4, 0, qF, 2);
192 cananian 1.1.2.1             // done!
193 cananian 1.1.2.1             this.quads = q0;
194 cananian 1.7                 // no allocation in this method, so this next statement is
195 cananian 1.7                 // actually redundant.
196 cananian 1.7                 setAllocationInformation(new DefaultAllocationInformationMap());
197 cananian 1.1.2.1         }
198 cananian 1.1.2.1     }
199 cananian 1.1.2.3     /** this method throws a CloneNotSupportedException */
200 cananian 1.1.2.3     private static class NotCloneableCode extends QuadSSI {
201 cananian 1.1.2.3         NotCloneableCode(HMethod m) {
202 cananian 1.1.2.3             super(m, null);
203 cananian 1.1.2.3             HClass HCcnse = m.getDeclaringClass().getLinker()
204 cananian 1.1.2.3                 .forName("java.lang.CloneNotSupportedException");
205 cananian 1.1.2.3             HMethod hm = HCcnse.getConstructor(new HClass[0]);
206 cananian 1.1.2.3             Temp thisT = new Temp(qf.tempFactory(), "this");
207 cananian 1.1.2.3             Temp excT0 = new Temp(qf.tempFactory(), "exc");
208 cananian 1.1.2.3             Temp excT1 = new Temp(qf.tempFactory(), "exc");
209 cananian 1.1.2.3             Temp excT2 = new Temp(qf.tempFactory(), "exc");
210 cananian 1.1.2.3             Quad q0 = new HEADER(qf, null);
211 cananian 1.1.2.3             Quad q1 = new METHOD(qf, null, new Temp[] { thisT }, 1);
212 cananian 1.1.2.3             Quad q2 = new NEW(qf, null, excT0, HCcnse);
213 cananian 1.1.2.3             Quad q3 = new CALL(qf, null, hm, new Temp[] { excT0 }, null,
214 cananian 1.1.2.3                                excT1, false, false, new Temp[0]);
215 cananian 1.1.2.3             Quad q4 = new PHI(qf, null,
216 cananian 1.1.2.3                               new Temp[] { excT2 },
217 cananian 1.1.2.3                               new Temp[][] { new Temp[] { excT0, excT1 }}, 2);
218 cananian 1.1.2.3             Quad q5 = new THROW(qf, null, excT2);
219 cananian 1.1.2.3             Quad qF = new FOOTER(qf, null, 2);
220 cananian 1.1.2.3             Quad.addEdge(q0, 0, qF, 0);
221 cananian 1.1.2.3             Quad.addEdge(q0, 1, q1, 0);
222 cananian 1.1.2.3             Quad.addEdges(new Quad[] { q1, q2, q3, q4, q5 });
223 cananian 1.1.2.3             Quad.addEdge(q3, 1, q4, 1);
224 cananian 1.1.2.3             Quad.addEdge(q5, 0, qF, 1);
225 cananian 1.1.2.3             // done!
226 cananian 1.1.2.3             this.quads = q0;
227 cananian 1.7                 setAllocationInformation(new DefaultAllocationInformationMap());
228 cananian 1.1.2.3         }
229 cananian 1.1.2.3     }
230 cananian 1.1.2.1     /* this method implements a specialized array clone operation */
231 cananian 1.1.2.1     private static class ArrayCloneCode extends QuadSSI {
232 cananian 1.1.2.1         ArrayCloneCode(HMethod m) {
233 cananian 1.1.2.1             //XXX: this is actually pruned-ssi form, since we don't
234 cananian 1.1.2.1             //     add phis and sigmas for thisT and objT.
235 cananian 1.1.2.1             super(m, null);
236 cananian 1.1.2.1             HClass hc = m.getDeclaringClass();
237 cananian 1.1.2.1             HClass hcC = hc.getComponentType();
238 cananian 1.1.2.1             Temp thisT = new Temp(qf.tempFactory(), "this");
239 cananian 1.1.2.1             Temp lenT = new Temp(qf.tempFactory(), "length");
240 cananian 1.1.2.1             Temp objT = new Temp(qf.tempFactory(), "result");
241 cananian 1.1.2.1             Temp indT0 = new Temp(qf.tempFactory(), "index");
242 cananian 1.1.2.1             Temp indT1 = new Temp(qf.tempFactory(), "index");
243 cananian 1.1.2.1             Temp indT2 = new Temp(qf.tempFactory(), "index");
244 cananian 1.1.2.1             Temp indT3 = new Temp(qf.tempFactory(), "index");
245 cananian 1.1.2.1             Temp indT4 = new Temp(qf.tempFactory(), "index");
246 cananian 1.1.2.1             Temp tstT = new Temp(qf.tempFactory(), "test");
247 cananian 1.1.2.1             Temp tmpT = new Temp(qf.tempFactory(), "temp");
248 cananian 1.1.2.1             Temp oneT = new Temp(qf.tempFactory(), "one");
249 cananian 1.1.2.1             Quad q0 = new HEADER(qf, null);
250 cananian 1.1.2.1             Quad q1 = new METHOD(qf, null, new Temp[] { thisT }, 1);
251 cananian 1.1.2.1             Quad q2 = new ALENGTH(qf, null, lenT, thisT);
252 cananian 1.1.2.1             Quad q3 = new ANEW(qf, null, objT, hc, new Temp[] { lenT });
253 cananian 1.1.2.1             // for (i=0; i<len; i++) ASET(objT, AGET(thisT, i))
254 cananian 1.1.2.1             Quad q4 = new CONST(qf, null, indT0, new Integer(0), HClass.Int);
255 cananian 1.1.2.1             Quad q5 = new PHI(qf, null, // indT1 = phi(indT0, indT4)
256 cananian 1.1.2.1                               new Temp[] { indT1 },
257 cananian 1.1.2.1                               new Temp[][] { new Temp[] { indT0, indT4 } }, 2);
258 cananian 1.1.2.1             Quad q6 = new OPER(qf, null, Qop.ICMPGT, tstT,
259 cananian 1.1.2.1                                new Temp[] { lenT, indT1});
260 cananian 1.1.2.1             Quad q7 = new CJMP(qf, null, tstT, // <indT2, indT3>=sigma(indT1)
261 cananian 1.1.2.1                                new Temp[][] { new Temp[] { indT2, indT3 } },
262 cananian 1.1.2.1                                new Temp[] { indT1 });
263 cananian 1.1.2.1             Quad q8 = new AGET(qf, null, tmpT, thisT, indT3, hcC);
264 cananian 1.1.2.1             Quad q9 = new ASET(qf, null, objT, indT3, tmpT, hcC);
265 cananian 1.1.2.1             Quad qA = new CONST(qf, null, oneT, new Integer(1), HClass.Int);
266 cananian 1.1.2.1             Quad qB = new OPER(qf, null, Qop.IADD, indT4,
267 cananian 1.1.2.1                                new Temp[] { indT3, oneT });
268 cananian 1.1.2.1             Quad qC = new RETURN(qf, null, objT);
269 cananian 1.1.2.1             Quad qF = new FOOTER(qf, null, 2);
270 cananian 1.1.2.1             Quad.addEdge(q0, 0, qF, 0);
271 cananian 1.1.2.2             Quad.addEdge(q0, 1, q1, 0);
272 cananian 1.1.2.1             Quad.addEdges(new Quad[] { q1, q2, q3, q4, q5, q6, q7, qC });
273 cananian 1.1.2.1             Quad.addEdge(q7, 1, q8, 0);
274 cananian 1.1.2.1             Quad.addEdge(qC, 0, qF, 1);
275 cananian 1.1.2.1             Quad.addEdges(new Quad[] { q8, q9, qA, qB });
276 cananian 1.1.2.1             Quad.addEdge(qB, 0, q5, 1);
277 cananian 1.1.2.1             // done!
278 cananian 1.1.2.1             this.quads = q0;
279 cananian 1.7                 setAllocationInformation(new DefaultAllocationInformationMap());
280 cananian 1.1.2.1         }
281 cananian 1.1.2.1     }
282 cananian 1.1.2.1     /* this method implements a specialized object clone operation */
283 cananian 1.1.2.1     private static class ObjectCloneCode extends QuadSSI {
284 cananian 1.6             ObjectCloneCode(HMethod m, List<HField> fields) {
285 cananian 1.1.2.1             super(m, null);
286 cananian 1.1.2.1             HClass hc = m.getDeclaringClass();
287 cananian 1.1.2.1             Temp thisT = new Temp(qf.tempFactory());
288 cananian 1.1.2.1             Temp objT = new Temp(qf.tempFactory());
289 cananian 1.1.2.1             Quad q0 = new HEADER(qf, null);
290 cananian 1.1.2.1             Quad q1 = new METHOD(qf, null, new Temp[] { thisT }, 1);
291 cananian 1.1.2.1             Quad q2 = new NEW(qf, null, objT, hc);
292 cananian 1.1.2.1             Quad.addEdge(q0, 1, q1, 0);
293 cananian 1.1.2.1             Quad.addEdge(q1, 0, q2, 0);
294 cananian 1.1.2.1             Quad qq = q2;
295 cananian 1.8                 for (HField hf : fields) {
296 cananian 1.1.2.1                 Temp tT = new Temp(qf.tempFactory());
297 cananian 1.1.2.1                 Quad q3 = new GET(qf, null, tT, hf, thisT);
298 cananian 1.1.2.1                 Quad q4 = new SET(qf, null, hf, objT, tT);
299 cananian 1.1.2.1                 Quad.addEdges(new Quad[] { qq, q3, q4 });
300 cananian 1.1.2.1                 qq = q4;
301 cananian 1.1.2.1             }
302 cananian 1.1.2.3             Quad q5 = new RETURN(qf, null, objT);
303 cananian 1.1.2.1             Quad qF = new FOOTER(qf, null, 2);
304 cananian 1.1.2.1             Quad.addEdge(qq, 0, q5, 0);
305 cananian 1.1.2.1             Quad.addEdge(q5, 0, qF, 1);
306 cananian 1.1.2.1             Quad.addEdge(q0, 0, qF, 0);
307 cananian 1.1.2.1             // done!
308 cananian 1.1.2.1             this.quads = q0;
309 cananian 1.7                 setAllocationInformation(new DefaultAllocationInformationMap());
310 cananian 1.1.2.1         }
311 cananian 1.1.2.1     }
312 cananian 1.6         /** Return a <code>List</code> of all fields (including
313 cananian 1.6             private fields of superclasses) belonging to
314 cananian 1.6             <code>HClass</code> <code>hc</code>. */
315 cananian 1.6         private List<HField> fields(HClass hc) {
316 cananian 1.6             List<HField> l = new ArrayList<HField>(hc.getFields().length);
317 cananian 1.6             for (; hc!=null; hc=hc.getSuperclass())
318 cananian 1.6                 l.addAll(0, declaredFieldMap.get(hc));
319 cananian 1.6             // filter out static fields.
320 cananian 1.6             for (Iterator<HField> it=l.iterator(); it.hasNext(); )
321 cananian 1.6                 if (it.next().isStatic())
322 cananian 1.6                     it.remove();
323 cananian 1.6             // done.
324 cananian 1.6             return l;
325 cananian 1.6         }
326 cananian 1.6         private final Map<HClass,List<HField>> declaredFieldMap =
327 cananian 1.6             new HashMap<HClass,List<HField>>();
328 cananian 1.2     }