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