KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > quilt > cl > MethodTransformer


1 /* MethodTransformer.java */
2 package org.quilt.cl;
3
4 import java.util.Hashtable JavaDoc;
5 import java.util.List JavaDoc;
6
7 import org.apache.bcel.classfile.*;
8 import org.apache.bcel.Constants;
9 import org.apache.bcel.generic.*;
10 import org.quilt.graph.*;
11
12 /**
13  * Optionally preprocesses a method, optionally transforms
14  * its control flow graph, optionally postprocesses it. The list of
15  * preprocessors is applied in forward order before graph transformation.
16  * The corresponding list of postprocessors is applied in reverse order
17  * after graph transformation.
18  *
19  * @author <a HREF="jddixon@users.sourceforge.net">Jim Dixon</a>
20  */

21 public class MethodTransformer {
22
23     /** For passing application-specific data. XXX Not used, probably
24      * best dropped. */

25     private Hashtable JavaDoc methodHash = new Hashtable JavaDoc();
26
27     /** Ordered list of method pre- and post-processors.*/
28     private List JavaDoc mxf;
29
30     /** Graph processors. */
31     private List JavaDoc gxf;
32
33     /** Main graph processor. */
34     private GraphTransformer xformer;
35
36     /**
37      * Sets up method transformer, saving MethodXformer vector here
38      * and passing GraphXformer vector to that transformer.
39      */

40     public MethodTransformer( List JavaDoc mxf, List JavaDoc gxf) {
41         this.mxf = mxf;
42         this.gxf = gxf;
43         xformer = new GraphTransformer (gxf);
44     }
45
46     /**
47      * Get a reference to the hash used to share data between this
48      * and other transformers.
49      */

50     public Hashtable JavaDoc getMethodHash() {
51         return methodHash;
52     }
53     /**
54      * Zero out a badly-behaved method Xformer.
55      * @param mxf The tranformer being killed.
56      * @param e The exception responsible.
57      */

58     private void zapMethodXformer ( MethodXformer mxf, Exception JavaDoc e) {
59         System.err.println("WARNING: exception in "
60             + mxf.getName() + ": transformation will not be applied" );
61         e.printStackTrace();
62         mxf = null;
63     }
64     /**
65      * <p>Transform a specific method, first applying preprocessors,
66      * then transforming the graph, then applying method postprocessors.</p>
67      *
68      * @param clazz The class to which the method belongs
69      * @param method The MethodGen being transformed.
70      */

71     public MethodGen xform ( ClassGen clazz, Method orig ) {
72         if (orig == null) {
73             throw new IllegalArgumentException JavaDoc("null method");
74         }
75         MethodGen method = new MethodGen (orig, clazz.getClassName(),
76                                                 clazz.getConstantPool());
77         // New instances of the MethodXformers.
78
MethodXformer [] xf = new MethodXformer[ mxf.size() ];
79
80         // apply preprocessors in order
81
for (int i = 0; i < xf.length; i++) {
82             try {
83                xf[i] = (MethodXformer) (
84                         (mxf.get(i)).getClass().newInstance() );
85             } catch (IllegalAccessException JavaDoc e) {
86                 zapMethodXformer (xf[i], e);
87             } catch (InstantiationException JavaDoc e) {
88                 zapMethodXformer (xf[i], e);
89             }
90             if (xf[i] != null && method != null) {
91                 xf[i].preGraph (clazz, method);
92             }
93         }
94         // transform the graph
95
if (gxf.size() > 0 && method != null) {
96             InstructionList ilist = xformer.xform (clazz, method);
97             if (ilist == null) {
98                 System.out.println("MethodTransformer.xformer: WARNING: "
99                     + "xformer returned null instruction list");
100                 return null;
101             }
102             // Quilt 0.5 approach, turns out to be unnecessary; the
103
// exception handlers are based on instruction handles,
104
// which in turn contain references to the method's instructions,
105
// which remain valid while the graph is being transformed.
106
//
107
// XXX But we may want to allow handlers to be added or changed.
108

109             method.removeExceptionHandlers(); // new ones come from graph
110

111             //checkAndSetPos(ilist);
112
ilist.setPositions(true);
113             method.setInstructionList (ilist);
114
115             CodeExceptionGen [] cgs = xformer.getExceptionHandlers();
116             for (int i = 0; i < cgs.length; i++) {
117                 // DEBUG
118
System.out.println("adding exception " + i
119                     + " to method " + method.getName()
120                     + ": [" + cgs[i].getStartPC().getPosition()
121                     + ".." + cgs[i].getEndPC().getPosition()
122                     + "] --> " + cgs[i].getHandlerPC().getPosition()
123                   );
124                 // END
125

126                 method.addExceptionHandler (
127                     cgs[i].getStartPC(), cgs[i].getEndPC(),
128                     cgs[i].getHandlerPC(), cgs[i].getCatchType() );
129             }
130             method.removeNOPs();
131             method.update(); // to be called after editing MethodGen
132
// during development, exceptions were thrown in setMaxStack
133
try {
134                 method.setMaxStack();
135                 method.setMaxLocals();
136                 // method.stripAttributes(true); // Quilt 0.5 legacy
137
} catch (RuntimeException JavaDoc e) {
138                 e.printStackTrace();
139                 System.out.println("GraphTransformer.xformer:\n"
140                     + " EXCEPTION finishing method " + e);
141                 throw e;
142             }
143 // // DEBUG ONLY ///////////////////////////////////////////
144
// dumpIList (method, "after fixups");
145
// cgs = method.getExceptionHandlers();
146
// dumpExceptionHandlers(method, "after fixups", cgs.length);
147
// /////////////////////////////////////////////////////////
148
}
149
150         // apply postprocessors in reverse order
151
for (int i = xf.length-1; i >= 0; i--) {
152             if (xf[i] != null && method != null) {
153                 xf[i].postGraph (clazz, method);
154             }
155         }
156         // IF THERE HAVE BEEN ANY FATAL ERRORS, SHOULD RETURN NULL
157
return method;
158     }
159     // UTILITY METHODS //////////////////////////////////////////////
160
void dumpExceptionHandlers (MethodGen method, String JavaDoc where, int len) {
161         CodeExceptionGen handlers[] = method.getExceptionHandlers();
162         if (handlers.length != len) {
163             System.out.println("EXPECTED " + len
164                     + " exception handlers, found " + handlers.length);
165         }
166         if (handlers.length > 0) {
167             System.out.println("Exception handlers for method "
168                                 + method.getName() + " " + where + ":");
169             
170             for (int j = 0; j < handlers.length; j++) {
171                 System.out.println(" " + j
172                     + ": [" + handlers[j].getStartPC().getPosition()
173                     + ".." + handlers[j].getEndPC().getPosition()
174                     + "] --> " + handlers[j].getHandlerPC().getPosition()
175                 );
176             }
177         }
178     }
179     void dumpIList(MethodGen method, String JavaDoc where) {
180         InstructionList myList = method.getInstructionList();
181         System.out.println(
182             "MethodTransformer: instruction list " + where + ":");
183         int i = 0;
184         for (InstructionHandle ih = myList.getStart(); ih != null;
185                                                     ih = ih.getNext() ) {
186             System.out.println( " " + (i++) + " " + ih);
187         }
188     }
189 }
190
Popular Tags