View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software 
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License.
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      /* The constant from the constant pool */
31      private ConstBasic constValue;
32  
33      /* public accessors */
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              /* handle interface invoke too */
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              /* handle interface invoke too */
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             /* handle interface invoke too */
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             /* handle interface invoke too */
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         /* invokes don't count as a branch */
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     //@olsen: added method
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">/* package local methods *//package-summary.html">class="comment"> package local methods */
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     /* used only by InsnInterfaceInvoke, to make sure that opc_invokeinterface cannot
250      * come through the wrong path and miss its extra nArgsOp */
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             /* ConstValue */
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             /* ConstFieldRef */
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             /* ConstMethodRef */
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             /* ConstInterfaceMethodRef */
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             /* ConstClass */
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 }