1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.jdo.impl.enhancer.classfile;
19
20 import java.io.PrintStream;
21 import java.util.Stack;
22
23 /***
24 * Special instruction form for the opc_lookupswitch instruction
25 */
26 public class InsnLookupSwitch extends Insn {
27
28 private InsnTarget defaultOp;
29
30
31 private int[] matchesOp;
32
33
34
35 private InsnTarget[] targetsOp;
36
37
38
39 public int nStackArgs() {
40 return 1;
41 }
42
43 public int nStackResults() {
44 return 0;
45 }
46
47 /***
48 * What are the types of the stack operands ?
49 */
50 public String argTypes() {
51 return "I";
52 }
53
54 /***
55 * What are the types of the stack results?
56 */
57 public String resultTypes() {
58 return "";
59 }
60
61 public boolean branches() {
62 return true;
63 }
64
65 /***
66 * Mark possible branch targets
67 */
68 public void markTargets() {
69 defaultOp.setBranchTarget();
70 for (int i=0; i<targetsOp.length; i++)
71 targetsOp[i].setBranchTarget();
72 }
73
74
75 /***
76 * Return the defaultTarget for the switch
77 */
78 public InsnTarget defaultTarget() {
79 return defaultOp;
80 }
81
82 /***
83 * Return the case values of the switch.
84 */
85 public int[] switchCases() {
86 return matchesOp;
87 }
88
89 /***
90 * Return the targets for the cases of the switch.
91 */
92 public InsnTarget[] switchTargets() {
93 return targetsOp;
94 }
95
96 /***
97 * Constructor for opc_lookupswitch
98 */
99 public InsnLookupSwitch(InsnTarget defaultOp, int[] matchesOp,
100 InsnTarget[] targetsOp) {
101 this(defaultOp, matchesOp, targetsOp, NO_OFFSET);
102 }
103
104 /***
105 * Compares this instance with another for structural equality.
106 */
107
108 public boolean isEqual(Stack msg, Object obj) {
109 if (!(obj instanceof InsnLookupSwitch)) {
110 msg.push("obj/obj.getClass() = "
111 + (obj == null ? null : obj.getClass()));
112 msg.push("this.getClass() = "
113 + this.getClass());
114 return false;
115 }
116 InsnLookupSwitch other = (InsnLookupSwitch)obj;
117
118 if (!super.isEqual(msg, other)) {
119 return false;
120 }
121
122 if (!this.defaultOp.isEqual(msg, other.defaultOp)) {
123 msg.push(String.valueOf("defaultOp = "
124 + other.defaultOp));
125 msg.push(String.valueOf("defaultOp = "
126 + this.defaultOp));
127 return false;
128 }
129
130 if (this.matchesOp.length != other.matchesOp.length) {
131 msg.push("matchesOp.length "
132 + String.valueOf(other.matchesOp.length));
133 msg.push("matchesOp.length "
134 + String.valueOf(this.matchesOp.length));
135 return false;
136 }
137 for (int i = 0; i < matchesOp.length; i++) {
138 int m1 = this.matchesOp[i];
139 int m2 = other.matchesOp[i];
140 if (m1 != m2) {
141 msg.push("matchesOp[" + i + "] = " + String.valueOf(m2));
142 msg.push("matchesOp[" + i + "] = " + String.valueOf(m1));
143 return false;
144 }
145 }
146
147 if (this.targetsOp.length != other.targetsOp.length) {
148 msg.push("targetsOp.length "
149 + String.valueOf(other.targetsOp.length));
150 msg.push("targetsOp.length "
151 + String.valueOf(this.targetsOp.length));
152 return false;
153 }
154 for (int i = 0; i < targetsOp.length; i++) {
155 InsnTarget t1 = this.targetsOp[i];
156 InsnTarget t2 = other.targetsOp[i];
157 if (!t1.isEqual(msg, t2)) {
158 msg.push("targetsOp[" + i + "] = " + String.valueOf(t2));
159 msg.push("targetsOp[" + i + "] = " + String.valueOf(t1));
160 return false;
161 }
162 }
163 return true;
164 }
165
166 /* package local methods *//package-summary/html">class="comment"> package local methods *//package-summary.html">
167
168 InsnLookupSwitch(InsnTarget defaultOp, int[] matchesOp,
169 InsnTarget[] targetsOp, int offset) {
170 super(opc_lookupswitch, offset);
171
172 this.defaultOp = defaultOp;
173 this.matchesOp = matchesOp;
174 this.targetsOp = targetsOp;
175
176 if (defaultOp == null || targetsOp == null || matchesOp == null ||
177 targetsOp.length != matchesOp.length)
178 throw new InsnError ("attempt to create an opc_lookupswitch" +
179 " with invalid operands");
180 }
181
182 void print(PrintStream out, int indent) {
183 ClassPrint.spaces(out, indent);
184 out.println(offset() + " opc_lookupswitch ");
185 for (int i=0; i<matchesOp.length; i++) {
186 ClassPrint.spaces(out, indent+2);
187 out.println(matchesOp[i] + " -> " + targetsOp[i].offset());
188 }
189 ClassPrint.spaces(out, indent+2);
190 out.println("default -> " + defaultOp.offset());
191 }
192
193 int store(byte[] buf, int index) {
194 buf[index++] = (byte) opcode();
195 index = (index + 3) & ~3;
196 index = storeInt(buf, index, defaultOp.offset() - offset());
197 index = storeInt(buf, index, targetsOp.length);
198 for (int i=0; i<targetsOp.length; i++) {
199 index = storeInt(buf, index, matchesOp[i]);
200 index = storeInt(buf, index, targetsOp[i].offset() - offset());
201 }
202 return index;
203 }
204
205 int size() {
206
207 int basic = ((offset() + 4) & ~3) - offset() + 8;
208
209 return basic + targetsOp.length*8;
210 }
211
212 static InsnLookupSwitch read (InsnReadEnv insnEnv, int myPC) {
213
214 int thisPC = myPC +1;
215 for (int pads = ((thisPC + 3) & ~3) - thisPC; pads > 0; pads--)
216 insnEnv.getByte();
217 InsnTarget defaultTarget = insnEnv.getTarget(insnEnv.getInt() + myPC);
218 int npairs = insnEnv.getInt();
219 int matches[] = new int[npairs];
220 InsnTarget[] offsets = new InsnTarget[npairs];
221 for (int i=0; i<npairs; i++) {
222 matches[i] = insnEnv.getInt();
223 offsets[i] = insnEnv.getTarget(insnEnv.getInt() + myPC);
224 }
225 return new InsnLookupSwitch(defaultTarget, matches, offsets, myPC);
226 }
227 }