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