Source code: com/techtrader/modules/tools/bytecode/JumpInstruction.java
1 package com.techtrader.modules.tools.bytecode;
2
3
4 import java.util.List;
5 import java.util.Iterator;
6 import java.io.IOException;
7 import java.io.DataInput;
8 import java.io.DataOutput;
9
10 import com.techtrader.modules.tools.bytecode.visitor.BCVisitor;
11
12
13 /**
14 * Represents an IF, GOTO, JSR, or similar instruction that specifies as
15 * its argument a position in the code block to jump to.
16 *
17 * @author Abe White
18 */
19 public class JumpInstruction
20 extends Instruction
21 implements InstructionPtr
22 {
23 protected int _offset = 0;
24 protected Instruction _target = null;
25
26
27 protected JumpInstruction (Code owner, int opcode)
28 {
29 super (owner);
30 _opcode = opcode;
31 }
32
33
34 /**
35 * Set the byte offset for the jump instruction.
36 */
37 public void setOffset (int offset)
38 {
39 _offset = offset;
40 _target = null;
41 }
42
43
44 /**
45 * Get the byte offset for the jump instruction.
46 */
47 public int getOffset ()
48 {
49 if (_target != null)
50 return _target.getByteIndex () - getByteIndex ();
51
52 return _offset;
53 }
54
55
56 /**
57 * Set the instruction to jump to; the instruction must already be
58 * added to the code block. WARNING: if this instruction is later
59 * deleted from the code block, the results are undefined.
60 *
61 * @return this Instruction, for method chaining
62 */
63 public JumpInstruction setTarget (Instruction instruction)
64 {
65 _target = instruction;
66 return this;
67 }
68
69
70 /**
71 * Get the current target instruction to jump to, if it has been set.
72 * WARNING: if this instruction is later
73 * deleted from the code block, the results are undefined.
74 */
75 public Instruction getTarget ()
76 {
77 return _target;
78 }
79
80
81 public void setMarkers (List instructions)
82 {
83 int jumpByteIndex = getByteIndex () + _offset;
84
85 Instruction ins;
86 for (Iterator i = instructions.iterator (); i.hasNext ();)
87 {
88 ins = (Instruction) i.next ();
89
90 if (ins.getByteIndex () == jumpByteIndex)
91 {
92 setTarget (ins);
93 break;
94 }
95 }
96 }
97
98
99 /**
100 * JumpInstructions are equal if they represent the same operation and
101 * the Instruction they jump to is the
102 * same, or if the jump Instruction of either is unset.
103 */
104 public boolean equals (Object other)
105 {
106 if (this == other)
107 return true;
108 if (!(other instanceof JumpInstruction))
109 return false;
110 if (!super.equals (other))
111 return false;
112
113 Instruction target = ((JumpInstruction) other).getTarget ();
114 return (target == null || _target == null || target == _target);
115 }
116
117
118 public int getLength ()
119 {
120 switch (_opcode)
121 {
122 case GOTO_W:
123 case JSR_W:
124 return super.getLength () + 4;
125 default:
126 return super.getLength () + 2;
127 }
128 }
129
130
131 public int getStackChange ()
132 {
133 switch (_opcode)
134 {
135 case IF_ACMPEQ:
136 case IF_ACMPNE:
137 case IF_ICMPEQ:
138 case IF_ICMPNE:
139 case IF_ICMPLT:
140 case IF_ICMPGT:
141 case IF_ICMPLE:
142 case IF_ICMPGE:
143 return -2;
144
145 case IF_EQ:
146 case IF_NE:
147 case IF_LT:
148 case IF_GT:
149 case IF_LE:
150 case IF_GE:
151 case IF_NULL:
152 case IF_NONNULL:
153 return -1;
154
155 case JSR:
156 return 1;
157
158 default:
159 return 0;
160 }
161 }
162
163
164 protected void copy (Instruction orig)
165 {
166 super.copy (orig);
167 setOffset (((JumpInstruction) orig).getOffset ());
168 }
169
170
171 protected void readData (DataInput in)
172 throws IOException
173 {
174 switch (_opcode)
175 {
176 case GOTO_W:
177 case JSR_W:
178 _offset = in.readInt ();
179 break;
180 default:
181 _offset = in.readShort ();
182 }
183 }
184
185
186 protected void writeData (DataOutput out)
187 throws IOException
188 {
189 switch (_opcode)
190 {
191 case GOTO_W:
192 case JSR_W:
193 out.writeInt (getOffset ());
194 break;
195 default:
196 out.writeShort (getOffset ());
197 }
198 }
199
200
201 public void acceptVisit (BCVisitor visit)
202 {
203 visit.enterJumpInstruction (this);
204 visit.exitJumpInstruction (this);
205 }
206 }