1 2 package org.quilt.cl; 3 4 import java.util.List ; 5 import org.apache.bcel.classfile.LineNumberTable; 6 import org.apache.bcel.classfile.Method; 7 import org.apache.bcel.generic.*; 8 9 import org.quilt.graph.*; 10 11 22 public class GraphTransformer { 23 24 25 private List gxf; 26 27 private TryStacks ts = null; 28 29 30 private CodeExceptionGen[] handlers; 31 32 33 private CodeExceptionGen [] ceg = null; 34 35 36 private InstructionList ilist = null; 37 38 47 public GraphTransformer ( List gxf ) { 48 this.gxf = gxf; 49 } 50 51 private void zapGraphXformer ( GraphXformer gxf, Exception e) { 52 System.err.println("WARNING: exception in " 53 + ": transformation will not be applied" ); 55 e.printStackTrace(); 56 gxf = null; 57 } 58 67 public InstructionList xform (ClassGen clazz, MethodGen method ) { 68 if (method == null) { 69 throw new IllegalArgumentException ("null method"); 70 } 71 ControlFlowGraph graph = makeGraph(clazz, method); 72 GraphXformer [] xf = new GraphXformer[ gxf.size() ]; 73 74 for (int i = 0; i < gxf.size(); i++) { 76 try { 77 xf[i] = (GraphXformer) ( 78 (gxf.get(i)).getClass().newInstance() ); 79 } catch (IllegalAccessException e ) { 80 zapGraphXformer (xf[i], e); 81 } catch (InstantiationException e ) { 82 zapGraphXformer (xf[i], e); 83 } 84 if (xf[i] != null && graph != null) { 85 xf[i].xform(clazz, method, graph); 86 } 87 } 88 89 if (graph == null) { 90 return null; 91 } 92 BytecodeCollector bc = collapseGraph(graph); 93 ilist = bc.getInstructionList(); 94 if (ilist == null) { 95 return null; 96 } 97 if (ts == null) { 98 ceg = null; 99 } else { 100 ceg = bc.getCEGs(ts.getCatchData()); 102 if (ceg.length != handlers.length) { 103 System.out.println( 104 "GraphTransformer.xform WARNING - PROBABLE INTERNAL ERROR:\n method had " 105 + handlers.length 106 + " exception handlers, but after graph transformation " 107 + ceg.length); 108 } 109 } 110 return ilist; 111 } 112 118 public CodeExceptionGen[] getExceptionHandlers() { 119 if (ilist != null && ceg != null) { 120 return ceg; 121 } else { 122 return new CodeExceptionGen[0]; 123 } 124 } 125 131 final protected ControlFlowGraph makeGraph ( ClassGen clazz, 132 MethodGen method ) { 133 134 SortedBlocks blox = new SortedBlocks(); 135 handlers = method.getExceptionHandlers(); 136 ControlFlowGraph cfg = new ControlFlowGraph(); 137 ControlFlowGraph currGraph = cfg; 138 Edge e = cfg.getEntry().getEdge(); 139 ts = null; 140 boolean startBlock = false; 141 CodeVertex currV = null; 142 LineNumberTable lineTab = method.getLineNumberTable ( 143 clazz.getConstantPool() ); 144 if (handlers.length > 0) { 145 ts = new TryStacks (handlers, blox, cfg); 147 } 148 if (blox.exists(0)) { 149 currV = blox.get(0); 151 } else { 152 currV = blox.find (0, currGraph, e); 153 } 154 if (lineTab != null) { 155 currV.setStartLine( lineTab.getSourceLine(0) ); 156 } 157 e = currV.getEdge(); 158 currGraph = (ControlFlowGraph) currV.getGraph(); 159 160 163 InstructionList iList = method.getInstructionList(); 164 InstructionHandle currHandle = iList.getStart(); 165 Instruction inst = currHandle.getInstruction(); 166 int pos = currHandle.getPosition(); 167 InstructionList vIList = currV.getInstructionList(); 169 170 while (currHandle != null) { 171 if (startBlock) { 172 startBlock = false; 173 if (e == null) { 174 if ( !blox.exists(pos) ) { 175 currV = new CodeVertex (currGraph, pos); 180 } else { 181 currV = blox.get(pos); 182 } 183 } else { 184 currV = blox.find(pos, currGraph, e); 185 } 186 if (lineTab != null) { 187 currV.setStartLine( lineTab.getSourceLine(pos) ); 188 } 189 e = currV.getEdge(); 190 currGraph = (ControlFlowGraph) currV.getGraph(); 191 vIList = currV.getInstructionList(); 195 } 196 if (inst instanceof GotoInstruction) { 197 Edge otherEdge = currV.makeBinary(); 202 currV.setConnInst(inst); 203 int tpos = ((GotoInstruction)inst).getTarget().getPosition(); 204 int endTry; 205 if (ts == null) { 206 endTry = -1; 207 } else { 208 endTry= ts.getEndTry(currGraph); 209 } 210 if (endTry >= 0 && tpos > endTry) { 211 Exit currExit = currGraph.getExit(); 215 otherEdge.setTarget(currExit); 216 if (!blox.exists(tpos)) { 217 Vertex vFinal; 218 for (vFinal = currExit; 219 vFinal.getTarget() instanceof Entry; 220 vFinal = vFinal.getTarget()) { 221 ; 222 } 223 blox.add (tpos, vFinal.getEdge()); 224 } 225 } else { 226 blox.find (tpos, currGraph, otherEdge); 228 } 229 startBlock = true; 231 236 } else if (inst instanceof IfInstruction 237 || inst instanceof JSR ) { 238 Edge otherEdge = currV.makeBinary(); 239 currV.setConnInst(inst); 240 int tpos = ((BranchInstruction)inst).getTarget().getPosition(); 242 blox.find(tpos, currGraph, otherEdge); 244 startBlock = true; 247 } else if (inst instanceof ReturnInstruction 248 || inst instanceof RET) { 249 currV.setConnInst(inst); 250 e = null; 251 startBlock = true; 252 253 } else if (inst instanceof InvokeInstruction) { 254 currV.setConnInst(inst); 255 startBlock = true; 258 } else if (inst instanceof Select) { 259 InstructionHandle[] targets = ((Select)inst).getTargets(); 260 ComplexConnector conn = currV.makeComplex(targets.length); 262 currV.setConnInst(inst); 263 for (int i = 0; i < targets.length; i++) { 264 int tpos = targets[i].getPosition(); 265 blox.find(tpos, currGraph, conn.getEdge(i)); 266 } 267 InstructionHandle theDefault = ((Select)inst).getTarget(); 269 if (theDefault != null) { 270 blox.find ( theDefault.getPosition(), 271 currGraph, conn.getEdge()); 272 } 273 e = null; startBlock = true; 275 276 } else if (inst instanceof ExceptionThrower) { 277 285 currV.setConnInst(inst); 286 startBlock = true; 288 } else { 289 vIList.append(inst); } 291 InstructionHandle nextHandle = currHandle.getNext(); 292 if (nextHandle != null) { 293 if (hasInbound(nextHandle)) { 294 startBlock = true; 297 } 298 } 299 if (startBlock == true) { 300 if (lineTab != null) { 301 currV.setEndLine( lineTab.getSourceLine(0) ); 302 } 303 } 304 currHandle = nextHandle; 305 if (currHandle != null) { 306 pos = currHandle.getPosition(); 307 inst = currHandle.getInstruction(); 308 } 309 } 310 return cfg; 311 } 312 319 final public static boolean hasInbound (InstructionHandle ih ) { 320 if (ih.hasTargeters()) { 321 InstructionTargeter targeters[] = ih.getTargeters(); 322 for (int j = 0; j < targeters.length; j++) { 323 if (targeters[j] instanceof BranchInstruction) { 324 return true; 325 } 326 if (targeters[j] instanceof CodeExceptionGen) { 327 return true; 328 } 329 } 330 } 331 return false; 332 } 333 337 final protected BytecodeCollector collapseGraph(ControlFlowGraph graph) { 338 BytecodeCollector theMan = new BytecodeCollector(); 339 new Walker().visit(graph, theMan); 340 return theMan; 341 } 342 } 343 | Popular Tags |