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