KickJava   Java API By Example, From Geeks To Geeks.

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


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.io.DataOutputStream JavaDoc;
20 import java.io.IOException JavaDoc;
21 import org.apache.bcel.util.ByteSequence;
22
23 /**
24  * Abstract super class for branching instructions like GOTO, IFEQ, etc..
25  * Branch instructions may have a variable length, namely GOTO, JSR,
26  * LOOKUPSWITCH and TABLESWITCH.
27  *
28  * @see InstructionList
29  * @version $Id: BranchInstruction.java 386056 2006-03-15 11:31:56Z tcurdt $
30  * @author <A HREF="mailto:m.dahm@gmx.de">M. Dahm</A>
31  */

32 public abstract class BranchInstruction extends Instruction implements InstructionTargeter {
33
34     protected int index; // Branch target relative to this instruction
35
protected InstructionHandle target; // Target object in instruction list
36
protected int position; // Byte code offset
37

38
39     /**
40      * Empty constructor needed for the Class.newInstance() statement in
41      * Instruction.readInstruction(). Not to be used otherwise.
42      */

43     BranchInstruction() {
44     }
45
46
47     /** Common super constructor
48      * @param opcode Instruction opcode
49      * @param target instruction to branch to
50      */

51     protected BranchInstruction(short opcode, InstructionHandle target) {
52         super(opcode, (short) 3);
53         setTarget(target);
54     }
55
56
57     /**
58      * Dump instruction as byte code to stream out.
59      * @param out Output stream
60      */

61     public void dump( DataOutputStream JavaDoc out ) throws IOException JavaDoc {
62         out.writeByte(opcode);
63         index = getTargetOffset();
64         if (Math.abs(index) >= 32767) {
65             throw new ClassGenException("Branch target offset too large for short");
66         }
67         out.writeShort(index); // May be negative, i.e., point backwards
68
}
69
70
71     /**
72      * @param _target branch target
73      * @return the offset to `target' relative to this instruction
74      */

75     protected int getTargetOffset( InstructionHandle _target ) {
76         if (_target == null) {
77             throw new ClassGenException("Target of " + super.toString(true)
78                     + " is invalid null handle");
79         }
80         int t = _target.getPosition();
81         if (t < 0) {
82             throw new ClassGenException("Invalid branch target position offset for "
83                     + super.toString(true) + ":" + t + ":" + _target);
84         }
85         return t - position;
86     }
87
88
89     /**
90      * @return the offset to this instruction's target
91      */

92     protected int getTargetOffset() {
93         return getTargetOffset(target);
94     }
95
96
97     /**
98      * Called by InstructionList.setPositions when setting the position for every
99      * instruction. In the presence of variable length instructions `setPositions'
100      * performs multiple passes over the instruction list to calculate the
101      * correct (byte) positions and offsets by calling this function.
102      *
103      * @param offset additional offset caused by preceding (variable length) instructions
104      * @param max_offset the maximum offset that may be caused by these instructions
105      * @return additional offset caused by possible change of this instruction's length
106      */

107     protected int updatePosition( int offset, int max_offset ) {
108         position += offset;
109         return 0;
110     }
111
112
113     /**
114      * Long output format:
115      *
116      * &lt;position in byte code&gt;
117      * &lt;name of opcode&gt; "["&lt;opcode number&gt;"]"
118      * "("&lt;length of instruction&gt;")"
119      * "&lt;"&lt;target instruction&gt;"&gt;" "@"&lt;branch target offset&gt;
120      *
121      * @param verbose long/short format switch
122      * @return mnemonic for instruction
123      */

124     public String JavaDoc toString( boolean verbose ) {
125         String JavaDoc s = super.toString(verbose);
126         String JavaDoc t = "null";
127         if (verbose) {
128             if (target != null) {
129                 if (target.getInstruction() == this) {
130                     t = "<points to itself>";
131                 } else if (target.getInstruction() == null) {
132                     t = "<null instruction!!!?>";
133                 } else {
134                     t = target.getInstruction().toString(false); // Avoid circles
135
}
136             }
137         } else {
138             if (target != null) {
139                 index = getTargetOffset();
140                 t = "" + (index + position);
141             }
142         }
143         return s + " -> " + t;
144     }
145
146
147     /**
148      * Read needed data (e.g. index) from file. Conversion to a InstructionHandle
149      * is done in InstructionList(byte[]).
150      *
151      * @param bytes input stream
152      * @param wide wide prefix?
153      * @see InstructionList
154      */

155     protected void initFromFile( ByteSequence bytes, boolean wide ) throws IOException JavaDoc {
156         length = 3;
157         index = bytes.readShort();
158     }
159
160
161     /**
162      * @return target offset in byte code
163      */

164     public final int getIndex() {
165         return index;
166     }
167
168
169     /**
170      * @return target of branch instruction
171      */

172     public InstructionHandle getTarget() {
173         return target;
174     }
175
176
177     /**
178      * Set branch target
179      * @param target branch target
180      */

181     public void setTarget( InstructionHandle target ) {
182         notifyTarget(this.target, target, this);
183         this.target = target;
184     }
185
186
187     /**
188      * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen
189      */

190     static final void notifyTarget( InstructionHandle old_ih, InstructionHandle new_ih,
191             InstructionTargeter t ) {
192         if (old_ih != null) {
193             old_ih.removeTargeter(t);
194         }
195         if (new_ih != null) {
196             new_ih.addTargeter(t);
197         }
198     }
199
200
201     /**
202      * @param old_ih old target
203      * @param new_ih new target
204      */

205     public void updateTarget( InstructionHandle old_ih, InstructionHandle new_ih ) {
206         if (target == old_ih) {
207             setTarget(new_ih);
208         } else {
209             throw new ClassGenException("Not targeting " + old_ih + ", but " + target);
210         }
211     }
212
213
214     /**
215      * @return true, if ih is target of this instruction
216      */

217     public boolean containsTarget( InstructionHandle ih ) {
218         return (target == ih);
219     }
220
221
222     /**
223      * Inform target that it's not targeted anymore.
224      */

225     void dispose() {
226         setTarget(null);
227         index = -1;
228         position = -1;
229     }
230 }
231
Popular Tags