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 * An instruction which requires a single constant from the constant
26 * pool as an immediate operand
27 */
28 public class InsnConstOp extends Insn {
29
30 private ConstBasic constValue;
31
32
33
34 public int nStackArgs() {
35 int n = VMOp.ops[opcode()].nStackArgs();
36 if (n >= 0)
37 return n;
38 switch (opcode()) {
39 case opc_putstatic:
40 case opc_putfield:
41 {
42 ConstFieldRef fld = (ConstFieldRef) constValue;
43 String sig = fld.nameAndType().signature().asString();
44 if (sig.equals("J") || sig.equals("D"))
45 return (opcode() == opc_putfield) ? 3 : 2;
46 return (opcode() == opc_putfield) ? 2 : 1;
47 }
48 case opc_invokevirtual:
49 case opc_invokespecial:
50 case opc_invokestatic:
51
52 case opc_invokeinterface:
53 {
54 ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue;
55 String sig = meth.nameAndType().signature().asString();
56 int nMethodArgWords = Descriptor.countMethodArgWords(sig);
57 return nMethodArgWords +
58 ((opcode() == opc_invokestatic) ? 0 : 1);
59 }
60 default:
61 throw new InsnError("unexpected variable opcode");
62 }
63 }
64
65 public int nStackResults() {
66 int n = VMOp.ops[opcode()].nStackResults();
67 if (n >= 0)
68 return n;
69 switch (opcode()) {
70 case opc_getstatic:
71 case opc_getfield:
72 {
73 ConstFieldRef fld = (ConstFieldRef) constValue;
74 String sig = fld.nameAndType().signature().asString();
75 if (sig.equals("J") || sig.equals("D"))
76 return 2;
77 return 1;
78 }
79 case opc_invokevirtual:
80 case opc_invokespecial:
81 case opc_invokestatic:
82
83 case opc_invokeinterface:
84 {
85 ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue;
86 return Descriptor.countMethodReturnWords(
87 meth.nameAndType().signature().asString());
88 }
89 default:
90 throw new InsnError("unexpected variable opcode");
91 }
92 }
93
94 public String argTypes() {
95 switch (opcode()) {
96 case opc_putstatic:
97 case opc_putfield:
98 {
99 ConstFieldRef fld = (ConstFieldRef) constValue;
100 String sig = fld.nameAndType().signature().asString();
101 if (opcode() == opc_putstatic)
102 return sig;
103 else
104 return descriptorTypeOfObject(fld) + sig;
105 }
106 case opc_invokevirtual:
107 case opc_invokespecial:
108 case opc_invokestatic:
109
110 case opc_invokeinterface:
111 {
112 ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue;
113 String argSig =
114 Descriptor.extractArgSig(meth.nameAndType().signature().asString());
115 if (opcode() == opc_invokestatic)
116 return argSig;
117 else
118 return descriptorTypeOfObject(meth) + argSig;
119 }
120 default:
121 return VMOp.ops[opcode()].argTypes();
122 }
123 }
124
125 public String resultTypes() {
126 switch (opcode()) {
127 case opc_invokevirtual:
128 case opc_invokespecial:
129 case opc_invokestatic:
130
131 case opc_invokeinterface:
132 {
133 ConstBasicMemberRef meth = (ConstBasicMemberRef) constValue;
134 String resultSig = Descriptor.extractResultSig(
135 meth.nameAndType().signature().asString());
136 if (resultSig.equals("V"))
137 return "";
138 return resultSig;
139 }
140 case opc_getstatic:
141 case opc_getfield:
142 {
143 ConstFieldRef fld = (ConstFieldRef) constValue;
144 return fld.nameAndType().signature().asString();
145 }
146 case opc_ldc:
147 case opc_ldc_w:
148 case opc_ldc2_w:
149 {
150 ConstValue constVal = (ConstValue) constValue;
151 return constVal.descriptor();
152 }
153 default:
154 return VMOp.ops[opcode()].resultTypes();
155 }
156 }
157
158 public boolean branches() {
159
160 return false;
161 }
162
163 /***
164 * Return the constant pool entry which is the immediate operand
165 */
166 public ConstBasic value() {
167 return constValue;
168 }
169
170 /***
171 * Modify the referenced constant
172 */
173 public void setValue(ConstBasic newValue) {
174 checkConstant(newValue);
175 constValue = newValue;
176 }
177
178 /***
179 * Compares this instance with another for structural equality.
180 */
181
182 public boolean isEqual(Stack msg, Object obj) {
183 if (!(obj instanceof InsnConstOp)) {
184 msg.push("obj/obj.getClass() = "
185 + (obj == null ? null : obj.getClass()));
186 msg.push("this.getClass() = "
187 + this.getClass());
188 return false;
189 }
190 InsnConstOp other = (InsnConstOp)obj;
191
192 if (!super.isEqual(msg, other)) {
193 return false;
194 }
195
196 if (!this.constValue.isEqual(msg, other.constValue)) {
197 msg.push(String.valueOf("constValue = "
198 + other.constValue));
199 msg.push(String.valueOf("constValue = "
200 + this.constValue));
201 return false;
202 }
203 return true;
204 }
205
206 /* package local methods *//package-summary/html">class="comment"> package local methods *//package-summary.html">
207
208 void print(PrintStream out, int indent) {
209 ClassPrint.spaces(out, indent);
210 out.println(offset() + " " + opName(opcode()) + " pool(" +
211 constValue.getIndex() + ")");
212 }
213
214 int store(byte[] buf, int index) {
215 if (opcode() == opc_ldc && !isNarrowldc())
216 buf[index++] = (byte) opc_ldc_w;
217 else
218 buf[index++] = (byte) opcode();
219 int constIndex = constValue.getIndex();
220 if (size() == 3)
221 buf[index++] = (byte) (constIndex >> 8);
222 buf[index++] = (byte)(constIndex & 0xff);
223 return index;
224 }
225
226 int size() {
227 return isNarrowldc() ? 2 : 3;
228 }
229
230 private boolean isNarrowldc() {
231 return (opcode() == opc_ldc && constValue.getIndex() < 256);
232 }
233
234
235 InsnConstOp(int theOpcode, ConstBasic theOperand) {
236 this(theOpcode, theOperand, NO_OFFSET);
237 }
238
239 InsnConstOp(int theOpcode, ConstBasic theOperand, int pc) {
240 super(theOpcode, pc);
241 constValue = theOperand;
242 checkConstant(theOperand);
243 if (theOpcode == opc_invokeinterface)
244 throw new InsnError("attempt to create an " + opName(theOpcode) +
245 " as an InsnConstOp instead of InsnInterfaceInvoke");
246 }
247
248
249
250 InsnConstOp(int theOpcode, ConstInterfaceMethodRef theOperand, int pc) {
251 super(theOpcode, pc);
252 constValue = theOperand;
253 checkConstant(theOperand);
254 }
255
256 private void checkConstant(ConstBasic operand) {
257 switch(opcode()) {
258 case opc_ldc:
259 case opc_ldc_w:
260 case opc_ldc2_w:
261
262 if (operand == null ||
263 (! (operand instanceof ConstValue)))
264 throw new InsnError ("attempt to create an " + opName(opcode()) +
265 " without a ConstValue operand");
266 break;
267
268 case opc_getstatic:
269 case opc_putstatic:
270 case opc_getfield:
271 case opc_putfield:
272
273 if (operand == null ||
274 (! (operand instanceof ConstFieldRef)))
275 throw new InsnError ("attempt to create an " + opName(opcode()) +
276 " without a ConstFieldRef operand");
277 break;
278
279 case opc_invokevirtual:
280 case opc_invokespecial:
281 case opc_invokestatic:
282
283 if (operand == null ||
284 (! (operand instanceof ConstMethodRef)))
285 throw new InsnError ("attempt to create an " + opName(opcode()) +
286 " without a ConstMethodRef operand");
287 break;
288
289 case opc_invokeinterface:
290
291 if (operand == null ||
292 (! (operand instanceof ConstInterfaceMethodRef)))
293 throw new InsnError("Attempt to create an " + opName(opcode()) +
294 " without a ConstInterfaceMethodRef operand");
295 break;
296
297 case opc_new:
298 case opc_anewarray:
299 case opc_checkcast:
300 case opc_instanceof:
301
302 if (operand == null ||
303 (! (operand instanceof ConstClass)))
304 throw new InsnError ("attempt to create an " + opName(opcode()) +
305 " without a ConstClass operand");
306 break;
307
308 default:
309 throw new InsnError ("attempt to create an " + opName(opcode()) +
310 " with a constant operand");
311 }
312 }
313
314 private final String descriptorTypeOfObject(ConstBasicMemberRef memRef) {
315 String cname = memRef.className().className().asString();
316 return "L" + cname + ";";
317 }
318 }