View Javadoc

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