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