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  import java.io.PrintStream;
21  import java.util.Stack;
22  
23  /***
24   * An instruction which requires a integral constant as an immediate operand 
25   */
26  
27  public class InsnIntOp extends Insn {
28      /* The operand */
29      private int operandValue;
30  
31      /* public accessors */
32  
33      public int nStackArgs() {
34          return VMOp.ops[opcode()].nStackArgs();
35      }
36  
37      public int nStackResults() {
38          return VMOp.ops[opcode()].nStackResults();
39      }
40  
41      public String argTypes() {
42          return VMOp.ops[opcode()].argTypes();
43      }
44  
45      public String resultTypes() {
46          return VMOp.ops[opcode()].resultTypes();
47      }
48  
49      public boolean branches() {
50          return opcode() == opc_ret;
51      }
52  
53      public int value() {
54          return operandValue;
55      }
56  
57      /***
58       * Compares this instance with another for structural equality.
59       */
60      //@olsen: added method
61      public boolean isEqual(Stack msg, Object obj) {
62          if (!(obj instanceof InsnIntOp)) {
63              msg.push("obj/obj.getClass() = "
64                       + (obj == null ? null : obj.getClass()));
65              msg.push("this.getClass() = "
66                       + this.getClass());
67              return false;
68          }
69          InsnIntOp other = (InsnIntOp)obj;
70  
71          if (!super.isEqual(msg, other)) {
72              return false;
73          }
74  
75          if (this.operandValue != other.operandValue) {
76              msg.push(String.valueOf("operandValue = "
77                                      + other.operandValue));
78              msg.push(String.valueOf("operandValue = "
79                                      + this.operandValue));
80              return false;
81          }
82          return true;
83      }
84  
85      /* 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 */
86  
87      static String primType(int primIndex) {
88          switch (primIndex) {
89          case T_BOOLEAN:
90              return "boolean";
91          case T_CHAR:
92              return "char";
93          case T_FLOAT:
94              return "float";
95          case T_DOUBLE:
96              return "double";
97          case T_BYTE:
98              return "byte";
99          case T_SHORT:
100             return "short";
101         case T_INT:
102             return "int";
103         case T_LONG:
104             return "long";
105         default:
106             throw new InsnError ("Invalid primitive type(" + primIndex + ")");
107         }
108     }
109 
110     void print (PrintStream out, int indent) {
111         ClassPrint.spaces(out, indent);
112         if (opcode() == opc_newarray) 
113             out.println(offset() + "  opc_newarray  " + primType(operandValue));
114         else
115             out.println(offset() + "  " + opName(opcode()) + "  " + operandValue);
116     }
117 
118     int store(byte[] buf, int index) {
119         if (size() == 4) {
120             /* prefix with an opc_wide */
121             buf[index++] = (byte) opc_wide;
122         }
123 
124         buf[index++] = (byte) opcode();
125         if (size() > 2)
126             buf[index++] = (byte)(operandValue >> 8);
127         buf[index++] = (byte)(operandValue & 0xff);
128         return index;
129     }
130 
131 
132     /* return the size of the instruction in bytes */
133 
134     int size() {
135         switch(opcode()) {
136         case opc_bipush:
137         case opc_newarray:
138             /* These are always 1 byte constants */
139             return 2;
140 
141         case opc_sipush: /* a short constant */
142             /* This is always a 2 byte constant */
143             return 3;
144 
145         case opc_iload:
146         case opc_lload:
147         case opc_fload:
148         case opc_dload:
149         case opc_aload:
150         case opc_istore:
151         case opc_lstore:
152         case opc_fstore:
153         case opc_dstore:
154         case opc_astore:
155         case opc_ret:
156             /* These can be one or two byte constants specifying a local var.
157              * If a two byte constant, the constant is prefixed by a wide
158              * instruction */
159             if (operandValue < 256)
160                 return 2;
161             else
162                 return 4;
163 
164         default:
165             throw new InsnError ("invalid instruction " + opName(opcode()) +
166                                  " with an integer operand");
167         }
168     }
169 
170 
171     InsnIntOp (int theOpcode, int theOperand, int pc) {
172         super(theOpcode, pc);
173 
174         operandValue = theOperand;
175     }
176 
177 
178     InsnIntOp (int theOpcode, int theOperand) {
179         super(theOpcode, NO_OFFSET);
180 
181         operandValue = theOperand;
182         switch(theOpcode) {
183         case opc_bipush:
184         case opc_newarray:
185             /* These are always 1 byte constants */
186 
187         case opc_sipush: /* a short constant */
188             /* This is always a 2 byte constant */
189 
190         case opc_dload:
191         case opc_lload:
192         case opc_iload:
193         case opc_fload:
194         case opc_aload:
195         case opc_istore:
196         case opc_lstore:
197         case opc_fstore:
198         case opc_dstore:
199         case opc_astore:
200         case opc_ret:
201             /* These can be one or two byte constants specifying a local var */
202             break;
203 
204         default:
205             throw new InsnError ("attempt to create an " + opName(theOpcode) +
206                                  " with an integer operand");
207         }
208     }
209 }