View Javadoc
1 /* GraphAction.java */ 2 package org.quilt.cover.stmt; 3 4 import org.apache.bcel.Constants; 5 import org.apache.bcel.classfile.ConstantPool; 6 import org.apache.bcel.generic.*; 7 import org.quilt.cl.*; 8 import org.quilt.graph.*; 9 10 /*** 11 * Walk the control flow graph, adding counter vertices on all edges 12 * inbound to code vertices. XXX Except those likely to cause 13 * problems; need to review this code later to make sure that all 14 * possibilities are covered. 15 * 16 * @author <a href="mailto:jddixon@users.sourceforge.net">Jim Dixon</a> 17 */ 18 public class GraphAction implements GraphXformer { 19 20 private static StmtRegistry stmtReg = null; 21 private ClassGen clazz_ = null; 22 private MethodGen method_ = null; 23 24 /*** Processor name for use in reports. */ 25 private static String name_ = null; 26 27 private InstructionFactory factory_; 28 29 private ConstantPoolGen cpGen_; 30 31 /*** Number of counters added to the graph. */ 32 private int counterCount = 0; 33 34 /*** The class Xformer responsible for tracking counter counts */ 35 private ClassAction classAct_ = null; 36 37 /*** constructor. */ 38 public GraphAction () {} 39 40 public GraphAction (StmtRegistry reg) { 41 stmtReg = reg; 42 setName(this.getClass().getName()); 43 } 44 45 /*** 46 * Constructor used by StmtRegistry. XXX Deprecate, dropping 47 * classAct argument. (Pass via registry if it's really necessary.) 48 * 49 * @param classAct The Xformer at the class level; the method needs 50 * to report back to it. 51 */ 52 public GraphAction (StmtRegistry reg, ClassAction classAct) { 53 if (reg == null || classAct == null) { 54 throw new IllegalArgumentException("null argument"); 55 } 56 stmtReg = reg; 57 classAct_ = classAct; 58 setName(this.getClass().getName()); 59 } 60 /*** The visitor that actually adds the vertices to the graph. */ 61 private class LampLighter implements org.quilt.graph.Visitor, 62 org.apache.bcel.Constants, 63 org.apache.bcel.generic.InstructionConstants { 64 private ControlFlowGraph graph = null; 65 public LampLighter() {} 66 public void discoverGraph(Directed g) { 67 graph = (ControlFlowGraph)g; 68 } 69 public void discoverVertex(Vertex v) { 70 } 71 /*** 72 * Instrument edges inbound to code vertex. 73 */ 74 public void discoverEdge(Edge e) { 75 Vertex source = e.getSource(); 76 Vertex target = e.getTarget(); 77 ControlFlowGraph srcGraph = (ControlFlowGraph)source.getGraph(); 78 ControlFlowGraph tgtGraph = (ControlFlowGraph)target.getGraph(); 79 // DEBUG 80 if (tgtGraph != graph) { 81 System.out.println("GraphAction.discoverEdge:\n" 82 + " current graph is " + graph.getIndex() 83 + " but edge is " + e); 84 } 85 // END 86 boolean addingCounter = true; 87 if ( (target instanceof CodeVertex) 88 && !(target instanceof CounterVertex) 89 && !(source instanceof CounterVertex) ) { 90 Instruction srcConnInst = null; 91 if (source instanceof CodeVertex) { 92 srcConnInst = ((CodeVertex)source).getConnInst(); 93 if (srcConnInst != null 94 && srcConnInst instanceof GotoInstruction 95 && (source.getGraph() != tgtGraph)) { 96 // Don't add a counter if the goto jumps out of 97 // this graph. XXX needs more thought! -- this 98 // eliminates some test failures but will fail to 99 // count some statement hits 100 addingCounter = false; 101 } 102 } 103 // XXX A BIT OF A KLUDGE (NestedTryBlocks bugfix) 104 if (srcGraph != graph) { 105 System.out.println("GraphAction.discoverEdge WARNING: " 106 + "graph index " + graph.getIndex() 107 + "\n but edge is " + e 108 + " - not adding counter"); 109 addingCounter = false; 110 } 111 if (addingCounter) { 112 CounterVertex cv; 113 if (source instanceof Exit) { 114 // MOVED UP 115 // ControlFlowGraph tgtGraph 116 // = (ControlFlowGraph)target.getGraph(); 117 cv = (CounterVertex) tgtGraph.insertCodeVertex( 118 (CodeVertex)new CounterVertex(tgtGraph), e); 119 120 } else { 121 cv = (CounterVertex) graph.insertCodeVertex( 122 (CodeVertex)new CounterVertex(graph), e); 123 } 124 InstructionList ilist = cv.getInstructionList(); 125 InstructionHandle ih = ilist.append ( 126 factory_.createFieldAccess(clazz_.getClassName(), "q$$q", 127 new ArrayType(Type.INT,1), Constants.GETSTATIC)); 128 ilist.append(new PUSH(cpGen_, counterCount++)); 129 ilist.append(InstructionConstants.DUP2); 130 ilist.append(InstructionConstants.IALOAD); 131 ilist.append(new PUSH(cpGen_, 1)); 132 ilist.append(InstructionConstants.IADD); 133 ilist.append(InstructionConstants.IASTORE); 134 // end instruction list /////////////////// 135 136 // RETARGETING ////////////////////////////////////// 137 if (source instanceof CodeVertex) { 138 if (srcConnInst != null) { 139 // UNARY //////////////////////////////////// 140 141 // BINARY /////////////////////////////////// 142 if (srcConnInst instanceof GotoInstruction) { 143 if (!( e == source.getEdge() )) { 144 ((CodeVertex)source).moveGoto(cv); 145 } 146 } else if (srcConnInst instanceof IfInstruction 147 || srcConnInst instanceof JsrInstruction ) { 148 Edge otherEdge 149 = ((BinaryConnector)source.getConnector()) 150 .getOtherEdge(); 151 if (e == otherEdge) { 152 // this is the 'else' branch; the 153 // counter needs to have a Goto 154 // connecting instruction 155 BranchInstruction bi 156 = (BranchInstruction) srcConnInst; 157 InstructionHandle targ = bi.getTarget(); 158 bi.setTarget(ih); 159 cv.setConnInst( new GOTO (targ) ); 160 // ignore the edge returned 161 cv.makeBinary(); 162 BinaryConnector bc = (BinaryConnector) 163 cv.getConnector(); 164 Vertex myTarget = bc.getTarget(); 165 // main edge is the flow-through exit 166 // DEBUG 167 if (graph.getExit() == null) { 168 System.out.println( 169 "GRAPH HAS NULL EXIT"); 170 } 171 // END 172 bc.setTarget(graph.getExit()); 173 bc.setOtherTarget(myTarget); 174 } 175 } 176 // COMPLEX - Select ///////////////////////// 177 178 } // if srcConnInst != null 179 } 180 } // GEEP 181 // ELSE IF ENTRY ... //////////////////////////////// 182 } 183 } 184 public void finishEdge(Edge e) { 185 } 186 public void finishVertex(Vertex v) { 187 } 188 public void finishGraph(Directed g) { 189 } 190 } 191 // Apply the transformation to the graph. 192 public void xform (final ClassGen cg, final MethodGen method, 193 final ControlFlowGraph cfg) { 194 clazz_ = cg; 195 method_ = method; 196 cpGen_ = cg.getConstantPool() ; 197 factory_ = new InstructionFactory (clazz_, cpGen_); 198 199 String className = clazz_.getClassName(); 200 Ephemera eph = stmtReg.getEphemera(className); 201 // DEBUG 202 if (eph == null) 203 System.out.println("GraphAction.xform: eph is null!"); 204 // END 205 counterCount = eph.getCounterCount(); 206 207 int cfgSize = cfg.size(); 208 Walker walker = new Walker(); 209 walker.visit(cfg, new LampLighter()); 210 211 // unnecessary, I think, because the ConstantPoolGen is part 212 // of the ClassGen 213 // clazz_.setConstantPool(cpGen_.getFinalConstantPool()); 214 215 eph.setEndCount(method.getName(), counterCount); 216 217 218 } 219 // GET/SET METHODS ////////////////////////////////////////////// 220 /*** Get the name for the transformation. */ 221 public static String getName() { 222 return name_; 223 } 224 /*** 225 * Set a name for the transformation, to allow reports to refer 226 * to it. 227 */ 228 public static void setName(String name) { 229 name_ = name; 230 } 231 }

This page was automatically generated by Maven