1 /* CodeVertex.java */
2 package org.quilt.cl;
3
4 import org.quilt.graph.*;
5 import org.apache.bcel.generic.GotoInstruction;
6 import org.apache.bcel.generic.Instruction;
7 import org.apache.bcel.generic.InstructionHandle;
8 import org.apache.bcel.generic.InstructionList;
9
10 /***
11 * A Vertex extended to carry the initial bytecode offset, line
12 * number, and an instruction list.
13 *
14 * @author <a href="mailto:jddixon@users.sourceforge.net">Jim Dixon</a>
15 */
16 public class CodeVertex extends Vertex {
17 /*** initial offset of first instruction in bytecode */
18 protected int pos = -1;
19
20 /*** the bytecode iteself */
21 protected InstructionList ilist = new InstructionList();
22
23 /***
24 * Line number in source code corresponding to first instruction,
25 * or if there is no such instruction, of the connecting instruction.
26 */
27 protected int startLine_ = -1;
28
29 /***
30 * Line number in source code corresponding to the connecting
31 * instruction, or if there is no such instruction, to the last
32 * instruction in the block
33 */
34 protected int endLine_ = -1;
35
36 /*** Instruction connecting this vertex to other(s). */
37 protected Instruction connInst_ = null;
38
39 /***
40 * Create a code vertex with default bytecode offset, line number,
41 * empty instruction list, and no label.
42 *
43 * @param g Graph which the vertex belongs to.
44 */
45 public CodeVertex (ControlFlowGraph g) {
46 super(g);
47 }
48 /*** Create a code vertex, specifying a non-negative bytecode offset.
49 *
50 * @param g Graph which the vertex belongs to.
51 * @param position Offset of the first instruction in the bytecode.
52 */
53 public CodeVertex (ControlFlowGraph g, int position) {
54 super(g);
55 if (position < 0) {
56 throw new IllegalArgumentException(
57 "position cannot be negative");
58 }
59 pos = position;
60 }
61 /***
62 * Create a code vertex, specifying a label
63 *
64 * @param g Graph which the vertex belongs to.
65 * @param l The String label applied to the vertex.
66 */
67 public CodeVertex (ControlFlowGraph g, String l) {
68 super(g);
69 pos = -1;
70 label_ = l;
71 }
72 // GET/SET METHODS //////////////////////////////////////////////
73 /*** Get connecting instruction. */
74 public Instruction getConnInst() {
75 return connInst_;
76 }
77 /*** Set the connecting instruction for this vertex. */
78 public void setConnInst (Instruction i) {
79 if (i == null) {
80 throw new IllegalArgumentException ("null instruction");
81 }
82 connInst_ = i;
83 }
84 // /*** Set the connecting instruction to null. */
85 // public void clearConnInst () {
86 // connInst_ = null;
87 // }
88 /***
89 * Get a reference to the InstructionList carried by the vertex.
90 * This is a doubly indirect reference to the first instruction
91 * in the list.
92 *
93 * @return Instruction list.
94 */
95 public InstructionList getInstructionList() {
96 return ilist;
97 }
98 /***
99 * Get the source code line number of the first instruction in a
100 * code vertex.
101 *
102 * @return Non-negative integer or -1, meaning no line number assigned.
103 */
104 public int getStartLine () {
105 return startLine_;
106 }
107 /***
108 * Set the source code line number.
109 * @param n Source code line number.
110 */
111 public void setStartLine(int n) {
112 startLine_ = n;
113 }
114 /***
115 * Get the line number in source code corresponding to the
116 * connecting instruction or last instruction in the block.
117 */
118 public int getEndLine() {
119 return endLine_;
120 }
121 /***
122 * Set the source line number of the connecting instruction, or of
123 * the last line number in the block if there is no connecting
124 * instruction.
125 *
126 * @param n Source code end line number.
127 */
128 public void setEndLine(int n) {
129 endLine_ = n;
130 }
131 /***
132 * Get the bytecode offset of the first instruction.
133 *
134 * @return The initial bytecode offset of the first instruction
135 * carried by the vertex (excluding any connection instruction.
136 */
137 public int getPosition () {
138 return pos;
139 }
140 /***
141 * Set the bytecode offset for the first instruction.
142 *
143 * XXX Should rename this to <code>setPosition</code> to match the
144 * <code>get</code> method.
145 *
146 * @param position A non-negative integer representing the bytecode
147 * position of the first instruction.
148 */
149 public void setPos (int position) {
150 if (position < 0) {
151 throw new IllegalArgumentException(
152 "position cannot be negative");
153 }
154 pos = position;
155 }
156 // OTHER METHODS ////////////////////////////////////////////////
157 /***
158 * Move this code vertex's Goto to another code vertex. The
159 * second vertex will be the target on the otherEdge from this
160 * vertex. This vertex has a BinaryConnector. The second vertex
161 * has a UnaryConnector.
162 *
163 * The goto instruction does NOT point to the target. The target
164 * is some sort of instrumentation being inserted into the graph.
165 */
166 public void moveGoto (final CodeVertex target) {
167 if (target == null) {
168 throw new IllegalArgumentException("null target vertex");
169 }
170 // this vertex's binary connector
171 BinaryConnector biConnector = (BinaryConnector)getConnector();
172 Edge flowEdge = biConnector.getEdge();
173 Edge otherEdge = biConnector.getOtherEdge(); // used by goto
174
175 if (otherEdge.getTarget() != target) {
176 throw new IllegalArgumentException("not target of otherEdge");
177 }
178 if (! (connInst_ instanceof GotoInstruction) ) {
179 throw new IllegalArgumentException(
180 "connecting instruction not goto");
181 }
182 // the target vertex's unary connector
183 UnaryConnector uConnector = (UnaryConnector)target.getConnector();
184 Edge uEdge = uConnector.getEdge();
185 Vertex tgtTarget = uEdge.getTarget();
186
187 // // DEBUG
188 // System.out.println("CodeVertex.moveGoto:"
189 // + "\n source: " + toString()
190 // + "\n edge: " + flowEdge
191 // + "\n other edge: " + otherEdge
192 // + "\n target: " + target
193 // + "\n edge: " + uEdge
194 // );
195 // // END
196
197 // change the unary connector and move it to this vertex
198 uEdge.setSource(this);
199 uEdge.setTarget(target);
200 setConnector(uConnector);
201
202 // change the binary connector and attach it to the target
203 flowEdge.setSource(target);
204 // flow target is unchanged
205 otherEdge.setSource(target);
206 otherEdge.setTarget(tgtTarget);
207 target.setConnector(biConnector);
208
209 // move the connecting instruction, a goto
210 target.setConnInst (connInst_); // move it to the target
211 connInst_ = null; // erase from this vertex
212
213 // // DEBUG
214 // System.out.println("CodeVertex.moveGoto:"
215 // + "\n source: " + toString()
216 // + "\n edge " + getEdge()
217 // + "\n target: " + target
218 // + "\n edge " + flowEdge
219 // + "\n other edge " + otherEdge );
220 // // END
221 }
222 /***
223 * Less verbose <code>toString.</code>
224 *
225 * @return Graph index and Vertex index in a neatly formatted String,
226 * *not* newline-terminated.
227 */
228 public String toString () {
229 StringBuffer sb = new StringBuffer().append("Code ")
230 .append(super.toString()).append(" pos ") .append(pos);
231
232 // may look a bit strange if there is an end line but no start line
233 if (startLine_ > -1) {
234 sb.append(" line ").append(startLine_);
235 }
236 if (endLine_ > -1) {
237 sb.append("/").append(endLine_);
238 }
239 return sb.toString();
240 }
241 /***
242 * Optionally more verbose method.
243 *
244 * @param b If true, add label (if any) and instruction list.
245 * @return A neatly formatted String.
246 */
247 public String toString (boolean b) {
248
249 StringBuffer sb = new StringBuffer().append(toString());
250 if (b) {
251 if (label_ != null) {
252 sb.append ("\n label ") .append(label_);
253 }
254 sb.append("\n ilist: ");
255 InstructionHandle ih = ilist.getStart();
256 while ( ih != null) {
257 sb.append(ih.getInstruction());
258 }
259 }
260 return sb.toString();
261 }
262 }
This page was automatically generated by Maven