KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > bcel > generic > InstructionHandle


1 /*
2  * Copyright 2000-2004 The Apache Software Foundation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  *
16  */

17 package org.apache.bcel.generic;
18
19 import java.util.Collection JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Set JavaDoc;
24 import org.apache.bcel.classfile.Utility;
25
26 /**
27  * Instances of this class give users a handle to the instructions contained in
28  * an InstructionList. Instruction objects may be used more than once within a
29  * list, this is useful because it saves memory and may be much faster.
30  *
31  * Within an InstructionList an InstructionHandle object is wrapped
32  * around all instructions, i.e., it implements a cell in a
33  * doubly-linked list. From the outside only the next and the
34  * previous instruction (handle) are accessible. One
35  * can traverse the list via an Enumeration returned by
36  * InstructionList.elements().
37  *
38  * @version $Id: InstructionHandle.java 386056 2006-03-15 11:31:56Z tcurdt $
39  * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
40  * @see Instruction
41  * @see BranchHandle
42  * @see InstructionList
43  */

44 public class InstructionHandle implements java.io.Serializable JavaDoc {
45
46     InstructionHandle next, prev; // Will be set from the outside
47
Instruction instruction;
48     protected int i_position = -1; // byte code offset of instruction
49
private Set JavaDoc targeters;
50     private Map JavaDoc attributes;
51
52
53     public final InstructionHandle getNext() {
54         return next;
55     }
56
57
58     public final InstructionHandle getPrev() {
59         return prev;
60     }
61
62
63     public final Instruction getInstruction() {
64         return instruction;
65     }
66
67
68     /**
69      * Replace current instruction contained in this handle.
70      * Old instruction is disposed using Instruction.dispose().
71      */

72     public void setInstruction( Instruction i ) { // Overridden in BranchHandle
73
if (i == null) {
74             throw new ClassGenException("Assigning null to handle");
75         }
76         if ((this.getClass() != BranchHandle.class) && (i instanceof BranchInstruction)) {
77             throw new ClassGenException("Assigning branch instruction " + i + " to plain handle");
78         }
79         if (instruction != null) {
80             instruction.dispose();
81         }
82         instruction = i;
83     }
84
85
86     /**
87      * Temporarily swap the current instruction, without disturbing
88      * anything. Meant to be used by a debugger, implementing
89      * breakpoints. Current instruction is returned.
90      */

91     public Instruction swapInstruction( Instruction i ) {
92         Instruction oldInstruction = instruction;
93         instruction = i;
94         return oldInstruction;
95     }
96
97
98     /*private*/protected InstructionHandle(Instruction i) {
99         setInstruction(i);
100     }
101
102     private static InstructionHandle ih_list = null; // List of reusable handles
103

104
105     /** Factory method.
106      */

107     static final InstructionHandle getInstructionHandle( Instruction i ) {
108         if (ih_list == null) {
109             return new InstructionHandle(i);
110         } else {
111             InstructionHandle ih = ih_list;
112             ih_list = ih.next;
113             ih.setInstruction(i);
114             return ih;
115         }
116     }
117
118
119     /**
120      * Called by InstructionList.setPositions when setting the position for every
121      * instruction. In the presence of variable length instructions `setPositions()'
122      * performs multiple passes over the instruction list to calculate the
123      * correct (byte) positions and offsets by calling this function.
124      *
125      * @param offset additional offset caused by preceding (variable length) instructions
126      * @param max_offset the maximum offset that may be caused by these instructions
127      * @return additional offset caused by possible change of this instruction's length
128      */

129     protected int updatePosition( int offset, int max_offset ) {
130         i_position += offset;
131         return 0;
132     }
133
134
135     /** @return the position, i.e., the byte code offset of the contained
136      * instruction. This is accurate only after
137      * InstructionList.setPositions() has been called.
138      */

139     public int getPosition() {
140         return i_position;
141     }
142
143
144     /** Set the position, i.e., the byte code offset of the contained
145      * instruction.
146      */

147     void setPosition( int pos ) {
148         i_position = pos;
149     }
150
151
152     /** Overridden in BranchHandle
153      */

154     protected void addHandle() {
155         next = ih_list;
156         ih_list = this;
157     }
158
159
160     /**
161      * Delete contents, i.e., remove user access and make handle reusable.
162      */

163     void dispose() {
164         next = prev = null;
165         instruction.dispose();
166         instruction = null;
167         i_position = -1;
168         attributes = null;
169         removeAllTargeters();
170         addHandle();
171     }
172
173
174     /** Remove all targeters, if any.
175      */

176     public void removeAllTargeters() {
177         if (targeters != null) {
178             targeters.clear();
179         }
180     }
181
182
183     /**
184      * Denote this handle isn't referenced anymore by t.
185      */

186     public void removeTargeter( InstructionTargeter t ) {
187         if (targeters != null) {
188             targeters.remove(t);
189         }
190     }
191
192
193     /**
194      * Denote this handle is being referenced by t.
195      */

196     public void addTargeter( InstructionTargeter t ) {
197         if (targeters == null) {
198             targeters = new HashSet JavaDoc();
199         }
200         //if(!targeters.contains(t))
201
targeters.add(t);
202     }
203
204
205     public boolean hasTargeters() {
206         return (targeters != null) && (targeters.size() > 0);
207     }
208
209
210     /**
211      * @return null, if there are no targeters
212      */

213     public InstructionTargeter[] getTargeters() {
214         if (!hasTargeters()) {
215             return null;
216         }
217         InstructionTargeter[] t = new InstructionTargeter[targeters.size()];
218         targeters.toArray(t);
219         return t;
220     }
221
222
223     /** @return a (verbose) string representation of the contained instruction.
224      */

225     public String JavaDoc toString( boolean verbose ) {
226         return Utility.format(i_position, 4, false, ' ') + ": " + instruction.toString(verbose);
227     }
228
229
230     /** @return a string representation of the contained instruction.
231      */

232     public String JavaDoc toString() {
233         return toString(true);
234     }
235
236
237     /** Add an attribute to an instruction handle.
238      *
239      * @param key the key object to store/retrieve the attribute
240      * @param attr the attribute to associate with this handle
241      */

242     public void addAttribute( Object JavaDoc key, Object JavaDoc attr ) {
243         if (attributes == null) {
244             attributes = new HashMap JavaDoc(3);
245         }
246         attributes.put(key, attr);
247     }
248
249
250     /** Delete an attribute of an instruction handle.
251      *
252      * @param key the key object to retrieve the attribute
253      */

254     public void removeAttribute( Object JavaDoc key ) {
255         if (attributes != null) {
256             attributes.remove(key);
257         }
258     }
259
260
261     /** Get attribute of an instruction handle.
262      *
263      * @param key the key object to store/retrieve the attribute
264      */

265     public Object JavaDoc getAttribute( Object JavaDoc key ) {
266         if (attributes != null) {
267             return attributes.get(key);
268         }
269         return null;
270     }
271
272
273     /** @return all attributes associated with this handle
274      */

275     public Collection JavaDoc getAttributes() {
276         if (attributes == null) {
277             attributes = new HashMap JavaDoc(3);
278         }
279         return attributes.values();
280     }
281
282
283     /** Convenience method, simply calls accept() on the contained instruction.
284      *
285      * @param v Visitor object
286      */

287     public void accept( Visitor v ) {
288         instruction.accept(v);
289     }
290 }
291
Popular Tags