1 package serp.bytecode;
2
3 import java.io.*;
4 import java.util.*;
5
6
7
8
9
10
11
12 public abstract class SwitchInstruction extends JumpInstruction {
13 private List _cases = new LinkedList();
14
15 public SwitchInstruction(Code owner, int opcode) {
16 super(owner, opcode);
17 }
18
19
20
21
22
23 public int[] getOffsets() {
24 int bi = getByteIndex();
25 int[] offsets = new int[_cases.size()];
26 for (int i = 0; i < offsets.length; i++)
27 offsets[i] = ((InstructionPtrStrategy) _cases.get(i)).getByteIndex()
28 - bi;
29 return offsets;
30 }
31
32
33
34
35
36
37
38
39
40
41 public void setOffsets(int[] offsets) {
42 int bi = getByteIndex();
43 _cases.clear();
44 for (int i = 0; i < offsets.length; i++) {
45 InstructionPtrStrategy next = new InstructionPtrStrategy(this);
46 next.setByteIndex(offsets[i] + bi);
47 _cases.add(next);
48 }
49 }
50
51 public int countTargets() {
52 return _cases.size();
53 }
54
55 int getLength() {
56
57
58 int length = 1;
59
60
61
62 int byteIndex = getByteIndex() + 1;
63 for (; (byteIndex % 4) != 0; byteIndex++, length++);
64 return length;
65 }
66
67
68
69
70 public Instruction getDefaultTarget() {
71 return getTarget();
72 }
73
74
75
76
77 public int getDefaultOffset() {
78 return getOffset();
79 }
80
81
82
83
84 public SwitchInstruction setDefaultOffset(int offset) {
85 setOffset(offset);
86 return this;
87 }
88
89
90
91
92 public SwitchInstruction setDefaultTarget(Instruction ins) {
93 return (SwitchInstruction) setTarget(ins);
94 }
95
96
97
98
99 public Instruction[] getTargets() {
100 Instruction[] result = new Instruction[_cases.size()];
101 for (int i = 0; i < _cases.size(); i++)
102 result[i] = ((InstructionPtrStrategy) _cases.get(i)).
103 getTargetInstruction();
104 return result;
105 }
106
107
108
109
110
111
112 public SwitchInstruction setTargets(Instruction[] targets) {
113 _cases.clear();
114 if (targets != null)
115 for (int i = 0; i < targets.length; i++)
116 addTarget(targets[i]);
117 return this;
118 }
119
120
121
122
123
124
125 public SwitchInstruction addTarget(Instruction target) {
126 _cases.add(new InstructionPtrStrategy(this, target));
127 return this;
128 }
129
130 public int getStackChange() {
131 return -1;
132 }
133
134 public void updateTargets() {
135 super.updateTargets();
136 for (Iterator itr = _cases.iterator(); itr.hasNext();)
137 ((InstructionPtrStrategy) itr.next()).updateTargets();
138 }
139
140 public void replaceTarget(Instruction oldTarget, Instruction newTarget) {
141 super.replaceTarget(oldTarget, newTarget);
142 for (Iterator itr = _cases.iterator(); itr.hasNext();)
143 ((InstructionPtrStrategy) itr.next()).replaceTarget(oldTarget,
144 newTarget);
145 }
146
147 void read(Instruction orig) {
148 super.read(orig);
149
150 SwitchInstruction ins = (SwitchInstruction) orig;
151 _cases.clear();
152 InstructionPtrStrategy incoming;
153 for (Iterator itr = ins._cases.iterator(); itr.hasNext();) {
154 incoming = (InstructionPtrStrategy) itr.next();
155 InstructionPtrStrategy next = new InstructionPtrStrategy(this);
156 next.setByteIndex(incoming.getByteIndex());
157 _cases.add(next);
158 }
159 }
160
161 void clearTargets() {
162 _cases.clear();
163 }
164
165 void readTarget(DataInput in) throws IOException {
166 InstructionPtrStrategy next = new InstructionPtrStrategy(this);
167 next.setByteIndex(getByteIndex() + in.readInt());
168 _cases.add(next);
169 }
170
171
172
173
174
175
176 public SwitchInstruction setCases(int[] matches, Instruction[] targets) {
177 setMatches(matches);
178 setTargets(targets);
179 return this;
180 }
181
182 public SwitchInstruction setMatches(int[] matches) {
183 clearMatches();
184 for (int i = 0; i < matches.length; i++)
185 addMatch(matches[i]);
186 return this;
187 }
188
189
190
191
192
193
194 public SwitchInstruction addCase(int match, Instruction target) {
195 addMatch(match);
196 addTarget(target);
197 return this;
198 }
199
200 public abstract SwitchInstruction addMatch(int match);
201
202 public abstract int[] getMatches();
203
204 abstract void clearMatches();
205
206 void calculateOpcode() {
207 }
208 }