KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > quilt > cover > stmt > GraphAction


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 JavaDoc 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 JavaDoc("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 JavaDoc 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 JavaDoc 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 JavaDoc name) {
229         name_ = name;
230     }
231 }
232
Popular Tags