76
77 /**
78 * Empty constructor needed for the Class.newInstance() statement in
79 * Instruction.readInstruction(). Not to be used otherwise.
80 */
81 BranchInstruction() {}
82
83 /** Common super constructor
84 * @param opcodee Instruction opcode
85 * @param target instruction to branch to
86 */
87 protected BranchInstruction(short opcode, InstructionHandle target) {
88 super(opcode, (short)3);
89 setTarget(target);
90 }
91
92 /**
93 * Dump instruction as byte code to stream out.
94 * @param out Output stream
95 */
96 public void dump(DataOutputStream out) throws IOException {
97 out.writeByte(opcode);
98
99 index = getTargetOffset();
100
101 if(Math.abs(index) >= 32767) // too large for short
102 throw new ClassGenException("Branch target offset too large for short");
103
104 out.writeShort(index); // May be negative, i.e., point backwards
105 }
106
107 /**
108 * @param target branch target
109 * @return the offset to `target' relative to this instruction
110 */
111 protected int getTargetOffset(InstructionHandle target) {
112 if(target == null)
113 throw new ClassGenException("Target of " + super.toString(true) +
114 " is invalid null handle");
115
136 * @param offset additional offset caused by preceding (variable length) instructions
137 * @param max_offset the maximum offset that may be caused by these instructions
138 * @return additional offset caused by possible change of this instruction's length
139 */
140 protected int updatePosition(int offset, int max_offset) {
141 position += offset;
142 return 0;
143 }
144
145 /**
146 * Long output format:
147 *
148 * <position in byte code>
149 * <name of opcode> "["<opcode number>"]"
150 * "("<length of instruction>")"
151 * "<"<target instruction>">" "@"<branch target offset>
152 *
153 * @param verbose long/short format switch
154 * @return mnemonic for instruction
155 */
156 public String toString(boolean verbose) {
157 String s = super.toString(verbose);
158 String t = "null";
159
160 if(verbose) {
161 if(target != null) {
162 if(target.getInstruction() == this)
163 t = "<points to itself>";
164 else if(target.getInstruction() == null)
165 t = "<null instruction!!!?>";
166 else
167 t = target.getInstruction().toString(false); // Avoid circles
168 }
169 } else {
170 if(target != null) {
171 index = getTargetOffset();
172 t = "" + (index + position);
173 }
174 }
175
176 return s + " -> " + t;
177 }
178
179 /**
180 * Read needed data (e.g. index) from file. Conversion to a InstructionHandle
181 * is done in InstructionList(byte[]).
182 *
183 * @param bytes input stream
184 * @param wide wide prefix?
185 * @see InstructionList
186 */
187 protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
188 {
189 length = 3;
190 index = bytes.readShort();
191 }
192
193 /**
194 * @return target offset in byte code
195 */
196 public final int getIndex() { return index; }
197
198 /**
199 * @return target of branch instruction
200 */
201 public InstructionHandle getTarget() { return target; }
202
203 /**
204 * Set branch target
205 * @param target branch target
206 */
207 public void setTarget(InstructionHandle target) {
208 notifyTarget(this.target, target, this);
209 this.target = target;
210 }
211
212 /**
213 * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen
214 */
215 static final void notifyTarget(InstructionHandle old_ih, InstructionHandle new_ih,
216 InstructionTargeter t) {
217 if(old_ih != null)
218 old_ih.removeTargeter(t);
219 if(new_ih != null)
220 new_ih.addTargeter(t);
221 }
222
223 /**
224 * @param old_ih old target
225 * @param new_ih new target
226 */
227 public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
228 if(target == old_ih)
229 setTarget(new_ih);
230 else
231 throw new ClassGenException("Not targeting " + old_ih + ", but " + target);
232 }
233
234 /**
235 * @return true, if ih is target of this instruction
236 */
237 public boolean containsTarget(InstructionHandle ih) {
238 return (target == ih);
239 }
240
241 /**
242 * Inform target that it's not targeted anymore.
243 */
244 void dispose() {
245 setTarget(null);
246 index=-1;
247 position=-1;
248 }
249 }
|
76
77 /**
78 * Empty constructor needed for the Class.newInstance() statement in
79 * Instruction.readInstruction(). Not to be used otherwise.
80 */
81 BranchInstruction() {}
82
83 /** Common super constructor
84 * @param opcodee Instruction opcode
85 * @param target instruction to branch to
86 */
87 protected BranchInstruction(short opcode, InstructionHandle target) {
88 super(opcode, (short)3);
89 setTarget(target);
90 }
91
92 /**
93 * Dump instruction as byte code to stream out.
94 * @param out Output stream
95 */
96 @Override
97 public void dump(DataOutputStream out) throws IOException {
98 out.writeByte(opcode);
99
100 index = getTargetOffset();
101
102 if(Math.abs(index) >= 32767) // too large for short
103 throw new ClassGenException("Branch target offset too large for short");
104
105 out.writeShort(index); // May be negative, i.e., point backwards
106 }
107
108 /**
109 * @param target branch target
110 * @return the offset to `target' relative to this instruction
111 */
112 protected int getTargetOffset(InstructionHandle target) {
113 if(target == null)
114 throw new ClassGenException("Target of " + super.toString(true) +
115 " is invalid null handle");
116
137 * @param offset additional offset caused by preceding (variable length) instructions
138 * @param max_offset the maximum offset that may be caused by these instructions
139 * @return additional offset caused by possible change of this instruction's length
140 */
141 protected int updatePosition(int offset, int max_offset) {
142 position += offset;
143 return 0;
144 }
145
146 /**
147 * Long output format:
148 *
149 * <position in byte code>
150 * <name of opcode> "["<opcode number>"]"
151 * "("<length of instruction>")"
152 * "<"<target instruction>">" "@"<branch target offset>
153 *
154 * @param verbose long/short format switch
155 * @return mnemonic for instruction
156 */
157 @Override
158 public String toString(boolean verbose) {
159 String s = super.toString(verbose);
160 String t = "null";
161
162 if(verbose) {
163 if(target != null) {
164 if(target.getInstruction() == this)
165 t = "<points to itself>";
166 else if(target.getInstruction() == null)
167 t = "<null instruction!!!?>";
168 else
169 t = target.getInstruction().toString(false); // Avoid circles
170 }
171 } else {
172 if(target != null) {
173 index = getTargetOffset();
174 t = "" + (index + position);
175 }
176 }
177
178 return s + " -> " + t;
179 }
180
181 /**
182 * Read needed data (e.g. index) from file. Conversion to a InstructionHandle
183 * is done in InstructionList(byte[]).
184 *
185 * @param bytes input stream
186 * @param wide wide prefix?
187 * @see InstructionList
188 */
189 @Override
190 protected void initFromFile(ByteSequence bytes, boolean wide) throws IOException
191 {
192 length = 3;
193 index = bytes.readShort();
194 }
195
196 /**
197 * @return target offset in byte code
198 */
199 public final int getIndex() { return index; }
200
201 /**
202 * @return target of branch instruction
203 */
204 public InstructionHandle getTarget() { return target; }
205
206 /**
207 * Set branch target
208 * @param target branch target
209 */
210 public final void setTarget(InstructionHandle target) {
211 notifyTargetChanging(this.target, this);
212 this.target = target;
213 notifyTargetChanged(this.target, this);
214 }
215
216 /**
217 * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen.
218 * Must be called before the target is actually changed in the
219 * InstructionTargeter.
220 */
221 static void notifyTargetChanging(InstructionHandle old_ih,
222 InstructionTargeter t) {
223 if(old_ih != null) {
224 old_ih.removeTargeter(t);
225 }
226 }
227
228 /**
229 * Used by BranchInstruction, LocalVariableGen, CodeExceptionGen.
230 * Must be called after the target is actually changed in the
231 * InstructionTargeter.
232 */
233 static void notifyTargetChanged(InstructionHandle new_ih,
234 InstructionTargeter t) {
235 if(new_ih != null) {
236 new_ih.addTargeter(t);
237 }
238 }
239
240 /**
241 * @param old_ih old target
242 * @param new_ih new target
243 */
244 @Override
245 public void updateTarget(InstructionHandle old_ih, InstructionHandle new_ih) {
246 if(target == old_ih)
247 setTarget(new_ih);
248 else
249 throw new ClassGenException("Not targeting " + old_ih + ", but " + target);
250 }
251
252 /**
253 * @return true, if ih is target of this instruction
254 */
255 @Override
256 public boolean containsTarget(InstructionHandle ih) {
257 return (target == ih);
258 }
259
260 /**
261 * Inform target that it's not targeted anymore.
262 */
263 @Override
264 void dispose() {
265 setTarget(null);
266 index=-1;
267 position=-1;
268 }
269 }
|